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 + "

注意:
1:您当前以[" + getpass.getuser() + "]用户查看文件(您或许对某些文件没有查看权限)
2:选择文件上传后,如文件较大,请只点击一次按钮直到页面刷新
").encode()) + f.write(b"
\n") + f.write(b"
") + f.write(b"") + f.write(b"
\n") + f.write(b"
\n") + f.write(b'[PARENTDIR]   \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()