diff --git a/Plane_Fighting/README.md b/Plane_Fighting/README.md
index 9b6df51..2e4232f 100644
--- a/Plane_Fighting/README.md
+++ b/Plane_Fighting/README.md
@@ -1,6 +1,12 @@
-# Plane Fighting
-## 一个跨平台的简易"飞机大战"程序
-## 基于 Python & PyGame 运行
-## 图标库来自 IconFont
-## 相应的版权归作者所有
-## 本目录中其他所有的文件根据 GPL 3.0 协议开源
+# Plane Fighting (plane_fighting)
+## 简介
+一个跨平台的简易"飞机大战"小游戏
+## 支持
+基于Python & PyGame 运行
+可通过 Buildozer 打包为移动应用
+## 协议
+图标库(./images/)来自 IconFont
+音效库(./sound/)来自网络
+字体库(./font)来自 Ubuntu
+相应的版权归作者所有
+本目录中其他所有的源代码文件根据 GPL 3.0 协议开源
\ No newline at end of file
diff --git a/Plane_Fighting/__pycache__/bullet.cpython-310.pyc b/Plane_Fighting/__pycache__/bullet.cpython-310.pyc
deleted file mode 100644
index a6cbdfd..0000000
Binary files a/Plane_Fighting/__pycache__/bullet.cpython-310.pyc and /dev/null differ
diff --git a/Plane_Fighting/__pycache__/enemy.cpython-310.pyc b/Plane_Fighting/__pycache__/enemy.cpython-310.pyc
deleted file mode 100644
index bbe5c60..0000000
Binary files a/Plane_Fighting/__pycache__/enemy.cpython-310.pyc and /dev/null differ
diff --git a/Plane_Fighting/__pycache__/myplane.cpython-310.pyc b/Plane_Fighting/__pycache__/myplane.cpython-310.pyc
deleted file mode 100644
index e1a1836..0000000
Binary files a/Plane_Fighting/__pycache__/myplane.cpython-310.pyc and /dev/null differ
diff --git a/Plane_Fighting/__pycache__/supply.cpython-310.pyc b/Plane_Fighting/__pycache__/supply.cpython-310.pyc
deleted file mode 100644
index bfd325b..0000000
Binary files a/Plane_Fighting/__pycache__/supply.cpython-310.pyc and /dev/null differ
diff --git a/Plane_Fighting/buildozer.spec b/Plane_Fighting/buildozer.spec
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/bullet.py b/Plane_Fighting/bullet.py
old mode 100755
new mode 100644
index 84ff6c3..eeb6641
--- a/Plane_Fighting/bullet.py
+++ b/Plane_Fighting/bullet.py
@@ -1,4 +1,5 @@
import pygame,os
+
abspath = os.getcwd() + "/"
class Bullet1(pygame.sprite.Sprite):
def __init__(self, position):
diff --git a/Plane_Fighting/enemy.py b/Plane_Fighting/enemy.py
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/font/font-2.ttf b/Plane_Fighting/font/font-2.ttf
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/font/font.ttf b/Plane_Fighting/font/font.ttf
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/again.png b/Plane_Fighting/images/again.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/background.png b/Plane_Fighting/images/background.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/bomb.png b/Plane_Fighting/images/bomb.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/bomb_supply.png b/Plane_Fighting/images/bomb_supply.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/bullet1.png b/Plane_Fighting/images/bullet1.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/bullet2.png b/Plane_Fighting/images/bullet2.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/bullet_supply.png b/Plane_Fighting/images/bullet_supply.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy1.png b/Plane_Fighting/images/enemy1.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy1_down1.png b/Plane_Fighting/images/enemy1_down1.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy1_down2.png b/Plane_Fighting/images/enemy1_down2.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy1_down3.png b/Plane_Fighting/images/enemy1_down3.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy1_down4.png b/Plane_Fighting/images/enemy1_down4.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy2.png b/Plane_Fighting/images/enemy2.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy2_down1.png b/Plane_Fighting/images/enemy2_down1.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy2_down2.png b/Plane_Fighting/images/enemy2_down2.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy2_down3.png b/Plane_Fighting/images/enemy2_down3.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy2_down4.png b/Plane_Fighting/images/enemy2_down4.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy2_hit.png b/Plane_Fighting/images/enemy2_hit.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_down1.png b/Plane_Fighting/images/enemy3_down1.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_down2.png b/Plane_Fighting/images/enemy3_down2.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_down3.png b/Plane_Fighting/images/enemy3_down3.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_down4.png b/Plane_Fighting/images/enemy3_down4.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_down5.png b/Plane_Fighting/images/enemy3_down5.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_down6.png b/Plane_Fighting/images/enemy3_down6.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_hit.png b/Plane_Fighting/images/enemy3_hit.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_n1.png b/Plane_Fighting/images/enemy3_n1.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/enemy3_n2.png b/Plane_Fighting/images/enemy3_n2.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/gameover.png b/Plane_Fighting/images/gameover.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/icon.png b/Plane_Fighting/images/icon.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/life.png b/Plane_Fighting/images/life.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/loading.png b/Plane_Fighting/images/loading.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/me1.png b/Plane_Fighting/images/me1.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/me2.png b/Plane_Fighting/images/me2.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/me_destroy_1.png b/Plane_Fighting/images/me_destroy_1.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/me_destroy_2.png b/Plane_Fighting/images/me_destroy_2.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/me_destroy_3.png b/Plane_Fighting/images/me_destroy_3.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/me_destroy_4.png b/Plane_Fighting/images/me_destroy_4.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/pause_nor.png b/Plane_Fighting/images/pause_nor.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/pause_pressed.png b/Plane_Fighting/images/pause_pressed.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/resume_nor.png b/Plane_Fighting/images/resume_nor.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/images/resume_pressed.png b/Plane_Fighting/images/resume_pressed.png
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/main.py b/Plane_Fighting/main.py
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/myplane.py b/Plane_Fighting/myplane.py
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/pyinstaller.spec b/Plane_Fighting/pyinstaller.spec
old mode 100755
new mode 100644
index a180fab..2d2c17f
--- a/Plane_Fighting/pyinstaller.spec
+++ b/Plane_Fighting/pyinstaller.spec
@@ -4,10 +4,10 @@
block_cipher = None
-a = Analysis(['main.py'],
+a = Analysis(['main.py','bullet.py','enemy.py','myplane.py','supply.py'],
pathex=[],
- binaries=[(‘./images/*.png’, ‘images’)]
- datas=[],
+ binaries=[("font", "images", "sound")]
+ datas=["record.dat"],
hiddenimports=[],
hookspath=[],
hooksconfig={},
@@ -26,7 +26,7 @@ exe = EXE(pyz,
a.zipfiles,
a.datas,
[],
- name='main',
+ name='Plane Fighting',
debug=False,
bootloader_ignore_signals=False,
strip=False,
diff --git a/Plane_Fighting/record.dat b/Plane_Fighting/record.dat
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/bullet.wav b/Plane_Fighting/sound/bullet.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/button.wav b/Plane_Fighting/sound/button.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/enemy1_down.wav b/Plane_Fighting/sound/enemy1_down.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/enemy2_down.wav b/Plane_Fighting/sound/enemy2_down.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/enemy3_down.wav b/Plane_Fighting/sound/enemy3_down.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/enemy3_flying.wav b/Plane_Fighting/sound/enemy3_flying.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/game_music.ogg b/Plane_Fighting/sound/game_music.ogg
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/get_bomb.wav b/Plane_Fighting/sound/get_bomb.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/get_bullet.wav b/Plane_Fighting/sound/get_bullet.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/loading_game.ogg b/Plane_Fighting/sound/loading_game.ogg
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/me_down.wav b/Plane_Fighting/sound/me_down.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/supply.wav b/Plane_Fighting/sound/supply.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/upgrade.wav b/Plane_Fighting/sound/upgrade.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/sound/use_bomb.wav b/Plane_Fighting/sound/use_bomb.wav
old mode 100755
new mode 100644
diff --git a/Plane_Fighting/supply.py b/Plane_Fighting/supply.py
old mode 100755
new mode 100644
index 2720dca..70d7986
--- a/Plane_Fighting/supply.py
+++ b/Plane_Fighting/supply.py
@@ -1,11 +1,12 @@
-import pygame
+import pygame,os
from random import *
+abspath = os.getcwd() + "/"
class Bullet_Supply(pygame.sprite.Sprite):
def __init__(self, bg_size):
pygame.sprite.Sprite.__init__(self)
- self.image = pygame.image.load("images/bullet_supply.png").convert_alpha()
+ self.image = pygame.image.load(abspath + "images/bullet_supply.png").convert_alpha()
self.rect = self.image.get_rect()
self.width, self.height = bg_size[0], bg_size[1]
self.rect.left, self.rect.bottom = \
@@ -29,7 +30,7 @@ class Bomb_Supply(pygame.sprite.Sprite):
def __init__(self, bg_size):
pygame.sprite.Sprite.__init__(self)
- self.image = pygame.image.load("images/bomb_supply.png").convert_alpha()
+ self.image = pygame.image.load(abspath + "images/bomb_supply.png").convert_alpha()
self.rect = self.image.get_rect()
self.width, self.height = bg_size[0], bg_size[1]
self.rect.left, self.rect.bottom = \
diff --git a/README.md b/README.md
index 5bfbb3d..8cdbca9 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,17 @@
-# 我的一些分散的代码文件
-# 主要用于通过 GitPod 在线编译
+# Tiny Project
+## 说明
+分散的代码文件
+一个文件夹代表一个小的代码集合
+不同文件夹所使用的开源协议不同
+有些工具虽然很小, 但却十分有用
+## 列表
+### 单目录 (root)
+|名称|路径|介绍|语言|
+|:---|:---|----|----|
+|LAN++|./lanpp|一个跨平台的简易局域网文件传输工具|Python|
+|Plane Fighting|./plane_fighting|一个跨平台的简易"飞机大战"小游戏|Python|
+|Python HTTPS Server|./python_https_server|一个 HTTPS 网络服务器程序|Python|
+### 单文件 (onefile)
+|文件名|介绍|语言|
+|----|----|----|
+|file_reader.cpp|输出文件内容至终端|C++|
\ No newline at end of file
diff --git a/lanpp/README.md b/lanpp/README.md
new file mode 100644
index 0000000..a8dff38
--- /dev/null
+++ b/lanpp/README.md
@@ -0,0 +1,10 @@
+# LAN++ (lanpp)
+## 简介
+一个跨平台的简易局域网文件传输工具
+## 支持
+基于 Python 语言编写
+底层依赖库: pyperclip & pyftpdlib
+UI 基于 Tkinter, 准备改写成 KivyMD
+将来可通过 Buildozer 打包为移动应用
+## 协议
+本目录中所有的源代码文件根据 GPL 3.0 协议开源
\ No newline at end of file
diff --git a/lanpp/ftpserver.py b/lanpp/ftpserver.py
new file mode 100644
index 0000000..031b46b
--- /dev/null
+++ b/lanpp/ftpserver.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from pyftpdlib.handlers import FTPHandler
+from pyftpdlib.servers import FTPServer
+from pyftpdlib.authorizers import DummyAuthorizer
+import json
+def jsonget(key_name):
+ with open("setting.json") as f:
+ json_data = f.read()
+ data = json.loads(json_data)
+ f.close()
+ return data[key_name]
+def start():
+ authorizer = DummyAuthorizer()
+ authorizer.add_user(jsonget("ftpserveruser"), jsonget("ftpserverpass"), jsonget("ftpserverroot"), perm='elradfmwM')
+ handler = FTPHandler
+ handler.authorizer = authorizer
+ server = FTPServer(('localhost', int(jsonget("ftpserverport"))), handler)
+ server.serve_forever()
+if __name__ == '__main__':
+ start()
\ No newline at end of file
diff --git a/lanpp/main-gui.py b/lanpp/main-gui.py
new file mode 100644
index 0000000..7bb9df0
--- /dev/null
+++ b/lanpp/main-gui.py
@@ -0,0 +1,142 @@
+import pyperclip
+import ftpserver
+import os
+import json
+import sys
+import socket
+import webserver
+import webbrowser
+from tkinter import *
+from tkinter import messagebox
+from ttkthemes import *
+from tkinter.ttk import *
+from multiprocessing import Process
+
+def getip():
+ try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.connect(('192.168.1.1', 0))
+ ip = s.getsockname()[0]
+ except:
+ ip = "localhost"
+ finally:
+ s.close()
+ return ip
+def jsonget(key_name):
+ with open("setting.json") as f:
+ json_data = f.read()
+ data = json.loads(json_data)
+ f.close()
+ return data[key_name]
+def webserver_ui():
+ if True :
+ #webserverui_status = 1
+ subwindow = ThemedTk(theme="yaru", toplevel=True, themebg=True)
+ subwindow.title("WebServer | LAN++ Manager")
+ subwindow.geometry("850x500")
+ os.chdir(static_path)
+ task = Process(target=webserver.start)
+ def start():
+ task.start()
+ print("started")
+ def __close__():
+ task.terminate()
+ os.chdir(static_path)
+ print("closed")
+ def close():
+ if task.is_alive() == False:
+ start()
+ __close__()
+ os.chdir(static_path)
+ subwindow.destroy()
+ def copylink():
+ pyperclip.copy("http://" + str(getip()) + ":" + jsonget("webserverport"))
+ ntext = " 点击按钮以控制[浏览器文件管理服务]\n [启动] - 启动服务\n [关闭窗口并退出] - 退出窗口(退出服务)\n [复制访问链接] - 复制链接以便访问服务" + '当前配置:\n 端口:' + jsonget("ftpserverport") + "\n 目录: " + jsonget("webserverroot") + "\n 打开服务后请用浏览器打开此链接以操作文件: [http://" + str(getip()) + ":" + jsonget("webserverport") + "]\n"
+ lbl1 = Label(subwindow, text=ntext)
+ lbl1.grid(column=1, row=1)
+ wtext = " 已知Bug:终止服务后,端口仍会占用一段时间,建议终止服务后一分钟后重新启动服务\n 注意:在不了解此程序文档时请勿打开多个相同服务,如需要,可在Wiki的[特技]一栏中找到方法."
+ lbl2 = Label(subwindow, text=wtext)
+ lbl2.grid(column=1, row=2)
+ start_btn = Button(subwindow, text="启动", command=start)
+ start_btn.grid(column=1, row=3)
+ close_btn = Button(subwindow, text="关闭窗口并退出", command=close)
+ close_btn.grid(column=1, row=4)
+ copy_btn = Button(subwindow, text="复制访问链接", command=copylink)
+ copy_btn.grid(column=1, row=5)
+ subwindow.protocol("WM_DELETE_WINDOW", close)
+ subwindow.mainloop()
+def ftpserver_ui():
+ if True :
+ #webserverui_status = 1
+ subwindow = ThemedTk(theme="yaru", toplevel=True, themebg=True)
+ subwindow.title("FTPServer | LAN++ Manager")
+ subwindow.geometry("850x500")
+ os.chdir(static_path)
+ task = Process(target=ftpserver.start)
+ def start():
+ task.start()
+ print("started")
+ def __close__():
+ task.terminate()
+ os.chdir(static_path)
+ print("closed")
+ def close():
+ if task.is_alive() == False:
+ start()
+ __close__()
+ os.chdir(static_path)
+ subwindow.destroy()
+ def copylink():
+ pyperclip.copy("ftp://" + jsonget("ftpserveruser") + "@" + str(getip()) + ":" + jsonget("ftpserverport"))
+ ntext = " 点击按钮以控制[FTP文件传输服务]\n [启动] - 启动服务\n [关闭窗口并退出] - 退出窗口(退出服务)\n [复制访问链接] - 复制链接以便访问服务" + '当前配置:\n 端口:' + jsonget("ftpserverport") + "\n 目录: " + jsonget("ftpserverroot") + "\n 用户名:" + jsonget("ftpserveruser") + "\n 密码:" + jsonget("ftpserverpass") + "\n 打开服务后请通过此链接连接FTP服务器: [ftp://" + jsonget("ftpserveruser") + "@" + str(getip()) + ":" + jsonget("ftpserverport") + "]"
+ lbl1 = Label(subwindow, text=ntext)
+ lbl1.grid(column=1, row=1)
+ wtext = " 已知Bug:终止服务后,端口仍会占用一段时间,建议终止服务后一分钟后重新启动服务\n 注意:在不了解此程序文档时请勿打开多个相同服务,如需要,可在Wiki的[特技]一栏中找到方法."
+ lbl2 = Label(subwindow, text=wtext)
+ lbl2.grid(column=1, row=2)
+ start_btn = Button(subwindow, text="启动", command=start)
+ start_btn.grid(column=1, row=3)
+ close_btn = Button(subwindow, text="关闭窗口并退出", command=close)
+ close_btn.grid(column=1, row=4)
+ copy_btn = Button(subwindow, text="复制访问链接", command=copylink)
+ copy_btn.grid(column=1, row=5)
+ subwindow.protocol("WM_DELETE_WINDOW", close)
+ subwindow.mainloop()
+def setting_ui():
+ pass
+def runexit():
+ sys.exit()
+def about_ui():
+ def visit():
+ webbrowser.open("http://github.com/david-ajax/LANPP", new=0)
+ subwindow = ThemedTk(theme="yaru", toplevel=True, themebg=True)
+ subwindow.title("About | LAN++")
+ subwindow.geometry("470x270")
+ ntext = " LAN++ -- A powerful tool for local area network \n Version: 1.0 (Beta) \n Repo: http://github.com/david-ajax/LANpp \n Powered By Wang Zhiyu \n Use GPL 3.0 License"
+ lbl1 = Label(subwindow, text=ntext)
+ lbl1.grid(column=1, row=1)
+ visit_btn = Button(subwindow, text="Visit The Repository", command=visit)
+ visit_btn.grid(column=1, row=2)
+ exit_btn = Button(subwindow, text="Exit", command=subwindow.destroy)
+ exit_btn.grid(column=1, row=3)
+def main():
+ window = ThemedTk(theme="yaru", toplevel=True, themebg=True)
+ window.title("LAN++ Manager")
+ window.geometry("800x200")
+ webserver = Button(window, text="浏览器文件管理服务", command=webserver_ui)
+ webserver.grid(column=0, row=2)
+ ftpserver = Button(window, text="FTP文件传输服务", command=ftpserver_ui)
+ ftpserver.grid(column=1, row=2)
+ setting = Button(window, text="设置", command=setting_ui)
+ setting.grid(column=2, row=2)
+ about = Button(window, text="关于", command=about_ui)
+ about.grid(column=3, row=2)
+ exit_btn = Button(window, text="退出", command=runexit)
+ exit_btn.grid(column=4, row=2)
+ window.mainloop()
+if __name__ == '__main__':
+ static_path = os.getcwd()
+ fw=Tk()
+ fw.withdraw()
+ messagebox.showinfo(title='Welcome',message='欢迎使用LAN++ Beta Edition')
+ main()
\ No newline at end of file
diff --git a/lanpp/setting.json b/lanpp/setting.json
new file mode 100644
index 0000000..6f30dc8
--- /dev/null
+++ b/lanpp/setting.json
@@ -0,0 +1,9 @@
+{
+ "webserverport": "8083",
+ "webserverroot": "/",
+ "ftpserverport": "8082",
+ "ftpserverroot": "/",
+ "ftpserveruser": "default",
+ "ftpserverpass": "000000",
+ "A Prompt For You": "Unless the program is not available,DO NOT EDIT THIS FILE"
+}
\ No newline at end of file
diff --git a/lanpp/webserver.py b/lanpp/webserver.py
new file mode 100644
index 0000000..484ed84
--- /dev/null
+++ b/lanpp/webserver.py
@@ -0,0 +1,326 @@
+#!/usr/bin/env python3
+
+"""
+Powered by "Simple HTTP Server With Upload."
+https://gist.github.com/UniIsland/3346170
+"""
+
+
+__version__ = "1.0"
+__all__ = ["SimpleHTTPRequestHandler"]
+__author__ = "bones7456"
+__home_page__ = "https://gist.github.com/UniIsland/3346170"
+import getpass
+import os
+import posixpath
+import http.server
+import socketserver
+import urllib.request, urllib.parse, urllib.error
+import html
+import shutil
+import mimetypes
+import re
+import argparse
+import base64
+from io import BytesIO
+import json
+
+def jsonget(key_name):
+ with open("setting.json") as f:
+ json_data = f.read()
+ data = json.loads(json_data)
+ f.close()
+ return data[key_name]
+def start():
+ theport = int(jsonget('webserverport'))
+ os.chdir(jsonget('webserverroot'))
+ class SimpleHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
+
+ """Simple HTTP request handler with GET/HEAD/POST commands.
+
+ This serves files from the current directory and any of its
+ subdirectories. The MIME type for files is determined by
+ calling the .guess_type() method. And can reveive file uploaded
+ by client.
+
+ The GET/HEAD/POST requests are identical except that the HEAD
+ request omits the actual contents of the file.
+
+ """
+
+ server_version = "SimpleHTTPWithUpload/" + __version__
+
+ def do_GET(self):
+ """Serve a GET request."""
+ f = self.send_head()
+ if f:
+ self.copyfile(f, self.wfile)
+ f.close()
+
+ def do_HEAD(self):
+ """Serve a HEAD request."""
+ f = self.send_head()
+ if f:
+ f.close()
+
+ def do_POST(self):
+ """Serve a POST request."""
+ r, info = self.deal_post_data()
+ print((r, info, "by: ", self.client_address))
+ f = BytesIO()
+ f.write(b'')
+ f.write(b"\n
\xe4\xb8\x8a\xe4\xbc\xa0\xe7\xbb\x93\xe6\x9e\x9c\xe9\xa1\xb5\xe9\x9d\xa2\n")
+ f.write(b"\n\xe4\xb8\x8a\xe4\xbc\xa0\xe7\xbb\x93\xe6\x9e\x9c\xe9\xa1\xb5\xe9\x9d\xa2
\n")
+ f.write(b"
\n")
+ if r:
+ f.write(b"\xe6\x88\x90\xe5\x8a\x9f:")
+ else:
+ f.write(b"\xe5\xa4\xb1\xe8\xb4\xa5:")
+ f.write(info.encode())
+ f.write(("
返回" % self.headers['referer']).encode())
+ f.write(b"
\xe4\xbb\xa5LAN++\xe4\xb8\xba\xe9\xa9\xb1\xe5\x8a\xa8 | \xe6\xba\x90\xe4\xbb\xa3\xe7\xa0\x81\xe5\x8f\x96\xe8\x87\xaabones7456")
+ f.write(b'
')
+ f.write(b"\xe5\xae\x98\xe6\x96\xb9\xe7\xbd\x91\xe7\xab\x99.\n\n")
+ length = f.tell()
+ f.seek(0)
+ self.send_response(200)
+ self.send_header("Content-type", "text/html")
+ self.send_header("Content-Length", str(length))
+ self.end_headers()
+ if f:
+ self.copyfile(f, self.wfile)
+ f.close()
+
+ def deal_post_data(self):
+ uploaded_files = []
+ content_type = self.headers['content-type']
+ if not content_type:
+ return (False, "内容类型头不含有边界")
+ boundary = content_type.split("=")[1].encode()
+ remainbytes = int(self.headers['content-length'])
+ line = self.rfile.readline()
+ remainbytes -= len(line)
+ if not boundary in line:
+ return (False, "内容没有边界")
+ while remainbytes > 0:
+ line = self.rfile.readline()
+ remainbytes -= len(line)
+ fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line.decode())
+ if not fn:
+ return (False, "无法获取文件名...")
+ path = self.translate_path(self.path)
+ fn = os.path.join(path, fn[0])
+ line = self.rfile.readline()
+ remainbytes -= len(line)
+ line = self.rfile.readline()
+ remainbytes -= len(line)
+ try:
+ out = open(fn, 'wb')
+ except IOError:
+ return (False, "无法写入文件
您是否以足够的权限运行LAN++及其组件?您是否选择了文件以上传?")
+ else:
+ with out:
+ preline = self.rfile.readline()
+ remainbytes -= len(preline)
+ while remainbytes > 0:
+ line = self.rfile.readline()
+ remainbytes -= len(line)
+ if boundary in line:
+ preline = preline[0:-1]
+ if preline.endswith(b'\r'):
+ preline = preline[0:-1]
+ out.write(preline)
+ uploaded_files.append(fn)
+ break
+ else:
+ out.write(preline)
+ preline = line
+ return (True, "文件 '%s' 上传成功" % ",".join(uploaded_files))
+
+ def send_head(self):
+ path = self.translate_path(self.path)
+ f = None
+ if os.path.isdir(path):
+ if not self.path.endswith('/'):
+ # redirect browser - doing basically what apache does
+ self.send_response(301)
+ self.send_header("Location", self.path + "/")
+ self.end_headers()
+ return None
+ for index in "index.html", "index.htm":
+ index = os.path.join(path, index)
+ if os.path.exists(index):
+ path = index
+ break
+ else:
+ return self.list_directory(path)
+ ctype = self.guess_type(path)
+ try:
+ # Always read in binary mode. Opening files in text mode may cause
+ # newline translations, making the actual size of the content
+ # transmitted *less* than the content-length!
+ f = open(path, 'rb')
+ except IOError:
+ self.send_error(404, "没有找到文件 错误码:404")
+ return None
+ self.send_response(200)
+ self.send_header("Content-type", ctype)
+ fs = os.fstat(f.fileno())
+ self.send_header("Content-Length", str(fs[6]))
+ self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
+ self.end_headers()
+ return f
+
+ def list_directory(self, path):
+ try:
+ list = os.listdir(path)
+ except os.error:
+ self.send_error(404, "No permission to list directory")
+ return None
+ list.sort(key=lambda a: a.lower())
+ f = BytesIO()
+ displaypath = html.escape(urllib.parse.unquote(self.path))
+ f.write(b'')
+ f.write(("\n此目录下的文件列表: %s\n" % displaypath).encode())
+ f.write(b'\n')
+ f.write(("\n此目录下的文件列表:" + displaypath + "2>
注意:
1:您当前以[" + getpass.getuser() + "]用户查看文件(您或许对某些文件没有查看权限)
2:选择文件上传后,如文件较大,请只点击一次按钮直到页面刷新
").encode())
+ f.write(b"
\n")
+ f.write(b"
\n")
+ f.write(b"
\n")
+ f.write(b'
\xe8\xbf\x94\xe5\x9b\x9e\xe7\x88\xb6\xe7\x9b\xae\xe5\xbd\x95
\n')
+ for name in list:
+ dirimage = 'data:image/png;base64,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BICE5bt8nsfjYdW9qQIgACQ8rM65a4jokvAO0VcCEAAyXUidc78moqOn6xJtNQABINOFM0mS1cz8y+m6RFsNQADI9OFct27dKw4cOFD8BE/Vzxemn7SdDgAEgOglLUmST5WfjawmouV6nTvrBEAAiH74Nm3a9JK9e/ces7S0dJR+d5WOxZmueDjPpAOAAJBJGbH3unOueGoVACm21jknVbYYNytWccnGGADyvH0EIDZCrakCgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAARDNP5noBEABiLtSaggAIANHMk7leAASAmAu1piAAAkA082SuFwABIOZCrSkIgAAQzTyZ6wVAAIi5UGsKAiAvBOSvRHTkJIOZ+U1pmu6cNA6v998B59y3iGjrJCXMfFGapjdMGqf5Oms2q9LLOfcoEa2ZNJaZz03T9KZJ4/B6/x1wzu0hotdPUiIiZ2VZ9rVJ4zRf7wKQHxHRWyuIeNh7v7HCOAzpsQNJklzAzFXPCid77x9oU24XgFxBRJdXFHmL9/7simMxrIcOOOf2E9HyKktfXFw8bGFh4ekqY7XGtA7I/Pz8hjzPH6ohYLP3/p4a4zG0Bw4Mh8MjROReItpQZbki8o0sy86sMlZzTOuAFIt3zu0mouNqCLk2z/OvjsfjXTVqMDRCB5xzxd8aJxPR52su7zzv/Rdq1kw9vCtALiWiqwJW/xQRFXDtC6hFSfcOvIGIVtVdhogsMPMG7/2f69ZOO74TQFavXv2ylStXPkxEx08rAPX2HWDmS9I0va4LpZ0AUl5mnRdwmu3CI8zZrQM/X7FixYadO3ce6GIZnQFSiE2SZDszn9GFcMzZGwc6fZOmU0DKM8nvieg1vdkuLLQ1B5j5wjRNP9fahP9nos4BKSF5kIjwoWCXSYhv7vO99zd2vawoACkhuYSIrunaEMzfuQO/Y+b3pGm6o/OVEFE0gBRmDIfDLSJSvAV8QgzmYA3tOiAity9btuyTo9HItzvzoWeLCpBimRs3bjxs3759BSTFfzhmw4HiEvta731xV29UR3SAHHQnSZLVzHyqiJxa/D8q17AYDQf+RkR3DQaDO0ej0V0aDZvoES0g/y322GOPPXLlypUvX1paOpKZK93c1oRh6BnuwGAweHL//v1PPPvss0/s2bPnyfBO7VX2BpD2LMFMcOA/DgAQpAEOvIgDAATxgAMABBmAA2EO4AwS5huqZsQBADIjGw2ZYQ4AkDDfUDUjDgCQGdloyAxzAICE+YaqGXEAgMzIRkNmmAMAJMw3VM2IAwBkRjYaMsMc+BeLyV0yKtmxMAAAAABJRU5ErkJggg=='
+ fullname = os.path.join(path, name)
+ displayname = linkname = name
+ # Append / for directories or @ for symbolic links
+ if os.path.isdir(fullname):
+ dirimage = 'data:image/png;base64,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'
+ displayname = name + "/"
+ linkname = name + "/"
+ if os.path.islink(fullname):
+ dirimage = 'data:image/png;base64,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'
+ displayname = name + "@"
+ if name.endswith(('.bmp','.gif','.jpg','.png')):
+ dirimage = 'data:image/png;base64,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'
+ if name.endswith(('.avi','.mpg')):
+ dirimage = 'data:image/png;base64,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'
+ if name.endswith(('.idx','.srt','.sub')):
+ dirimage = name
+ if name.endswith('.iso'):
+ dirimage = name
+ # Note: a link to a directory displays with @ and links with /
+ f.write(('
%s
\n'
+ % (urllib.parse.quote(linkname), dirimage , html.escape(displayname))).encode())
+ f.write(b"
\n\n\n")
+ length = f.tell()
+ f.seek(0)
+ self.send_response(200)
+ self.send_header("Content-type", "text/html")
+ self.send_header("Content-Length", str(length))
+ self.end_headers()
+ return f
+
+ def translate_path(self, path):
+ """Translate a /-separated PATH to the local filename syntax.
+ Components that mean special things to the local file system
+ (e.g. drive or directory names) are ignored. (XXX They should
+ probably be diagnosed.)
+
+ """
+ # abandon query parameters
+ path = path.split('?',1)[0]
+ path = path.split('#',1)[0]
+ path = posixpath.normpath(urllib.parse.unquote(path))
+ words = path.split('/')
+ words = [_f for _f in words if _f]
+ path = os.getcwd()
+ for word in words:
+ drive, word = os.path.splitdrive(word)
+ head, word = os.path.split(word)
+ if word in (os.curdir, os.pardir): continue
+ path = os.path.join(path, word)
+ return path
+
+ def copyfile(self, source, outputfile):
+ """Copy all data between two file objects.
+
+ The SOURCE argument is a file object open for reading
+ (or anything with a read() method) and the DESTINATION
+ argument is a file object open for writing (or
+ anything with a write() method).
+
+ The only reason for overriding this would be to change
+ the block size or perhaps to replace newlines by CRLF
+ -- note however that this the default server uses this
+ to copy binary data as well.
+
+ """
+ shutil.copyfileobj(source, outputfile)
+
+ def guess_type(self, path):
+ """Guess the type of a file.
+
+ Argument is a PATH (a filename).
+
+ Return value is a string of the form type/subtype,
+ usable for a MIME Content-type header.
+
+ The default implementation looks the file's extension
+ up in the table self.extensions_map, using application/octet-stream
+ as a default; however it would be permissible (if
+ slow) to look inside the data to make a better guess.
+
+ """
+
+ base, ext = posixpath.splitext(path)
+ if ext in self.extensions_map:
+ return self.extensions_map[ext]
+ ext = ext.lower()
+ if ext in self.extensions_map:
+ return self.extensions_map[ext]
+ else:
+ return self.extensions_map['']
+
+ if not mimetypes.inited:
+ mimetypes.init() # try to read system mime.types
+ extensions_map = mimetypes.types_map.copy()
+ extensions_map.update({
+ '': 'application/octet-stream', # Default
+ '.py': 'text/plain',
+ '.c': 'text/plain',
+ '.h': 'text/plain',
+ })
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
+ help='Specify alternate bind address '
+ '[default: all interfaces]')
+ parser.add_argument('port', action='store',
+ default=theport, type=int,
+ nargs='?',
+ help='Specify alternate port [default:' + str(theport) + ']')
+ args = parser.parse_args()
+
+ PORT = args.port
+ BIND = args.bind
+ HOST = BIND
+
+ if HOST == '':
+ HOST = 'localhost'
+
+ Handler = SimpleHTTPRequestHandler
+
+ with socketserver.TCPServer((BIND, PORT), Handler) as httpd:
+ serve_message = "[Webserver - 1.0]\nServing HTTP on {host} port {port} (http://{host}:{port}/) ..."
+ print(serve_message.format(host=HOST, port=PORT))
+ httpd.serve_forever()
+if __name__ == "__main__":
+ start()
\ No newline at end of file
diff --git a/onefile/README.md b/onefile/README.md
new file mode 100644
index 0000000..8a9dc32
--- /dev/null
+++ b/onefile/README.md
@@ -0,0 +1,9 @@
+# 单文件 (onefile)
+## 简介
+单文件小程序
+## 支持
+每个文件都是一个不同的程序
+请分别根据注释运行
+## 协议
+详见文件内部注释
+如无注释, 根据 GPL 3.0 协议开源
diff --git a/onefile/file_reader.cpp b/onefile/file_reader.cpp
new file mode 100644
index 0000000..944e1f1
--- /dev/null
+++ b/onefile/file_reader.cpp
@@ -0,0 +1,31 @@
+// main.cpp
+// author: Wang Zhiyu
+// SFIS C++ Project
+#include
+using namespace std;
+
+int main(int argc, char *argv[]){
+ fstream config;
+ config.open(argv[1], ios::in);
+ if(config){
+ cout << "Reading Data" << endl;
+ vector data;
+ string tmp;
+ while(getline(config,tmp)){
+ data.push_back(tmp);
+ }
+ cout << "Redirect to terminal:" << endl;
+ for(int i = 0;i < data.size();i++){
+ cout << data[i] << endl;
+ }
+ config.close();
+ }
+ else{
+ cout << "File NOT Found" << endl;
+ }
+ cout << "Press any key to Continue...";
+ cin.clear();
+ cin.sync();
+ cin.get();
+ return 0;
+}
diff --git a/plane_fighting/README.md b/plane_fighting/README.md
new file mode 100644
index 0000000..2e4232f
--- /dev/null
+++ b/plane_fighting/README.md
@@ -0,0 +1,12 @@
+# Plane Fighting (plane_fighting)
+## 简介
+一个跨平台的简易"飞机大战"小游戏
+## 支持
+基于Python & PyGame 运行
+可通过 Buildozer 打包为移动应用
+## 协议
+图标库(./images/)来自 IconFont
+音效库(./sound/)来自网络
+字体库(./font)来自 Ubuntu
+相应的版权归作者所有
+本目录中其他所有的源代码文件根据 GPL 3.0 协议开源
\ No newline at end of file
diff --git a/plane_fighting/buildozer.spec b/plane_fighting/buildozer.spec
new file mode 100644
index 0000000..665c3ea
--- /dev/null
+++ b/plane_fighting/buildozer.spec
@@ -0,0 +1,427 @@
+[app]
+
+# (str) Title of your application
+title = Plane Fighting
+
+# (str) Package name
+package.name = plane_fighting
+
+# (str) Package domain (needed for android/ios packaging)
+package.domain = ga.imwangzhiyu
+
+# (str) Source code where the main.py live
+source.dir = .
+
+# (list) Source files to include (let empty to include all the files)
+source.include_exts = py,png,ogg,wav,ttf,dat
+
+# (list) List of inclusions using pattern matching
+source.include_patterns = font/*,sound/*,images/*,record.dat
+
+# (list) Source files to exclude (let empty to not exclude anything)
+#source.exclude_exts = spec
+
+# (list) List of directory to exclude (let empty to not exclude anything)
+#source.exclude_dirs = tests, bin, venv
+
+# (list) List of exclusions using pattern matching
+# Do not prefix with './'
+#source.exclude_patterns = license,images/*/*.jpg
+
+# (str) Application versioning (method 1)
+version = 0.1
+
+# (str) Application versioning (method 2)
+# version.regex = __version__ = ['"](.*)['"]
+# version.filename = %(source.dir)s/main.py
+
+# (list) Application requirements
+# comma separated e.g. requirements = sqlite3,kivy
+requirements = python3,pygame
+
+# (str) Custom source folders for requirements
+# Sets custom source for any requirements with recipes
+# requirements.source.kivy = ../../kivy
+
+# (str) Presplash of the application
+#presplash.filename = %(source.dir)s/data/presplash.png
+
+# (str) Icon of the application
+icon.filename = %(source.dir)s/images/icon.png
+
+# (str) Supported orientation (one of landscape, sensorLandscape, portrait or all)
+orientation = portrait
+
+# (list) List of service to declare
+#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
+
+#
+# OSX Specific
+#
+
+#
+# author = © Copyright Info
+
+# change the major version of python used by the app
+osx.python_version = 3
+
+# Kivy version to use
+osx.kivy_version = 1.9.1
+
+#
+# Android specific
+#
+
+# (bool) Indicate if the application should be fullscreen or not
+fullscreen = 0
+
+# (string) Presplash background color (for android toolchain)
+# Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
+# red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
+# darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
+# olive, purple, silver, teal.
+#android.presplash_color = #FFFFFF
+
+# (string) Presplash animation using Lottie format.
+# see https://lottiefiles.com/ for examples and https://airbnb.design/lottie/
+# for general documentation.
+# Lottie files can be created using various tools, like Adobe After Effect or Synfig.
+#android.presplash_lottie = "path/to/lottie/file.json"
+
+# (str) Adaptive icon of the application (used if Android API level is 26+ at runtime)
+#icon.adaptive_foreground.filename = %(source.dir)s/data/icon_fg.png
+#icon.adaptive_background.filename = %(source.dir)s/data/icon_bg.png
+
+# (list) Permissions
+#android.permissions = INTERNET
+
+# (list) features (adds uses-feature -tags to manifest)
+#android.features = android.hardware.usb.host
+
+# (int) Target Android API, should be as high as possible.
+#android.api = 27
+
+# (int) Minimum API your APK / AAB will support.
+#android.minapi = 21
+
+# (int) Android SDK version to use
+#android.sdk = 20
+
+# (str) Android NDK version to use
+#android.ndk = 19b
+
+# (int) Android NDK API to use. This is the minimum API your app will support, it should usually match android.minapi.
+#android.ndk_api = 21
+
+# (bool) Use --private data storage (True) or --dir public storage (False)
+#android.private_storage = True
+
+# (str) Android NDK directory (if empty, it will be automatically downloaded.)
+#android.ndk_path =
+
+# (str) Android SDK directory (if empty, it will be automatically downloaded.)
+#android.sdk_path =
+
+# (str) ANT directory (if empty, it will be automatically downloaded.)
+#android.ant_path =
+
+# (bool) If True, then skip trying to update the Android sdk
+# This can be useful to avoid excess Internet downloads or save time
+# when an update is due and you just want to test/build your package
+# android.skip_update = False
+
+# (bool) If True, then automatically accept SDK license
+# agreements. This is intended for automation only. If set to False,
+# the default, you will be shown the license when first running
+# buildozer.
+# android.accept_sdk_license = False
+
+# (str) Android entry point, default is ok for Kivy-based app
+#android.entrypoint = org.kivy.android.PythonActivity
+
+# (str) Full name including package path of the Java class that implements Android Activity
+# use that parameter together with android.entrypoint to set custom Java class instead of PythonActivity
+#android.activity_class_name = org.kivy.android.PythonActivity
+
+# (str) Extra xml to write directly inside the element of AndroidManifest.xml
+# use that parameter to provide a filename from where to load your custom XML code
+#android.extra_manifest_xml = ./src/android/extra_manifest.xml
+
+# (str) Extra xml to write directly inside the tag of AndroidManifest.xml
+# use that parameter to provide a filename from where to load your custom XML arguments:
+#android.extra_manifest_application_arguments = ./src/android/extra_manifest_application_arguments.xml
+
+# (str) Full name including package path of the Java class that implements Python Service
+# use that parameter to set custom Java class instead of PythonService
+#android.service_class_name = org.kivy.android.PythonService
+
+# (str) Android app theme, default is ok for Kivy-based app
+# android.apptheme = "@android:style/Theme.NoTitleBar"
+
+# (list) Pattern to whitelist for the whole project
+#android.whitelist =
+
+# (str) Path to a custom whitelist file
+#android.whitelist_src =
+
+# (str) Path to a custom blacklist file
+#android.blacklist_src =
+
+# (list) List of Java .jar files to add to the libs so that pyjnius can access
+# their classes. Don't add jars that you do not need, since extra jars can slow
+# down the build process. Allows wildcards matching, for example:
+# OUYA-ODK/libs/*.jar
+#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
+
+# (list) List of Java files to add to the android project (can be java or a
+# directory containing the files)
+#android.add_src =
+
+# (list) Android AAR archives to add
+#android.add_aars =
+
+# (list) Put these files or directories in the apk assets directory.
+# Either form may be used, and assets need not be in 'source.include_exts'.
+# 1) android.add_assets = source_asset_relative_path
+# 2) android.add_assets = source_asset_path:destination_asset_relative_path
+#android.add_assets =
+
+# (list) Gradle dependencies to add
+#android.gradle_dependencies =
+
+# (bool) Enable AndroidX support. Enable when 'android.gradle_dependencies'
+# contains an 'androidx' package, or any package from Kotlin source.
+# android.enable_androidx requires android.api >= 28
+#android.enable_androidx = False
+
+# (list) add java compile options
+# this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option
+# see https://developer.android.com/studio/write/java8-support for further information
+# android.add_compile_options = "sourceCompatibility = 1.8", "targetCompatibility = 1.8"
+
+# (list) Gradle repositories to add {can be necessary for some android.gradle_dependencies}
+# please enclose in double quotes
+# e.g. android.gradle_repositories = "maven { url 'https://kotlin.bintray.com/ktor' }"
+#android.add_gradle_repositories =
+
+# (list) packaging options to add
+# see https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html
+# can be necessary to solve conflicts in gradle_dependencies
+# please enclose in double quotes
+# e.g. android.add_packaging_options = "exclude 'META-INF/common.kotlin_module'", "exclude 'META-INF/*.kotlin_module'"
+#android.add_packaging_options =
+
+# (list) Java classes to add as activities to the manifest.
+#android.add_activities = com.example.ExampleActivity
+
+# (str) OUYA Console category. Should be one of GAME or APP
+# If you leave this blank, OUYA support will not be enabled
+#android.ouya.category = GAME
+
+# (str) Filename of OUYA Console icon. It must be a 732x412 png image.
+#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
+
+# (str) XML file to include as an intent filters in tag
+#android.manifest.intent_filters =
+
+# (str) launchMode to set for the main activity
+#android.manifest.launch_mode = standard
+
+# (list) Android additional libraries to copy into libs/armeabi
+#android.add_libs_armeabi = libs/android/*.so
+#android.add_libs_armeabi_v7a = libs/android-v7/*.so
+#android.add_libs_arm64_v8a = libs/android-v8/*.so
+#android.add_libs_x86 = libs/android-x86/*.so
+#android.add_libs_mips = libs/android-mips/*.so
+
+# (bool) Indicate whether the screen should stay on
+# Don't forget to add the WAKE_LOCK permission if you set this to True
+#android.wakelock = False
+
+# (list) Android application meta-data to set (key=value format)
+#android.meta_data =
+
+# (list) Android library project to add (will be added in the
+# project.properties automatically.)
+#android.library_references =
+
+# (list) Android shared libraries which will be added to AndroidManifest.xml using tag
+#android.uses_library =
+
+# (str) Android logcat filters to use
+#android.logcat_filters = *:S python:D
+
+# (bool) Android logcat only display log for activity's pid
+#android.logcat_pid_only = False
+
+# (str) Android additional adb arguments
+#android.adb_args = -H host.docker.internal
+
+# (bool) Copy library instead of making a libpymodules.so
+#android.copy_libs = 1
+
+# (list) The Android archs to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
+# In past, was `android.arch` as we weren't supporting builds for multiple archs at the same time.
+android.archs = arm64-v8a, armeabi-v7a
+
+# (int) overrides automatic versionCode computation (used in build.gradle)
+# this is not the same as app version and should only be edited if you know what you're doing
+# android.numeric_version = 1
+
+# (bool) enables Android auto backup feature (Android API >=23)
+android.allow_backup = True
+
+# (str) XML file for custom backup rules (see official auto backup documentation)
+# android.backup_rules =
+
+# (str) If you need to insert variables into your AndroidManifest.xml file,
+# you can do so with the manifestPlaceholders property.
+# This property takes a map of key-value pairs. (via a string)
+# Usage example : android.manifest_placeholders = [myCustomUrl:\"org.kivy.customurl\"]
+# android.manifest_placeholders = [:]
+
+# (bool) disables the compilation of py to pyc/pyo files when packaging
+# android.no-compile-pyo = True
+
+# (str) The format used to package the app for release mode (aab or apk).
+# android.release_artifact = aab
+
+#
+# Python for android (p4a) specific
+#
+
+# (str) python-for-android URL to use for checkout
+#p4a.url =
+
+# (str) python-for-android fork to use in case if p4a.url is not specified, defaults to upstream (kivy)
+#p4a.fork = kivy
+
+# (str) python-for-android branch to use, defaults to master
+#p4a.branch = master
+
+# (str) python-for-android specific commit to use, defaults to HEAD, must be within p4a.branch
+#p4a.commit = HEAD
+
+# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
+#p4a.source_dir =
+
+# (str) The directory in which python-for-android should look for your own build recipes (if any)
+#p4a.local_recipes =
+
+# (str) Filename to the hook for p4a
+#p4a.hook =
+
+# (str) Bootstrap to use for android builds
+# p4a.bootstrap = sdl2
+
+# (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask)
+#p4a.port =
+
+# Control passing the --use-setup-py vs --ignore-setup-py to p4a
+# "in the future" --use-setup-py is going to be the default behaviour in p4a, right now it is not
+# Setting this to false will pass --ignore-setup-py, true will pass --use-setup-py
+# NOTE: this is general setuptools integration, having pyproject.toml is enough, no need to generate
+# setup.py if you're using Poetry, but you need to add "toml" to source.include_exts.
+#p4a.setup_py = false
+
+# (str) extra command line arguments to pass when invoking pythonforandroid.toolchain
+#p4a.extra_args =
+
+
+#
+# iOS specific
+#
+
+# (str) Path to a custom kivy-ios folder
+#ios.kivy_ios_dir = ../kivy-ios
+# Alternately, specify the URL and branch of a git checkout:
+ios.kivy_ios_url = https://github.com/kivy/kivy-ios
+ios.kivy_ios_branch = master
+
+# Another platform dependency: ios-deploy
+# Uncomment to use a custom checkout
+#ios.ios_deploy_dir = ../ios_deploy
+# Or specify URL and branch
+ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
+ios.ios_deploy_branch = 1.10.0
+
+# (bool) Whether or not to sign the code
+ios.codesign.allowed = false
+
+# (str) Name of the certificate to use for signing the debug version
+# Get a list of available identities: buildozer ios list_identities
+#ios.codesign.debug = "iPhone Developer: ()"
+
+# (str) The development team to use for signing the debug version
+#ios.codesign.development_team.debug =
+
+# (str) Name of the certificate to use for signing the release version
+#ios.codesign.release = %(ios.codesign.debug)s
+
+# (str) The development team to use for signing the release version
+#ios.codesign.development_team.release =
+
+# (str) URL pointing to .ipa file to be installed
+# This option should be defined along with `display_image_url` and `full_size_image_url` options.
+#ios.manifest.app_url =
+
+# (str) URL pointing to an icon (57x57px) to be displayed during download
+# This option should be defined along with `app_url` and `full_size_image_url` options.
+#ios.manifest.display_image_url =
+
+# (str) URL pointing to a large icon (512x512px) to be used by iTunes
+# This option should be defined along with `app_url` and `display_image_url` options.
+#ios.manifest.full_size_image_url =
+
+
+[buildozer]
+
+# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
+log_level = 2
+
+# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
+warn_on_root = 1
+
+# (str) Path to build artifact storage, absolute or relative to spec file
+# build_dir = ./.buildozer
+
+# (str) Path to build output (i.e. .apk, .aab, .ipa) storage
+# bin_dir = ./bin
+
+# -----------------------------------------------------------------------------
+# List as sections
+#
+# You can define all the "list" as [section:key].
+# Each line will be considered as a option to the list.
+# Let's take [app] / source.exclude_patterns.
+# Instead of doing:
+#
+#[app]
+#source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
+#
+# This can be translated into:
+#
+#[app:source.exclude_patterns]
+#license
+#data/audio/*.wav
+#data/images/original/*
+#
+
+
+# -----------------------------------------------------------------------------
+# Profiles
+#
+# You can extend section / key with a profile
+# For example, you want to deploy a demo version of your application without
+# HD content. You could first change the title to add "(demo)" in the name
+# and extend the excluded directories to remove the HD content.
+#
+#[app@demo]
+#title = My Application (demo)
+#
+#[app:source.exclude_patterns@demo]
+#images/hd/*
+#
+# Then, invoke the command line with the "demo" profile:
+#
+#buildozer --profile demo android debug
diff --git a/plane_fighting/bullet.py b/plane_fighting/bullet.py
new file mode 100644
index 0000000..eeb6641
--- /dev/null
+++ b/plane_fighting/bullet.py
@@ -0,0 +1,45 @@
+import pygame,os
+
+abspath = os.getcwd() + "/"
+class Bullet1(pygame.sprite.Sprite):
+ def __init__(self, position):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.image = pygame.image.load(abspath + "images/bullet1.png").convert_alpha()
+ self.rect = self.image.get_rect()
+ self.rect.left, self.rect.top = position
+ self.speed = 11
+ self.active = False
+ self.mask = pygame.mask.from_surface(self.image)
+
+ def move(self):
+ self.rect.top -= self.speed
+
+ if self.rect.top < 0:
+ self.active = False
+
+ def reset(self, position):
+ self.rect.left, self.rect.top = position
+ self.active = True
+
+class Bullet2(pygame.sprite.Sprite):
+ def __init__(self, position):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.image = pygame.image.load(abspath + "images/bullet2.png").convert_alpha()
+ self.rect = self.image.get_rect()
+ self.rect.left, self.rect.top = position
+ self.speed = 14#14
+ self.active = False
+ self.mask = pygame.mask.from_surface(self.image)
+
+ def move(self):
+ self.rect.top -= self.speed
+
+ if self.rect.top < 0:
+ self.active = False
+
+ def reset(self, position):
+ self.rect.left, self.rect.top = position
+ self.active = True
+
diff --git a/plane_fighting/enemy.py b/plane_fighting/enemy.py
new file mode 100644
index 0000000..1ab4d9b
--- /dev/null
+++ b/plane_fighting/enemy.py
@@ -0,0 +1,118 @@
+import pygame,os
+from random import *
+abspath = os.getcwd() + "/"
+class SmallEnemy(pygame.sprite.Sprite):
+ def __init__(self, bg_size):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.image = pygame.image.load(abspath + "images/enemy1.png").convert_alpha()
+ self.destroy_images = []
+ self.destroy_images.extend([\
+ pygame.image.load(abspath + "images/enemy1_down1.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy1_down2.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy1_down3.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy1_down4.png").convert_alpha() \
+ ])
+ self.rect = self.image.get_rect()
+ self.width, self.height = bg_size[0], bg_size[1]
+ self.speed = 2
+ self.active = True
+ self.rect.left, self.rect.top = \
+ randint(0, self.width - self.rect.width), \
+ randint(-5 * self.height, 0)
+ self.mask = pygame.mask.from_surface(self.image)
+
+ def move(self):
+ if self.rect.top < self.height:
+ self.rect.top += self.speed
+ else:
+ self.reset()
+
+ def reset(self):
+ self.active = True
+ self.rect.left, self.rect.top = \
+ randint(0, self.width - self.rect.width), \
+ randint(-5 * self.height, 0)
+
+
+class MidEnemy(pygame.sprite.Sprite):
+ energy = 8
+
+ def __init__(self, bg_size):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.image = pygame.image.load(abspath + "images/enemy2.png").convert_alpha()
+ self.image_hit = pygame.image.load(abspath + "images/enemy2_hit.png").convert_alpha()
+ self.destroy_images = []
+ self.destroy_images.extend([\
+ pygame.image.load(abspath + "images/enemy2_down1.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy2_down2.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy2_down3.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy2_down4.png").convert_alpha() \
+ ])
+ self.rect = self.image.get_rect()
+ self.width, self.height = bg_size[0], bg_size[1]
+ self.speed = 1
+ self.active = True
+ self.rect.left, self.rect.top = \
+ randint(0, self.width - self.rect.width), \
+ randint(-10 * self.height, -self.height)
+ self.mask = pygame.mask.from_surface(self.image)
+ self.energy = MidEnemy.energy
+ self.hit = False
+
+ def move(self):
+ if self.rect.top < self.height:
+ self.rect.top += self.speed
+ else:
+ self.reset()
+
+ def reset(self):
+ self.active = True
+ self.energy = MidEnemy.energy
+ self.rect.left, self.rect.top = \
+ randint(0, self.width - self.rect.width), \
+ randint(-10 * self.height, -self.height)
+
+
+class BigEnemy(pygame.sprite.Sprite):
+ energy = 20
+
+ def __init__(self, bg_size):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.image1 = pygame.image.load(abspath + "images/enemy3_n1.png").convert_alpha()
+ self.image2 = pygame.image.load(abspath + "images/enemy3_n2.png").convert_alpha()
+ self.image_hit = pygame.image.load(abspath + "images/enemy3_hit.png").convert_alpha()
+ self.destroy_images = []
+ self.destroy_images.extend([\
+ pygame.image.load(abspath + "images/enemy3_down1.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy3_down2.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy3_down3.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy3_down4.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy3_down5.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/enemy3_down6.png").convert_alpha() \
+ ])
+ self.rect = self.image1.get_rect()
+ self.width, self.height = bg_size[0], bg_size[1]
+ self.speed = 1
+ self.active = True
+ self.rect.left, self.rect.top = \
+ randint(0, self.width - self.rect.width), \
+ randint(-15 * self.height, -5 * self.height)
+ self.mask = pygame.mask.from_surface(self.image1)
+ self.energy = BigEnemy.energy
+ self.hit = False
+
+ def move(self):
+ if self.rect.top < self.height:
+ self.rect.top += self.speed
+ else:
+ self.reset()
+
+ def reset(self):
+ self.active = True
+ self.energy = BigEnemy.energy
+ self.rect.left, self.rect.top = \
+ randint(0, self.width - self.rect.width), \
+ randint(-15 * self.height, -5 * self.height)
diff --git a/plane_fighting/font/font-2.ttf b/plane_fighting/font/font-2.ttf
new file mode 100644
index 0000000..ed0f5bc
Binary files /dev/null and b/plane_fighting/font/font-2.ttf differ
diff --git a/plane_fighting/font/font.ttf b/plane_fighting/font/font.ttf
new file mode 100644
index 0000000..b173da2
Binary files /dev/null and b/plane_fighting/font/font.ttf differ
diff --git a/plane_fighting/images/again.png b/plane_fighting/images/again.png
new file mode 100644
index 0000000..cbcc54d
Binary files /dev/null and b/plane_fighting/images/again.png differ
diff --git a/plane_fighting/images/background.png b/plane_fighting/images/background.png
new file mode 100644
index 0000000..2197c0f
Binary files /dev/null and b/plane_fighting/images/background.png differ
diff --git a/plane_fighting/images/bomb.png b/plane_fighting/images/bomb.png
new file mode 100644
index 0000000..1c92d5b
Binary files /dev/null and b/plane_fighting/images/bomb.png differ
diff --git a/plane_fighting/images/bomb_supply.png b/plane_fighting/images/bomb_supply.png
new file mode 100644
index 0000000..07f242b
Binary files /dev/null and b/plane_fighting/images/bomb_supply.png differ
diff --git a/plane_fighting/images/bullet1.png b/plane_fighting/images/bullet1.png
new file mode 100644
index 0000000..9b575e3
Binary files /dev/null and b/plane_fighting/images/bullet1.png differ
diff --git a/plane_fighting/images/bullet2.png b/plane_fighting/images/bullet2.png
new file mode 100644
index 0000000..43e3246
Binary files /dev/null and b/plane_fighting/images/bullet2.png differ
diff --git a/plane_fighting/images/bullet_supply.png b/plane_fighting/images/bullet_supply.png
new file mode 100644
index 0000000..9c51e82
Binary files /dev/null and b/plane_fighting/images/bullet_supply.png differ
diff --git a/plane_fighting/images/enemy1.png b/plane_fighting/images/enemy1.png
new file mode 100644
index 0000000..51cfce7
Binary files /dev/null and b/plane_fighting/images/enemy1.png differ
diff --git a/Plane_Fighting/images/enemy1_down.png b/plane_fighting/images/enemy1_down1.png
old mode 100755
new mode 100644
similarity index 90%
rename from Plane_Fighting/images/enemy1_down.png
rename to plane_fighting/images/enemy1_down1.png
index 1e0fa49..95e211b
Binary files a/Plane_Fighting/images/enemy1_down.png and b/plane_fighting/images/enemy1_down1.png differ
diff --git a/plane_fighting/images/enemy1_down2.png b/plane_fighting/images/enemy1_down2.png
new file mode 100644
index 0000000..508b769
Binary files /dev/null and b/plane_fighting/images/enemy1_down2.png differ
diff --git a/plane_fighting/images/enemy1_down3.png b/plane_fighting/images/enemy1_down3.png
new file mode 100644
index 0000000..3c4630c
Binary files /dev/null and b/plane_fighting/images/enemy1_down3.png differ
diff --git a/plane_fighting/images/enemy1_down4.png b/plane_fighting/images/enemy1_down4.png
new file mode 100644
index 0000000..e7aebbf
Binary files /dev/null and b/plane_fighting/images/enemy1_down4.png differ
diff --git a/plane_fighting/images/enemy2.png b/plane_fighting/images/enemy2.png
new file mode 100644
index 0000000..7f7e68d
Binary files /dev/null and b/plane_fighting/images/enemy2.png differ
diff --git a/plane_fighting/images/enemy2_down1.png b/plane_fighting/images/enemy2_down1.png
new file mode 100644
index 0000000..f7c68de
Binary files /dev/null and b/plane_fighting/images/enemy2_down1.png differ
diff --git a/plane_fighting/images/enemy2_down2.png b/plane_fighting/images/enemy2_down2.png
new file mode 100644
index 0000000..8a72aca
Binary files /dev/null and b/plane_fighting/images/enemy2_down2.png differ
diff --git a/plane_fighting/images/enemy2_down3.png b/plane_fighting/images/enemy2_down3.png
new file mode 100644
index 0000000..e510526
Binary files /dev/null and b/plane_fighting/images/enemy2_down3.png differ
diff --git a/plane_fighting/images/enemy2_down4.png b/plane_fighting/images/enemy2_down4.png
new file mode 100644
index 0000000..2031b6c
Binary files /dev/null and b/plane_fighting/images/enemy2_down4.png differ
diff --git a/plane_fighting/images/enemy2_hit.png b/plane_fighting/images/enemy2_hit.png
new file mode 100644
index 0000000..9f4d8c3
Binary files /dev/null and b/plane_fighting/images/enemy2_hit.png differ
diff --git a/Plane_Fighting/images/enemy3_down.png b/plane_fighting/images/enemy3_down1.png
old mode 100755
new mode 100644
similarity index 100%
rename from Plane_Fighting/images/enemy3_down.png
rename to plane_fighting/images/enemy3_down1.png
diff --git a/plane_fighting/images/enemy3_down2.png b/plane_fighting/images/enemy3_down2.png
new file mode 100644
index 0000000..3e7469c
Binary files /dev/null and b/plane_fighting/images/enemy3_down2.png differ
diff --git a/plane_fighting/images/enemy3_down3.png b/plane_fighting/images/enemy3_down3.png
new file mode 100644
index 0000000..3e7469c
Binary files /dev/null and b/plane_fighting/images/enemy3_down3.png differ
diff --git a/plane_fighting/images/enemy3_down4.png b/plane_fighting/images/enemy3_down4.png
new file mode 100644
index 0000000..3e7469c
Binary files /dev/null and b/plane_fighting/images/enemy3_down4.png differ
diff --git a/plane_fighting/images/enemy3_down5.png b/plane_fighting/images/enemy3_down5.png
new file mode 100644
index 0000000..1a6d711
Binary files /dev/null and b/plane_fighting/images/enemy3_down5.png differ
diff --git a/plane_fighting/images/enemy3_down6.png b/plane_fighting/images/enemy3_down6.png
new file mode 100644
index 0000000..3e7469c
Binary files /dev/null and b/plane_fighting/images/enemy3_down6.png differ
diff --git a/plane_fighting/images/enemy3_hit.png b/plane_fighting/images/enemy3_hit.png
new file mode 100644
index 0000000..3e7469c
Binary files /dev/null and b/plane_fighting/images/enemy3_hit.png differ
diff --git a/Plane_Fighting/images/enemy3.png b/plane_fighting/images/enemy3_n1.png
old mode 100755
new mode 100644
similarity index 100%
rename from Plane_Fighting/images/enemy3.png
rename to plane_fighting/images/enemy3_n1.png
diff --git a/plane_fighting/images/enemy3_n2.png b/plane_fighting/images/enemy3_n2.png
new file mode 100644
index 0000000..0e8bfc9
Binary files /dev/null and b/plane_fighting/images/enemy3_n2.png differ
diff --git a/plane_fighting/images/gameover.png b/plane_fighting/images/gameover.png
new file mode 100644
index 0000000..09d2df5
Binary files /dev/null and b/plane_fighting/images/gameover.png differ
diff --git a/plane_fighting/images/icon.png b/plane_fighting/images/icon.png
new file mode 100644
index 0000000..6059812
Binary files /dev/null and b/plane_fighting/images/icon.png differ
diff --git a/plane_fighting/images/life.png b/plane_fighting/images/life.png
new file mode 100644
index 0000000..d759806
Binary files /dev/null and b/plane_fighting/images/life.png differ
diff --git a/plane_fighting/images/loading.png b/plane_fighting/images/loading.png
new file mode 100644
index 0000000..9b6d9c5
Binary files /dev/null and b/plane_fighting/images/loading.png differ
diff --git a/plane_fighting/images/me1.png b/plane_fighting/images/me1.png
new file mode 100644
index 0000000..b28bf94
Binary files /dev/null and b/plane_fighting/images/me1.png differ
diff --git a/plane_fighting/images/me2.png b/plane_fighting/images/me2.png
new file mode 100644
index 0000000..f971015
Binary files /dev/null and b/plane_fighting/images/me2.png differ
diff --git a/plane_fighting/images/me_destroy_1.png b/plane_fighting/images/me_destroy_1.png
new file mode 100644
index 0000000..d46ad28
Binary files /dev/null and b/plane_fighting/images/me_destroy_1.png differ
diff --git a/plane_fighting/images/me_destroy_2.png b/plane_fighting/images/me_destroy_2.png
new file mode 100644
index 0000000..a480bef
Binary files /dev/null and b/plane_fighting/images/me_destroy_2.png differ
diff --git a/plane_fighting/images/me_destroy_3.png b/plane_fighting/images/me_destroy_3.png
new file mode 100644
index 0000000..e1908bd
Binary files /dev/null and b/plane_fighting/images/me_destroy_3.png differ
diff --git a/plane_fighting/images/me_destroy_4.png b/plane_fighting/images/me_destroy_4.png
new file mode 100644
index 0000000..446b4fb
Binary files /dev/null and b/plane_fighting/images/me_destroy_4.png differ
diff --git a/plane_fighting/images/pause_nor.png b/plane_fighting/images/pause_nor.png
new file mode 100644
index 0000000..d2b9cc2
Binary files /dev/null and b/plane_fighting/images/pause_nor.png differ
diff --git a/plane_fighting/images/pause_pressed.png b/plane_fighting/images/pause_pressed.png
new file mode 100644
index 0000000..8df8d2d
Binary files /dev/null and b/plane_fighting/images/pause_pressed.png differ
diff --git a/plane_fighting/images/resume_nor.png b/plane_fighting/images/resume_nor.png
new file mode 100644
index 0000000..19a185e
Binary files /dev/null and b/plane_fighting/images/resume_nor.png differ
diff --git a/plane_fighting/images/resume_pressed.png b/plane_fighting/images/resume_pressed.png
new file mode 100644
index 0000000..3bfc993
Binary files /dev/null and b/plane_fighting/images/resume_pressed.png differ
diff --git a/plane_fighting/main.py b/plane_fighting/main.py
new file mode 100644
index 0000000..9716a85
--- /dev/null
+++ b/plane_fighting/main.py
@@ -0,0 +1,603 @@
+# main.py
+import pygame
+import sys
+import traceback
+import myplane
+import enemy
+import bullet
+import supply
+import time
+import os
+
+abspath = os.getcwd() + "/"
+from pygame.locals import *
+from random import *
+jj = 0
+pygame.init()
+pygame.mixer.init()
+
+bg_size = width, height = 480, 700
+screen = pygame.display.set_mode(bg_size)
+pygame.display.set_caption("Plane Fighting")
+key_pressed = pygame.key.get_pressed()
+background=pygame.image.load(abspath + "images/loading.png") #图片位置
+screen.blit(background,(0,0)) #对齐的坐标
+pygame.display.update() #显示内容
+pygame.mixer.music.load(abspath + "sound/game_music.ogg")
+pygame.mixer.music.set_volume(0.1)
+pygame.mixer.music.play(-1)
+time.sleep(7.5)
+background = pygame.image.load(abspath + "images/background.png").convert()
+BLACK = (0, 0, 0)
+WHITE = (255, 255, 255)
+GREEN = (0, 255, 0)
+RED = (255, 0, 0)
+
+# 载入游戏音乐
+bullet_sound = pygame.mixer.Sound(abspath + "sound/bullet.wav")
+bullet_sound.set_volume(0.2)
+bomb_sound = pygame.mixer.Sound(abspath + "sound/use_bomb.wav")
+bomb_sound.set_volume(0.2)
+supply_sound = pygame.mixer.Sound(abspath + "sound/supply.wav")
+supply_sound.set_volume(0.2)
+get_bomb_sound = pygame.mixer.Sound(abspath + "sound/get_bomb.wav")
+get_bomb_sound.set_volume(0.2)
+get_bullet_sound = pygame.mixer.Sound(abspath + "sound/get_bullet.wav")
+get_bullet_sound.set_volume(0.2)
+upgrade_sound = pygame.mixer.Sound(abspath + "sound/upgrade.wav")
+upgrade_sound.set_volume(0.2)
+enemy3_fly_sound = pygame.mixer.Sound(abspath + "sound/enemy3_flying.wav")
+enemy3_fly_sound.set_volume(0.2)
+enemy1_down_sound = pygame.mixer.Sound(abspath + "sound/enemy1_down.wav")
+enemy1_down_sound.set_volume(0.2)
+enemy2_down_sound = pygame.mixer.Sound(abspath + "sound/enemy2_down.wav")
+enemy2_down_sound.set_volume(0.2)
+enemy3_down_sound = pygame.mixer.Sound(abspath + "sound/enemy3_down.wav")
+enemy3_down_sound.set_volume(0.5)
+me_down_sound = pygame.mixer.Sound(abspath + "sound/me_down.wav")
+
+
+
+def add_small_enemies(group1, group2, num):
+ for i in range(num):
+ e1 = enemy.SmallEnemy(bg_size)
+ group1.add(e1)
+ group2.add(e1)
+
+def add_mid_enemies(group1, group2, num):
+ for i in range(num):
+ e2 = enemy.MidEnemy(bg_size)
+ group1.add(e2)
+ group2.add(e2)
+
+def add_big_enemies(group1, group2, num):
+ for i in range(num):
+ e3 = enemy.BigEnemy(bg_size)
+ group1.add(e3)
+ group2.add(e3)
+
+def inc_speed(target, inc):
+ for each in target:
+ each.speed += inc
+
+def main():
+ # Me
+ me = myplane.MyPlane(bg_size)
+
+ enemies = pygame.sprite.Group()
+
+
+ # Enemy Level 1
+ small_enemies = pygame.sprite.Group()
+ add_small_enemies(small_enemies, enemies, 15)
+
+ # Enemy Level 2
+ mid_enemies = pygame.sprite.Group()
+ add_mid_enemies(mid_enemies, enemies, 4)
+
+ # Enemy Level 3
+ big_enemies = pygame.sprite.Group()
+ add_big_enemies(big_enemies, enemies, 2)
+
+ # Common Bull
+ bullet1 = []
+ bullet1_index = 0
+ BULLET1_NUM = 4
+ for i in range(BULLET1_NUM):
+ bullet1.append(bullet.Bullet1((me.rect.centerx-3, me.rect.centery)))
+
+ # Super Bull
+ bullet2 = []
+ bullet2_index = 0
+ BULLET2_NUM = 8
+ for i in range(BULLET2_NUM//2):
+ bullet2.append(bullet.Bullet2((me.rect.centerx-33, me.rect.centery)))
+ bullet2.append(bullet.Bullet2((me.rect.centerx+30, me.rect.centery)))
+
+ clock = pygame.time.Clock()
+
+ # 中弹图片索引
+ e1_destroy_index = 0
+ e2_destroy_index = 0
+ e3_destroy_index = 0
+ me_destroy_index = 0
+
+ # 统计得分
+ score = 0
+ score_font = pygame.font.Font(abspath + "font/font.ttf", 36)
+
+ # 标志是否暂停游戏
+ paused = False
+ pause_nor_image = pygame.image.load(abspath + "images/pause_nor.png").convert_alpha()
+ pause_pressed_image = pygame.image.load(abspath + "images/pause_pressed.png").convert_alpha()
+ resume_nor_image = pygame.image.load(abspath + "images/resume_nor.png").convert_alpha()
+ resume_pressed_image = pygame.image.load(abspath + "images/resume_pressed.png").convert_alpha()
+ paused_rect = pause_nor_image.get_rect()
+ paused_rect.left, paused_rect.top = width - paused_rect.width - 10, 10
+ paused_image = pause_nor_image
+
+ # 设置难度级别
+ level = 1
+
+ # 全屏炸弹
+ bomb_image = pygame.image.load(abspath + "images/bomb.png").convert_alpha()
+ bomb_rect = bomb_image.get_rect()
+ bomb_font = pygame.font.Font(abspath + "font/font.ttf", 48)
+ bomb_num = 3
+
+ # 每30秒发放一个补给包
+ bullet_supply = supply.Bullet_Supply(bg_size)
+ bomb_supply = supply.Bomb_Supply(bg_size)
+ SUPPLY_TIME = USEREVENT
+ pygame.time.set_timer(SUPPLY_TIME, 30 * 1000)
+
+ # 超级子弹定时器
+ DOUBLE_BULLET_TIME = USEREVENT + 1
+
+ # 标志是否使用超级子弹
+ is_double_bullet = False
+
+ # 解除我方无敌状态定时器
+ INVINCIBLE_TIME = USEREVENT + 3
+
+
+ # 生命数量
+ life_num = 3
+ life_image = pygame.image.load(abspath + "images/life.png").convert_alpha()
+ life_rect = life_image.get_rect()
+
+ # 用于阻止重复打开记录文件
+ recorded = False
+
+ # 游戏结束画面
+ gameover_font = pygame.font.Font(abspath + "font/font.ttf", 48)
+ again_image = pygame.image.load(abspath + "images/again.png").convert_alpha()
+ again_rect = again_image.get_rect()
+ gameover_image = pygame.image.load(abspath + "images/gameover.png").convert_alpha()
+ gameover_rect = gameover_image.get_rect()
+
+ # 用于切换图片
+ switch_image = True
+
+ # 用于延迟
+ delay = 100
+
+ running = True
+
+ while running:
+ for event in pygame.event.get():
+ if event.type == QUIT:
+ pygame.quit()
+ sys.exit()
+
+ elif event.type == MOUSEBUTTONDOWN:
+ if event.button == 1 and paused_rect.collidepoint(event.pos):
+ paused = not paused
+ if paused:
+ pygame.time.set_timer(SUPPLY_TIME, 0)
+ pygame.mixer.music.pause()
+ pygame.mixer.pause()
+ else:
+ pygame.time.set_timer(SUPPLY_TIME, 30 * 1000)
+ pygame.mixer.music.unpause()
+ pygame.mixer.unpause()
+
+ elif event.type == MOUSEMOTION:
+ if paused_rect.collidepoint(event.pos):
+ if paused:
+ paused_image = resume_pressed_image
+ else:
+ paused_image = pause_pressed_image
+ else:
+ if paused:
+ paused_image = resume_nor_image
+ else:
+ paused_image = pause_nor_image
+
+ elif event.type == KEYDOWN:
+ if event.key == K_SPACE:
+ if bomb_num:
+ bomb_num -= 1
+ bomb_sound.play()
+ for each in enemies:
+ if each.rect.bottom > 0:
+ each.active = False
+
+ elif event.type == SUPPLY_TIME:
+ supply_sound.play()
+ if choice([True, False]):
+ bomb_supply.reset()
+ else:
+ bullet_supply.reset()
+
+ elif event.type == DOUBLE_BULLET_TIME:
+ is_double_bullet = False
+ pygame.time.set_timer(DOUBLE_BULLET_TIME, 0)
+
+ elif event.type == INVINCIBLE_TIME:
+ me.invincible = False
+ pygame.time.set_timer(INVINCIBLE_TIME, 0)
+
+
+ # 根据用户的得分增加难度
+ if level == 1 and score > 50000:
+ level = 2
+ upgrade_sound.play()
+ # 增加3架小型敌机、2架中型敌机和1架大型敌机
+ add_small_enemies(small_enemies, enemies, 3)
+ add_mid_enemies(mid_enemies, enemies, 2)
+ add_big_enemies(big_enemies, enemies, 1)
+ # 提升小型敌机的速度
+ inc_speed(small_enemies, 1)
+ elif level == 2 and score > 300000:
+ level = 3
+ upgrade_sound.play()
+ # 增加5架小型敌机、3架中型敌机和2架大型敌机
+ add_small_enemies(small_enemies, enemies, 5)
+ add_mid_enemies(mid_enemies, enemies, 3)
+ add_big_enemies(big_enemies, enemies, 2)
+ # 提升小型敌机的速度
+ inc_speed(small_enemies, 1)
+ inc_speed(mid_enemies, 1)
+ elif level == 3 and score > 600000:
+ level = 4
+ upgrade_sound.play()
+ # 增加5架小型敌机、3架中型敌机和2架大型敌机
+ add_small_enemies(small_enemies, enemies, 5)
+ add_mid_enemies(mid_enemies, enemies, 3)
+ add_big_enemies(big_enemies, enemies, 2)
+ # 提升小型敌机的速度
+ inc_speed(small_enemies, 1)
+ inc_speed(mid_enemies, 1)
+ elif level == 4 and score > 1000000:
+ level = 5
+ upgrade_sound.play()
+ # 增加5架小型敌机、3架中型敌机和2架大型敌机
+ add_small_enemies(small_enemies, enemies, 300)
+
+ # 提升小型敌机的速度
+ inc_speed(small_enemies, 1)
+ inc_speed(mid_enemies, 1)
+
+
+ screen.blit(background, (0, 0))
+
+ if life_num and not paused:
+ # 检测用户的键盘操作
+ key_pressed = pygame.key.get_pressed()
+
+ if key_pressed[K_w] or key_pressed[K_UP]:
+ me.moveUp()
+ elif key_pressed[K_s] or key_pressed[K_DOWN]:
+ me.moveDown()
+ elif key_pressed[K_a] or key_pressed[K_LEFT]:
+ me.moveLeft()
+ elif key_pressed[K_d] or key_pressed[K_RIGHT]:
+ me.moveRight()
+ elif key_pressed[K_F1]:#100核弹
+ bomb_num = 100
+ elif key_pressed[K_F2]:#不使用双子弹
+ is_double_bullet = True
+ elif key_pressed[K_F3]:#使用双子弹
+ is_double_bullet = False
+ elif key_pressed[K_F4]:#生命+1
+ life_num += 1
+ elif key_pressed[K_F5]:#小+1
+ add_small_enemies(small_enemies, enemies, 100)
+ elif key_pressed[K_F6]:#中+1
+ add_mid_enemies(mid_enemies, enemies, 100)
+ elif key_pressed[K_F7]:#大+1
+ add_big_enemies(big_enemies, enemies, 100)
+ elif key_pressed[K_F8]:
+ level = 4
+ score = 1000000
+
+
+
+
+ # 绘制全屏炸弹补给并检测是否获得
+ if bomb_supply.active:
+ bomb_supply.move()
+ screen.blit(bomb_supply.image, bomb_supply.rect)
+ if pygame.sprite.collide_mask(bomb_supply, me):
+ get_bomb_sound.play()
+ if bomb_num < 3:
+ bomb_num += 1
+ bomb_supply.active = False
+
+ # 绘制超级子弹补给并检测是否获得
+ if bullet_supply.active:
+ bullet_supply.move()
+ screen.blit(bullet_supply.image, bullet_supply.rect)
+ if pygame.sprite.collide_mask(bullet_supply, me):
+ get_bullet_sound.play()
+ is_double_bullet = True
+ pygame.time.set_timer(DOUBLE_BULLET_TIME, 18 * 1000)
+ bullet_supply.active = False
+
+ # 发射子弹
+ if not(delay % 10):
+ bullet_sound.play()
+ if is_double_bullet:
+ bullets = bullet2
+ bullets[bullet2_index].reset((me.rect.centerx-33, me.rect.centery))
+ bullets[bullet2_index+1].reset((me.rect.centerx+30, me.rect.centery))
+ bullet2_index = (bullet2_index + 2) % BULLET2_NUM
+ else:
+ bullets = bullet1
+ bullets[bullet1_index].reset(me.rect.midtop)
+ bullet1_index = (bullet1_index + 1) % BULLET1_NUM
+
+
+ # 检测子弹是否击中敌机
+ for b in bullets:
+ if b.active:
+ b.move()
+ screen.blit(b.image, b.rect)
+ enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
+ if enemy_hit:
+ b.active = False
+ for e in enemy_hit:
+ if e in mid_enemies or e in big_enemies:
+ e.hit = True
+ e.energy -= 1
+ if e.energy == 0:
+ e.active = False
+ else:
+ e.active = False
+
+ # 绘制大型敌机
+ for each in big_enemies:
+ if each.active:
+ each.move()
+ if each.hit:
+ screen.blit(each.image_hit, each.rect)
+ each.hit = False
+ else:
+ if switch_image:
+ screen.blit(each.image1, each.rect)
+ else:
+ screen.blit(each.image2, each.rect)
+
+ # 绘制血槽
+ pygame.draw.line(screen, BLACK, \
+ (each.rect.left, each.rect.top - 5), \
+ (each.rect.right, each.rect.top - 5), \
+ 2)
+ # 当生命大于20%显示绿色,否则显示红色
+ energy_remain = each.energy / enemy.BigEnemy.energy
+ if energy_remain > 0.2:
+ energy_color = GREEN
+ else:
+ energy_color = RED
+ pygame.draw.line(screen, energy_color, \
+ (each.rect.left, each.rect.top - 5), \
+ (each.rect.left + each.rect.width * energy_remain, \
+ each.rect.top - 5), 2)
+
+ # 即将出现在画面中,播放音效
+ if each.rect.bottom == -50:
+ enemy3_fly_sound.play(-1)
+ else:
+ # 毁灭
+ if not(delay % 3):
+ if e3_destroy_index == 0:
+ enemy3_down_sound.play()
+ screen.blit(each.destroy_images[e3_destroy_index], each.rect)
+ e3_destroy_index = (e3_destroy_index + 1) % 6
+ if e3_destroy_index == 0:
+ enemy3_fly_sound.stop()
+ score += 10000
+ each.reset()
+
+ # 绘制中型敌机:
+ for each in mid_enemies:
+ if each.active:
+ each.move()
+
+ if each.hit:
+ screen.blit(each.image_hit, each.rect)
+ each.hit = False
+ else:
+ screen.blit(each.image, each.rect)
+
+ # 绘制血槽
+ pygame.draw.line(screen, BLACK, \
+ (each.rect.left, each.rect.top - 5), \
+ (each.rect.right, each.rect.top - 5), \
+ 2)
+ # 当生命大于20%显示绿色,否则显示红色
+ lu = (0, 230, 0)
+ qiancheng = (115, 165, 0)
+ shencheng = (165, 115, 0)
+ hong = (230, 0, 0)
+ energy_remain = each.energy / enemy.MidEnemy.energy
+ if energy_remain > 0.75:
+ energy_color = lu
+ elif energy_remain > 0.50:
+ energy_color = qiancheng
+ elif energy_remain > 0.25:
+ energy_color = shencheng
+ else:
+ energy_color = hong
+ pygame.draw.line(screen, energy_color, \
+ (each.rect.left, each.rect.top - 5), \
+ (each.rect.left + each.rect.width * energy_remain, \
+ each.rect.top - 5), 2)
+ else:
+ # 毁灭
+ if not(delay % 3):
+ if e2_destroy_index == 0:
+ enemy2_down_sound.play()
+ screen.blit(each.destroy_images[e2_destroy_index], each.rect)
+ e2_destroy_index = (e2_destroy_index + 1) % 4
+ if e2_destroy_index == 0:
+ score += 6000
+ each.reset()
+
+ # 绘制小型敌机:
+ for each in small_enemies:
+ if each.active:
+ each.move()
+ screen.blit(each.image, each.rect)
+ else:
+ # 毁灭
+ if not(delay % 3):
+ if e1_destroy_index == 0:
+ enemy1_down_sound.play()
+ score += 1000
+ each.reset()
+ screen.blit(each.destroy_images[e1_destroy_index], each.rect)
+ e1_destroy_index = (e1_destroy_index + 1) % 4
+
+ # 检测我方飞机是否被撞
+ enemies_down = pygame.sprite.spritecollide(me, enemies, False, pygame.sprite.collide_mask)
+ if enemies_down and not me.invincible:
+ me.active = False
+ for e in enemies_down:
+ e.active = False
+
+ # 绘制我方飞机
+ if me.active:
+ if switch_image:
+ screen.blit(me.image1, me.rect)
+ else:
+ screen.blit(me.image2, me.rect)
+ else:
+ # 毁灭
+ if not(delay % 3):
+ if me_destroy_index == 0:
+ me_down_sound.play()
+ screen.blit(me.destroy_images[me_destroy_index], me.rect)
+ me_destroy_index = (me_destroy_index + 1) % 4
+ if me_destroy_index == 0:
+ life_num -= 1
+ me.reset()
+ pygame.time.set_timer(INVINCIBLE_TIME, 3 * 1000)
+
+ # 绘制全屏炸弹数量
+ bomb_text = bomb_font.render("× %d" % bomb_num, True, WHITE)
+ text_rect = bomb_text.get_rect()
+ screen.blit(bomb_image, (10, height - 10 - bomb_rect.height))
+ screen.blit(bomb_text, (20 + bomb_rect.width, height - 5 - text_rect.height))
+
+ # 绘制剩余生命数量
+ if life_num:
+ for i in range(life_num):
+ screen.blit(life_image, \
+ (width-10-(i+1)*life_rect.width, \
+ height-10-life_rect.height))
+
+ # 绘制得分
+ score_text = score_font.render("Score : %s" % str(score), True, WHITE)
+ screen.blit(score_text, (10, 5))
+
+ # 绘制游戏结束画面
+ elif life_num == 0:
+ # 背景音乐停止
+ pygame.mixer.music.stop()
+
+ # 停止全部音效
+ pygame.mixer.stop()
+
+ # 停止发放补给
+ pygame.time.set_timer(SUPPLY_TIME, 0)
+
+ if not recorded:
+ recorded = True
+ # 读取历史最高得分
+ with open("record.dat", "r") as f:
+ record_score = int(f.read())
+
+ # 如果玩家得分高于历史最高得分,则存档
+ if score > record_score:
+ with open("record.dat", "w") as f:
+ f.write(str(score))
+
+ # 绘制结束画面
+ record_score_text = score_font.render("Best : %d" % record_score, True, (255, 255, 255))
+ screen.blit(record_score_text, (50, 50))
+
+ gameover_text1 = gameover_font.render("Your Score", True, (255, 255, 255))
+ gameover_text1_rect = gameover_text1.get_rect()
+ gameover_text1_rect.left, gameover_text1_rect.top = \
+ (width - gameover_text1_rect.width) // 2, height // 3
+ screen.blit(gameover_text1, gameover_text1_rect)
+
+ gameover_text2 = gameover_font.render(str(score), True, (255, 255, 255))
+ gameover_text2_rect = gameover_text2.get_rect()
+ gameover_text2_rect.left, gameover_text2_rect.top = \
+ (width - gameover_text2_rect.width) // 2, \
+ gameover_text1_rect.bottom + 10
+ screen.blit(gameover_text2, gameover_text2_rect)
+
+ again_rect.left, again_rect.top = \
+ (width - again_rect.width) // 2, \
+ gameover_text2_rect.bottom + 50
+ screen.blit(again_image, again_rect)
+
+ gameover_rect.left, gameover_rect.top = \
+ (width - again_rect.width) // 2, \
+ again_rect.bottom + 10
+ screen.blit(gameover_image, gameover_rect)
+
+ # 检测用户的鼠标操作
+ # 如果用户按下鼠标左键
+ if pygame.mouse.get_pressed()[0]:
+ # 获取鼠标坐标
+ pos = pygame.mouse.get_pos()
+ # 如果用户点击“重新开始”
+ if again_rect.left < pos[0] < again_rect.right and \
+ again_rect.top < pos[1] < again_rect.bottom:
+ # 调用main函数,重新开始游戏
+ main()
+ # 如果用户点击“结束游戏”
+ elif gameover_rect.left < pos[0] < gameover_rect.right and \
+ gameover_rect.top < pos[1] < gameover_rect.bottom:
+ # 退出游戏
+ pygame.quit()
+ sys.exit()
+
+ # 绘制暂停按钮
+ screen.blit(paused_image, paused_rect)
+
+ # 切换图片
+ if not(delay % 5):
+ switch_image = not switch_image
+
+ delay -= 1
+ if not delay:
+ delay = 100
+
+ pygame.display.flip()
+ clock.tick(60)
+
+if __name__ == "__main__":
+ try:
+ main()
+ except SystemExit:
+ pass
+ except:
+ traceback.print_exc()
+ pygame.quit()
+ input()
diff --git a/plane_fighting/myplane.py b/plane_fighting/myplane.py
new file mode 100644
index 0000000..f28bffc
--- /dev/null
+++ b/plane_fighting/myplane.py
@@ -0,0 +1,55 @@
+import pygame,os
+abspath = os.getcwd() + "/"
+class MyPlane(pygame.sprite.Sprite):
+ def __init__(self, bg_size):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.image1 = pygame.image.load(abspath + "images/me1.png").convert_alpha()
+ self.image2 = pygame.image.load(abspath + "images/me2.png").convert_alpha()
+ self.destroy_images = []
+ self.destroy_images.extend([\
+ pygame.image.load(abspath + "images/me_destroy_1.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/me_destroy_2.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/me_destroy_3.png").convert_alpha(), \
+ pygame.image.load(abspath + "images/me_destroy_4.png").convert_alpha() \
+ ])
+ self.rect = self.image1.get_rect()
+ self.width, self.height = bg_size[0], bg_size[1]
+ self.rect.left, self.rect.top = \
+ (self.width - self.rect.width) // 2, \
+ self.height - self.rect.height - 60
+ self.speed = 10
+ self.active = True
+ self.invincible = False
+ self.mask = pygame.mask.from_surface(self.image1)
+
+ def moveUp(self):
+ if self.rect.top > 0:
+ self.rect.top -= self.speed
+ else:
+ self.rect.top = 0
+
+ def moveDown(self):
+ if self.rect.bottom < self.height - 60:
+ self.rect.top += self.speed
+ else:
+ self.rect.bottom = self.height - 60
+
+ def moveLeft(self):
+ if self.rect.left > 0:
+ self.rect.left -= self.speed
+ else:
+ self.rect.left = 0
+
+ def moveRight(self):
+ if self.rect.right < self.width:
+ self.rect.left += self.speed
+ else:
+ self.rect.right = self.width
+
+ def reset(self):
+ self.rect.left, self.rect.top = \
+ (self.width - self.rect.width) // 2, \
+ self.height - self.rect.height - 60
+ self.active = True
+ self.invincible = True
diff --git a/plane_fighting/old_images/again.png b/plane_fighting/old_images/again.png
new file mode 100644
index 0000000..627e7b3
Binary files /dev/null and b/plane_fighting/old_images/again.png differ
diff --git a/plane_fighting/old_images/background.png b/plane_fighting/old_images/background.png
new file mode 100644
index 0000000..01e4a5d
Binary files /dev/null and b/plane_fighting/old_images/background.png differ
diff --git a/plane_fighting/old_images/bomb.png b/plane_fighting/old_images/bomb.png
new file mode 100644
index 0000000..1b988d2
Binary files /dev/null and b/plane_fighting/old_images/bomb.png differ
diff --git a/plane_fighting/old_images/bomb_supply.png b/plane_fighting/old_images/bomb_supply.png
new file mode 100644
index 0000000..b2ef345
Binary files /dev/null and b/plane_fighting/old_images/bomb_supply.png differ
diff --git a/plane_fighting/old_images/bullet1.png b/plane_fighting/old_images/bullet1.png
new file mode 100644
index 0000000..6c4e3d6
Binary files /dev/null and b/plane_fighting/old_images/bullet1.png differ
diff --git a/plane_fighting/old_images/bullet2.png b/plane_fighting/old_images/bullet2.png
new file mode 100644
index 0000000..cc0258e
Binary files /dev/null and b/plane_fighting/old_images/bullet2.png differ
diff --git a/plane_fighting/old_images/bullet_supply.png b/plane_fighting/old_images/bullet_supply.png
new file mode 100644
index 0000000..9cf6fdd
Binary files /dev/null and b/plane_fighting/old_images/bullet_supply.png differ
diff --git a/plane_fighting/old_images/enemy1.png b/plane_fighting/old_images/enemy1.png
new file mode 100644
index 0000000..88774c7
Binary files /dev/null and b/plane_fighting/old_images/enemy1.png differ
diff --git a/plane_fighting/old_images/enemy1_down1.png b/plane_fighting/old_images/enemy1_down1.png
new file mode 100644
index 0000000..fd5af5d
Binary files /dev/null and b/plane_fighting/old_images/enemy1_down1.png differ
diff --git a/plane_fighting/old_images/enemy1_down2.png b/plane_fighting/old_images/enemy1_down2.png
new file mode 100644
index 0000000..69cf644
Binary files /dev/null and b/plane_fighting/old_images/enemy1_down2.png differ
diff --git a/plane_fighting/old_images/enemy1_down3.png b/plane_fighting/old_images/enemy1_down3.png
new file mode 100644
index 0000000..7a9a94c
Binary files /dev/null and b/plane_fighting/old_images/enemy1_down3.png differ
diff --git a/plane_fighting/old_images/enemy1_down4.png b/plane_fighting/old_images/enemy1_down4.png
new file mode 100644
index 0000000..a5d8a84
Binary files /dev/null and b/plane_fighting/old_images/enemy1_down4.png differ
diff --git a/plane_fighting/old_images/enemy2.png b/plane_fighting/old_images/enemy2.png
new file mode 100644
index 0000000..cd3f415
Binary files /dev/null and b/plane_fighting/old_images/enemy2.png differ
diff --git a/plane_fighting/old_images/enemy2_down1.png b/plane_fighting/old_images/enemy2_down1.png
new file mode 100644
index 0000000..93ec9d5
Binary files /dev/null and b/plane_fighting/old_images/enemy2_down1.png differ
diff --git a/plane_fighting/old_images/enemy2_down2.png b/plane_fighting/old_images/enemy2_down2.png
new file mode 100644
index 0000000..c234755
Binary files /dev/null and b/plane_fighting/old_images/enemy2_down2.png differ
diff --git a/plane_fighting/old_images/enemy2_down3.png b/plane_fighting/old_images/enemy2_down3.png
new file mode 100644
index 0000000..37d3d2c
Binary files /dev/null and b/plane_fighting/old_images/enemy2_down3.png differ
diff --git a/plane_fighting/old_images/enemy2_down4.png b/plane_fighting/old_images/enemy2_down4.png
new file mode 100644
index 0000000..1e10fc7
Binary files /dev/null and b/plane_fighting/old_images/enemy2_down4.png differ
diff --git a/plane_fighting/old_images/enemy2_hit.png b/plane_fighting/old_images/enemy2_hit.png
new file mode 100644
index 0000000..463ec69
Binary files /dev/null and b/plane_fighting/old_images/enemy2_hit.png differ
diff --git a/plane_fighting/old_images/enemy3_down1.png b/plane_fighting/old_images/enemy3_down1.png
new file mode 100644
index 0000000..2288724
Binary files /dev/null and b/plane_fighting/old_images/enemy3_down1.png differ
diff --git a/plane_fighting/old_images/enemy3_down2.png b/plane_fighting/old_images/enemy3_down2.png
new file mode 100644
index 0000000..6bd2bab
Binary files /dev/null and b/plane_fighting/old_images/enemy3_down2.png differ
diff --git a/plane_fighting/old_images/enemy3_down3.png b/plane_fighting/old_images/enemy3_down3.png
new file mode 100644
index 0000000..64a6154
Binary files /dev/null and b/plane_fighting/old_images/enemy3_down3.png differ
diff --git a/plane_fighting/old_images/enemy3_down4.png b/plane_fighting/old_images/enemy3_down4.png
new file mode 100644
index 0000000..1592446
Binary files /dev/null and b/plane_fighting/old_images/enemy3_down4.png differ
diff --git a/plane_fighting/old_images/enemy3_down5.png b/plane_fighting/old_images/enemy3_down5.png
new file mode 100644
index 0000000..04e53ba
Binary files /dev/null and b/plane_fighting/old_images/enemy3_down5.png differ
diff --git a/plane_fighting/old_images/enemy3_down6.png b/plane_fighting/old_images/enemy3_down6.png
new file mode 100644
index 0000000..5fc1c90
Binary files /dev/null and b/plane_fighting/old_images/enemy3_down6.png differ
diff --git a/plane_fighting/old_images/enemy3_hit.png b/plane_fighting/old_images/enemy3_hit.png
new file mode 100644
index 0000000..1373efc
Binary files /dev/null and b/plane_fighting/old_images/enemy3_hit.png differ
diff --git a/plane_fighting/old_images/enemy3_n1.png b/plane_fighting/old_images/enemy3_n1.png
new file mode 100644
index 0000000..813cf51
Binary files /dev/null and b/plane_fighting/old_images/enemy3_n1.png differ
diff --git a/plane_fighting/old_images/enemy3_n2.png b/plane_fighting/old_images/enemy3_n2.png
new file mode 100644
index 0000000..5853cf1
Binary files /dev/null and b/plane_fighting/old_images/enemy3_n2.png differ
diff --git a/plane_fighting/old_images/gameover.png b/plane_fighting/old_images/gameover.png
new file mode 100644
index 0000000..2349fb0
Binary files /dev/null and b/plane_fighting/old_images/gameover.png differ
diff --git a/plane_fighting/old_images/life.png b/plane_fighting/old_images/life.png
new file mode 100644
index 0000000..1c071b5
Binary files /dev/null and b/plane_fighting/old_images/life.png differ
diff --git a/plane_fighting/old_images/loading.png b/plane_fighting/old_images/loading.png
new file mode 100644
index 0000000..5968679
Binary files /dev/null and b/plane_fighting/old_images/loading.png differ
diff --git a/plane_fighting/old_images/me1.png b/plane_fighting/old_images/me1.png
new file mode 100644
index 0000000..9517f01
Binary files /dev/null and b/plane_fighting/old_images/me1.png differ
diff --git a/plane_fighting/old_images/me2.png b/plane_fighting/old_images/me2.png
new file mode 100644
index 0000000..18ea8e3
Binary files /dev/null and b/plane_fighting/old_images/me2.png differ
diff --git a/plane_fighting/old_images/me_destroy_1.png b/plane_fighting/old_images/me_destroy_1.png
new file mode 100644
index 0000000..a87e447
Binary files /dev/null and b/plane_fighting/old_images/me_destroy_1.png differ
diff --git a/plane_fighting/old_images/me_destroy_2.png b/plane_fighting/old_images/me_destroy_2.png
new file mode 100644
index 0000000..3429a30
Binary files /dev/null and b/plane_fighting/old_images/me_destroy_2.png differ
diff --git a/plane_fighting/old_images/me_destroy_3.png b/plane_fighting/old_images/me_destroy_3.png
new file mode 100644
index 0000000..215ffb4
Binary files /dev/null and b/plane_fighting/old_images/me_destroy_3.png differ
diff --git a/plane_fighting/old_images/me_destroy_4.png b/plane_fighting/old_images/me_destroy_4.png
new file mode 100644
index 0000000..1e713e9
Binary files /dev/null and b/plane_fighting/old_images/me_destroy_4.png differ
diff --git a/plane_fighting/old_images/pause_nor.png b/plane_fighting/old_images/pause_nor.png
new file mode 100644
index 0000000..f6ef291
Binary files /dev/null and b/plane_fighting/old_images/pause_nor.png differ
diff --git a/plane_fighting/old_images/pause_pressed.png b/plane_fighting/old_images/pause_pressed.png
new file mode 100644
index 0000000..f6ef291
Binary files /dev/null and b/plane_fighting/old_images/pause_pressed.png differ
diff --git a/plane_fighting/old_images/resume_nor.png b/plane_fighting/old_images/resume_nor.png
new file mode 100644
index 0000000..a4db815
Binary files /dev/null and b/plane_fighting/old_images/resume_nor.png differ
diff --git a/plane_fighting/old_images/resume_pressed.png b/plane_fighting/old_images/resume_pressed.png
new file mode 100644
index 0000000..a4db815
Binary files /dev/null and b/plane_fighting/old_images/resume_pressed.png differ
diff --git a/plane_fighting/pyinstaller.spec b/plane_fighting/pyinstaller.spec
new file mode 100644
index 0000000..2d2c17f
--- /dev/null
+++ b/plane_fighting/pyinstaller.spec
@@ -0,0 +1,40 @@
+# -*- mode: python ; coding: utf-8 -*-
+
+
+block_cipher = None
+
+
+a = Analysis(['main.py','bullet.py','enemy.py','myplane.py','supply.py'],
+ pathex=[],
+ binaries=[("font", "images", "sound")]
+ datas=["record.dat"],
+ hiddenimports=[],
+ hookspath=[],
+ hooksconfig={},
+ runtime_hooks=[],
+ excludes=[],
+ win_no_prefer_redirects=False,
+ win_private_assemblies=False,
+ cipher=block_cipher,
+ noarchive=False)
+pyz = PYZ(a.pure, a.zipped_data,
+ cipher=block_cipher)
+
+exe = EXE(pyz,
+ a.scripts,
+ a.binaries,
+ a.zipfiles,
+ a.datas,
+ [],
+ name='Plane Fighting',
+ debug=False,
+ bootloader_ignore_signals=False,
+ strip=False,
+ upx=True,
+ upx_exclude=[],
+ runtime_tmpdir=None,
+ console=False,
+ disable_windowed_traceback=False,
+ target_arch=None,
+ codesign_identity=None,
+ entitlements_file=None )
diff --git a/plane_fighting/record.dat b/plane_fighting/record.dat
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/plane_fighting/record.dat
@@ -0,0 +1 @@
+0
diff --git a/plane_fighting/sound/bullet.wav b/plane_fighting/sound/bullet.wav
new file mode 100644
index 0000000..cb97090
Binary files /dev/null and b/plane_fighting/sound/bullet.wav differ
diff --git a/plane_fighting/sound/button.wav b/plane_fighting/sound/button.wav
new file mode 100644
index 0000000..f7b246f
Binary files /dev/null and b/plane_fighting/sound/button.wav differ
diff --git a/plane_fighting/sound/enemy1_down.wav b/plane_fighting/sound/enemy1_down.wav
new file mode 100644
index 0000000..2baa2d2
Binary files /dev/null and b/plane_fighting/sound/enemy1_down.wav differ
diff --git a/plane_fighting/sound/enemy2_down.wav b/plane_fighting/sound/enemy2_down.wav
new file mode 100644
index 0000000..b72fa43
Binary files /dev/null and b/plane_fighting/sound/enemy2_down.wav differ
diff --git a/plane_fighting/sound/enemy3_down.wav b/plane_fighting/sound/enemy3_down.wav
new file mode 100644
index 0000000..f7c59fb
Binary files /dev/null and b/plane_fighting/sound/enemy3_down.wav differ
diff --git a/plane_fighting/sound/enemy3_flying.wav b/plane_fighting/sound/enemy3_flying.wav
new file mode 100644
index 0000000..6c57d7d
Binary files /dev/null and b/plane_fighting/sound/enemy3_flying.wav differ
diff --git a/plane_fighting/sound/game_music.ogg b/plane_fighting/sound/game_music.ogg
new file mode 100644
index 0000000..97b59d2
Binary files /dev/null and b/plane_fighting/sound/game_music.ogg differ
diff --git a/plane_fighting/sound/get_bomb.wav b/plane_fighting/sound/get_bomb.wav
new file mode 100644
index 0000000..541933f
Binary files /dev/null and b/plane_fighting/sound/get_bomb.wav differ
diff --git a/plane_fighting/sound/get_bullet.wav b/plane_fighting/sound/get_bullet.wav
new file mode 100644
index 0000000..39e4844
Binary files /dev/null and b/plane_fighting/sound/get_bullet.wav differ
diff --git a/plane_fighting/sound/loading_game.ogg b/plane_fighting/sound/loading_game.ogg
new file mode 100644
index 0000000..97b59d2
Binary files /dev/null and b/plane_fighting/sound/loading_game.ogg differ
diff --git a/plane_fighting/sound/me_down.wav b/plane_fighting/sound/me_down.wav
new file mode 100644
index 0000000..8ecab0f
Binary files /dev/null and b/plane_fighting/sound/me_down.wav differ
diff --git a/plane_fighting/sound/supply.wav b/plane_fighting/sound/supply.wav
new file mode 100644
index 0000000..a184de9
Binary files /dev/null and b/plane_fighting/sound/supply.wav differ
diff --git a/plane_fighting/sound/upgrade.wav b/plane_fighting/sound/upgrade.wav
new file mode 100644
index 0000000..b856b32
Binary files /dev/null and b/plane_fighting/sound/upgrade.wav differ
diff --git a/plane_fighting/sound/use_bomb.wav b/plane_fighting/sound/use_bomb.wav
new file mode 100644
index 0000000..4c60777
Binary files /dev/null and b/plane_fighting/sound/use_bomb.wav differ
diff --git a/plane_fighting/supply.py b/plane_fighting/supply.py
new file mode 100644
index 0000000..70d7986
--- /dev/null
+++ b/plane_fighting/supply.py
@@ -0,0 +1,51 @@
+import pygame,os
+from random import *
+
+abspath = os.getcwd() + "/"
+class Bullet_Supply(pygame.sprite.Sprite):
+ def __init__(self, bg_size):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.image = pygame.image.load(abspath + "images/bullet_supply.png").convert_alpha()
+ self.rect = self.image.get_rect()
+ self.width, self.height = bg_size[0], bg_size[1]
+ self.rect.left, self.rect.bottom = \
+ randint(0, self.width - self.rect.width), -100
+ self.speed = 5
+ self.active = False
+ self.mask = pygame.mask.from_surface(self.image)
+
+ def move(self):
+ if self.rect.top < self.height:
+ self.rect.top += self.speed
+ else:
+ self.active = False
+
+ def reset(self):
+ self.active = True
+ self.rect.left, self.rect.bottom = \
+ randint(0, self.width - self.rect.width), -100
+
+class Bomb_Supply(pygame.sprite.Sprite):
+ def __init__(self, bg_size):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.image = pygame.image.load(abspath + "images/bomb_supply.png").convert_alpha()
+ self.rect = self.image.get_rect()
+ self.width, self.height = bg_size[0], bg_size[1]
+ self.rect.left, self.rect.bottom = \
+ randint(0, self.width - self.rect.width), -100
+ self.speed = 5
+ self.active = False
+ self.mask = pygame.mask.from_surface(self.image)
+
+ def move(self):
+ if self.rect.top < self.height:
+ self.rect.top += self.speed
+ else:
+ self.active = False
+
+ def reset(self):
+ self.active = True
+ self.rect.left, self.rect.bottom = \
+ randint(0, self.width - self.rect.width), -100
diff --git a/python_https_server/README.md b/python_https_server/README.md
new file mode 100644
index 0000000..809e9e9
--- /dev/null
+++ b/python_https_server/README.md
@@ -0,0 +1,8 @@
+# Python HTTPS Server (python_https_server)
+## 简介
+一个 HTTPS 网络服务器程序
+## 支持
+需要一个证书
+基于 Python 运行
+## 协议
+本目录中所有的源代码文件根据 MIT 协议开源
\ No newline at end of file
diff --git a/python_https_server/https_svr_key.pem b/python_https_server/https_svr_key.pem
new file mode 100644
index 0000000..e706fbb
--- /dev/null
+++ b/python_https_server/https_svr_key.pem
@@ -0,0 +1,49 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCe+wWQgjueNm66
+zGE85YViKACs3wL786toKY03mreqvQ6Ffz4tTfXtJdFuFem4n+FEUp9SKhpaGPxN
+mX7cRX/v+6jqkYDOMvyp9w2y/t0rTivSsJr8micFmmRN/gpJH8Ma9Zl28hjPYS8c
+8gCnIevk/we1vd/IZYCMnRQKuTHh1kUWgBLuRDEwsD2Ka7iVVvonDZMJye42IHoG
+PO+bif1SBDkW8NkX4TFg0iFKxeplLqAVVx5hgs8pMGjgvGp1HIRJdOcTurXWZIHM
+cr9nAALRriOA76BOOOYvuljPqf8oPAVqiP+bHHRWNGaeVwAZnGRB369SZbaO9CmZ
+rf4Xk2pXAgMBAAECggEACYTWLHTfxPVVY/Hg0Jidh+cFQ1SHBTbtyGrUfcPRw3NW
+bz/TJTtJwk1FYOYG/Hr2LfUUfQLwWPyt/qd2JRI0OtZCoujbYX1EC5kzRMhlzbX8
+gbz5Sq6gL4GzB8hyLTato+uYqLqOKbyT6ZPD3j31tdxfRc58m68YJ1MwZAP6rJ7j
+kUGmgg2OlQp7X0EJE5ivDHNYNlluAGD0uLZuyt5+3WnK/ms7sySVBg8BIipS/iQj
+vv01VlanQNZGYrZurJ8s1PjRyDR/1HI6HjJPCt7XD6LLKla7KV+IBI0tXbkZ7tAw
+UYQaKBB4R9elqhgxIAU5xbhqmqlXp/diucLb4S4awQKBgQDPQcfQq030JXvL6eWx
+veN34AWHyi88Ipi5ildJJr/bmIJH6/p8SqhrVHaEzjATDYNAfyRnxLcLgsEVMkl6
+njZKt4FKVXaCKHJfksnmHrrBnhSzpvL8OWL9rZDqBqLRjQ3FmwtF6uiPIbaoY33+
+X/MiYCC/Bdo+yQbvHUekoGb03wKBgQDEXq/sbPjOfSyWkeIfl2bPcnSPLsu7nR+O
+ywXHxh/ftUoSCOR6qCW2er3IxfMwTIE8agitgi3H29Tj7UlaohCqjjDB/lA0I8PG
+3LsI9fIk20ZE+wE9hJxoHJI2fXM8v1DAnNZ49bUMEUQ75epH6L3BjyPoh8kp7BbO
+X9obnaqBiQKBgECiTQQgSCE5h0/iU4WIqGV78X2VagGg8Gv8Xpgrg22iNA7l4qnc
+RoWiQ4vLGWb3sdTtUZci28q1Li3EDvI0YM4QSDu8R0b0AicYCeq/7pHvEJmuGNzb
+sKlX9XdmNmSPTpovbeaSCZCJfQMqc+JeXd58h/nKg3NNEeKECRGoDDOVAoGAVK9d
+AQHxvuMeooShVuxtKxN6DvGobO2S2XrWsFPSFSDSo7pwBjGTqgF+7SHpAbBMn6g+
+u80DP0ifo/gGBW8U7ujJQDATmJi/6nfwtSmT1q81u7Pf0g7pgMCpkZRCaTU8dwRs
+PdgAzwZ3PbmmcoJ9qwa2/qXobArjvvZ5UiWJjbkCgYBN0hspwEszCUmeGdRBgQGf
+yM9YHeqx+N1PeH2M64l7XcYN5fp/g//3CRDrOjuYtVEN/FImYPEVZ9ZgLY2DTSDT
+VDk6TGD7mkn6rGMq6z7ik7Zwp4oP4TIuIHogglpuKmFu3YO7DYfBBcL104vYcTEo
+unsnUGiTNNfxctLK/2yKcQ==
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIDazCCAlOgAwIBAgIULxW2C/o4zLPTG+pNAzPBCFSEnAEwDQYJKoZIhvcNAQEL
+BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
+GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMjAzMDIxNTQ4MzVaFw0zMjAy
+MjgxNTQ4MzVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
+HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCe+wWQgjueNm66zGE85YViKACs3wL786toKY03mreq
+vQ6Ffz4tTfXtJdFuFem4n+FEUp9SKhpaGPxNmX7cRX/v+6jqkYDOMvyp9w2y/t0r
+TivSsJr8micFmmRN/gpJH8Ma9Zl28hjPYS8c8gCnIevk/we1vd/IZYCMnRQKuTHh
+1kUWgBLuRDEwsD2Ka7iVVvonDZMJye42IHoGPO+bif1SBDkW8NkX4TFg0iFKxepl
+LqAVVx5hgs8pMGjgvGp1HIRJdOcTurXWZIHMcr9nAALRriOA76BOOOYvuljPqf8o
+PAVqiP+bHHRWNGaeVwAZnGRB369SZbaO9CmZrf4Xk2pXAgMBAAGjUzBRMB0GA1Ud
+DgQWBBQw7XwOekH/mm4y2oSuQ4FFrfqPPjAfBgNVHSMEGDAWgBQw7XwOekH/mm4y
+2oSuQ4FFrfqPPjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB/
++bSYD+p8vnxB5U5tjV+S7Sw1tXEPkwCNdX/fRXh0waFQ9WIkttbHXwPK2/DurgOE
+uG9fU3XMTWpOzSisDIRlySerxfunZM63nB/GnW7SnyqfcUBXZHU875Gsdvt3ZNIi
+RoH/Wvkc8S5taUMzg/gxaEe2Ss52cvR1TfqWz0WtkyVcaX8TF3q0niecznimiRMc
+ptUw19v0KM5JbPLdZYPXZehBFdy79wzlBvqScKglNguXF4Hfjqagox+PPzO1HEJk
+z8GSMfZSm7ayDIJk4bkGZ+KFJZil1wM3hf0QQlZVNZexv6Wv+vyXkpl8Ext5Jb0k
+1+KOgCJmsCXJZ+D0OeqQ
+-----END CERTIFICATE-----
diff --git a/python_https_server/main.py b/python_https_server/main.py
new file mode 100644
index 0000000..9985305
--- /dev/null
+++ b/python_https_server/main.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+# taken from https://gist.github.com/dergachev/7028596
+#
+# generate server.xml with the following command:
+# openssl req -new -x509 -keyout https_svr_key.pem -out https_svr_key.pem -days 3650 -nodes
+#
+# run as follows:
+# python https_svr.py
+#
+# then in your browser, visit:
+# https://localhost:4443
+#
+
+import BaseHTTPServer
+import SimpleHTTPServer
+import os
+import socket
+import ssl
+
+script_home = os.path.dirname(os.path.abspath(__file__))
+ip = [(s.connect(('1.1.1.1', 53)), s.getsockname()[0], s.close()) \
+ for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]
+port = 443
+
+def main():
+ print ("simple https server, address:%s:%d, document root:%s" % (ip, port, script_home))
+
+ httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', port), SimpleHTTPServer.SimpleHTTPRequestHandler)
+ httpd.socket = ssl.wrap_socket(httpd.socket, certfile='./https_svr_key.pem', server_side=True)
+ httpd.serve_forever()
+
+if __name__ == '__main__':
+ os.chdir(script_home)
+ main()