python之星河战争游戏

效果图:

开始界面:
python之星河战争游戏_第1张图片
游戏中:
python之星河战争游戏_第2张图片
gameover!

文件结构:

python之星河战争游戏_第3张图片

  • game_file:所有游戏逻辑相关的源码;
  • rec:游戏相关的图片、音乐资源;
  • main.py: 游戏的启动文件;

所用到的图片:
python之星河战争游戏_第4张图片
源码和文件我会放到文末,感兴趣的自取。

源码及注释:

game_windows.py 游戏运行的主函数模块,所有的顶层函数

# coding=utf-8

import time
import math
import sys

import pygame
from pygame.locals import *

from .resource_game import *
from . import setting as st

# 创建一个敌机机型的字典
dict_enemy = {
     '0': st.ENEMY_1, '1': st.ENEMY_2, '2': st.ENEMY_3}
fps1 = 0  # 开始按钮计数器
fps2 = 0
fps6 = 0
ran3 = 0
num = 0  # 减慢移动的计数器
num_shower = 0  # 创建流星雨的帧数计数器和循环次数的计数器


def main():  # 定义一个游戏运行的主函数
    fps = 0  # 创建帧数计数器
    fps4 = 0
    fps5 = 0
    f = 0
    time1 = time.time()
    buttons = ()  # 登陆界面按钮的元组
    buttons1 = ()  # 用来放结束界面的按钮

    pygame.init()  # 系统初始化
    # 创建一个全屏的屏幕对象
    screen = pygame.display.set_mode((st.SCREEN_WIDTH, st.SCREEN_HIGHT), 0, 32)
    pygame.display.set_caption("星河战争-天宇之游")
    screen.get_rect()  # 获取屏幕矩形
    # 创建一个敌机生成器
    EnemyCreate = enemy_create(screen)
    # 创建一个文字显示效果生成器
    Chars = chars(screen)
    game_before(screen)  # 加入游戏界面元素
    st.GAME_BEFORE = True  # 打开游戏前言开关

    while True:  # 开始游戏主循环
        mouse_x, mouse_y = pygame.mouse.get_pos()  # 获取光标的位置
        if st.GAME_BEFORE:  # 游戏进入前言
            key_quit()  # 检测退出按键
            if fps % st.FRAMES == 0:  # 每过帧数显示一个字
                try:
                    next(Chars)
                except StopIteration:
                    pass
            fps += 1
            if fps == st.WIN_OVER_FRAMES:
                fps = 0  # 计数器还原
                cls()  # 清空子弹、删除、界面元素列表
                buttons = game_load(screen)  # 加入登陆界面元素,返回三个按钮的元组
                bc(k2=True)  # 打开游戏界面控制开关

        elif st.SCREEN_CHANGE:  # 游戏界面控制开关
            # 界面按钮遍历检测
            mc(buttons, mouse_x, mouse_y)
            key_load(screen, mouse_x, mouse_y)  # 按键的控制函数

        elif st.GAME_SAY:  # 游戏前言
            key_quit()  # 检测窗口退出按键
            fps5 += 1
            if fps5 == st.WIN_FONT_FRAMES:
                bc(k4=True)  # 打开战斗界面控制开关
                fps5 = 0  # 计数器还原
                cls()  # 清空子弹、删除、界面元素列表
                beijing_1, hero_me = game_fight(screen)  # 加入游戏元素

        elif st.GAME_FIGHT:  # 进入战斗界面
            # 创建一个开关字典用来指示上下左右方向
            dict_key = {
     st.KEY_UP: 'up',
                        st.KEY_DOWN: 'down',
                        st.KEY_LEFT: 'left',
                        st.KEY_RIGHT: 'right'
                        }
            buttons = key_fight(screen, hero_me)  # 战斗界面的控制函数
            # 创建敌机随机生成器
            fps += 1
            if st.GAME_MOSHI:  # 判断目前的游戏模式
                ps = st.ENEMY_CREATE1
            else:
                ps = st.ENEMY_CREATE2
            if fps % ps == 0:  # 每循环ps次执行
                enemy_make(screen, EnemyCreate)  # 敌机的生产控制
            boss_make(screen)  # boss飞机的产生
            buff_make()  # buff有效时间控制
            move_make(dict_key, hero_me)  # 通过开关字典控制飞机的移动
            if st.ENEMY_START:  # 在boss飞机出现后才检测
                if boss_die():  # boss是否死光
                    buttons1 = go_game_end(screen)  # 加载结束界面得到按钮

        elif st.GAME_END:  # 进入结束界面
            # 界面按钮遍历检测
            mc(buttons1, mouse_x, mouse_y)
            # 按钮控制
            buttons = key_end(screen, mouse_x, mouse_y)
        # 计算帧数的速度
        time2 = time.time()
        fps4 += 1
        if time2 - time1 >= 1:
            time1 = time2
            print(fps4 - f)
            f = fps4

        loop()  # 元素循环显示和清空
        pygame.display.update()  # 更新屏幕
        time.sleep(0.01)  # 休眠0.01秒


def buttons_control(k1=False, k2=False,
                    k3=False, k4=False, k5=False):
    """所有相关界面的开关管理,全部默认关闭"""
    st.GAME_BEFORE = k1  # 游戏进入前的界面控制开关
    st.SCREEN_CHANGE = k2  # 登陆界面开关
    st.GAME_SAY = k3  # 游戏历史背景开关
    st.GAME_FIGHT = k4  # 战斗界面控制开关
    st.GAME_END = k5  # 游戏结束界面控制开关
bc = buttons_control


def mouse_control(buttons, mouse_x, mouse_y):
    """界面按钮的检测函数"""
    try:
        for button in buttons:  # 将光标的坐标传入对象检测开关是否应该打开
            button.mouse_make(mouse_x, mouse_y)
    except Exception as re:
        print(re)
mc = mouse_control


def key_quit():
    """检测是否按了退出键"""
    for event in pygame.event.get():  # 键盘和鼠标事件的监听
        if event.type == pygame.QUIT:  # 检测是否按了窗口的退出按键
            sys.exit()


def key_end(screen, mouse_x, mouse_y):
    """游戏结束后统计界面的按键控制函数"""
    for event in pygame.event.get():  # 键盘和鼠标事件的监听
        # 检测是否按了窗口的退出按键
        if event.type == pygame.QUIT:
            sys.exit()
        # 判断是否按下了鼠标并且光标在按钮范围内
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if 20 <= mouse_x <= 620:
                print(mouse_x)
                print(mouse_y)
                if 200 <= mouse_y <= 285:  # 按下了下一关按钮
                    # st.GAME_MOSHI = True
                    pass
                elif 350 <= mouse_y <= 435:  # 按下了重新开始按钮
                    bc(k2=True)  # 打开登陆界面开关
                    cls()  # 清空子弹、删除、界面元素列表
                    # 将敌机死亡的数量重新设置为0
                    EnemyPlane.set_enemy_die(True)
                    buttons = game_load(screen)  # 加载登陆界面元素

                    return buttons
                elif 500 <= mouse_y <= 585:  # 按下了退出按钮
                    exit()


def key_load(screen, mouse_x, mouse_y):
    """游戏开始前的设置界面的按键控制函数"""
    for event in pygame.event.get():  # 键盘和鼠标事件的监听
        # 检测是否按了窗口的退出按键
        if event.type == pygame.QUIT:
            sys.exit()
        # 判断是否按下了鼠标并且光标在按钮范围内
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if 220 <= mouse_x <= 420:
                print(mouse_x)
                print(mouse_y)
                if 300 <= mouse_y <= 340:  # 按下了标准模式按钮
                    st.GAME_MOSHI = True
                elif 400 <= mouse_y <= 440:  # 按下了困难模式按钮
                    st.GAME_MOSHI = False
                elif 200 <= mouse_y <= 240:  # 按下了退出按钮
                    exit()

            # 按下了进入游戏按钮
            if 230 <= mouse_x <= 412 and 500 <= mouse_y <= 695:
                print("执行成功")
                cls()  # 清空子弹、删除、界面元素列表
                game_say(screen)  # 加入历史背景界面
                bc(k3=True)  # 游戏历史背景开关打开
                st.ENEMY_MAKE = True  # 重新打开敌机生成器的开关


def key_fight(screen, hero_me):
    """一个战斗界面的按键检测控制函数 """
    for event in pygame.event.get():  # 键盘和鼠标事件的监听
        if event.type == pygame.QUIT:  # 检测是否按了窗口的退出按键
            sys.exit()
        elif event.type == pygame.KEYDOWN:  # 判断是否按下了键盘
            # 是否按下W键或up键
            if event.key == pygame.K_w or event.key == pygame.K_UP:
                st.KEY_UP = True  # 打开开关
            # 是否按下s or down
            elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
                # 打开向下移动的开关
                st.KEY_DOWN = True
            # 是否按下a or left
            elif event.key == pygame.K_a or event.key == pygame.K_LEFT:
                # 打开向左移动的开关
                st.KEY_LEFT = True
            # 是否按下d or right
            elif event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                # 打开向右移动的开关
                st.KEY_RIGHT = True
            # 判断是否按下了Q键
            elif event.key == pygame.K_q:
                bc(k2=True)  # 打开登陆界面开关
                cls()  # 清空子弹、删除、界面元素列表
                # 将敌机死亡的数量重新设置为0
                EnemyPlane.set_enemy_die(True)
                buttons = game_load(screen)  # 加载登陆界面元素
                return buttons

        elif event.type == pygame.KEYUP:  # 是否放开了键盘
            if event.key == pygame.K_w or event.key == pygame.K_UP:
                # 关闭开关
                st.KEY_UP = False
            elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
                # 关闭向下移动的开关
                st.KEY_DOWN = False
            elif event.key == pygame.K_a or event.key == pygame.K_LEFT:
                # 关闭向左移动的开关
                st.KEY_LEFT = False
            elif event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                # 关闭向右移动的开关
                st.KEY_RIGHT = False

        if event.type == pygame.MOUSEBUTTONDOWN:  # 判断是否按下了鼠标
            if hero_me.get_fire():  # 如果发射子弹的开关是打开的
                hero_me.fire()  # 将子弹列表的元素加入显示列表


def go_game_end(screen):
    """游戏结束的界面控制"""
    global fps6
    if st.ENEMY_START and st.BOSS_DIE:  # 如果boss产生了但又死光
        fps6 += 1  # 计数器启动
        if fps6 == 300:
            cls()  # 清空子弹、删除、界面元素列表
            buttons = game_end(screen)  # 加载结束界面
            bc(k5=True)  # 打开结束界面开关
            st.ENEMY_START = False  # 关闭boss检测开关
            st.BOSS_DIE = False  # 关闭boss死光开关
            return buttons


def game_end(screen):
    """对方大boss死亡后出现结束界面"""
    # 创建背景图片
    Factory.beijing_act(0, 0, screen, st.MY_TEXT)
    # 创建退出游戏按钮
    button_4 = Factory.button1_act(20, 500, screen, st.BUTTON_D)
    # 创建重新开始按钮
    button_5 = Factory.button1_act(20, 350, screen, st.BUTTON_E)
    # 创建下一关按钮
    button_6 = Factory.button1_act(20, 200, screen, st.BUTTON_F)
    # 创建积分界面画布
    Factory.beijing_act(640, 0, screen, st.IMAGE_BJ)
    integ(screen)  # 创建统计信息标签
    return button_4, button_5, button_6


def game_say(screen):
    """显示一段文字"""
    # 创建一个星空背景
    Factory.beijing_act(0, 0, screen, st.MY_TEXT)
    text = "公元2300年,外星人入侵,这是人类的最后时刻!"
    Factory.script_act(20, 300, screen, text, 30, num=3,
                       filename=st.SCRIPT, bg_script=(255, 255, 255))


def enemy_make(screen, EnemyCreate):
    """敌机生成控制函数"""
    if st.ENEMY_MAKE:  # 生成器开关默认是打开的
        enemy_plane = None
        stony = None
        try:
            # 若未达到敌机死亡的上限
            if EnemyPlane.get_enemy_die() < st.ENEMY_NUM:
                enemy_plane = next(EnemyCreate)  # 敌机生成
                stony = stony_creat(screen)  # 陨石生成
            else:
                st.BOSS_CREAT = True
                st.ENEMY_MAKE = False  # 关闭生成器的开关
        except StopIteration:
            enemy_plane = None
            stony = None

        try:
            if enemy_plane:  # 如果不为空
                screen_list.append(enemy_plane)  # 加入显示列表

            if stony:  # 如果不为空
                screen_list.append(stony)
        except Exception as re:
            print(re)


def boss_make(screen):
    """敌机boss的生成控制"""
    global fps2
    if st.BOSS_CREAT:  # 创建boss
        fps2 += 1
        # print(fps2)
        if fps2 == 100:
            for i in range(st.BOSS_NUM):
                Factory.enemy_act(300, -200, screen, dict_enemy['2'])
            fps2 = 0
            st.BOSS_CREAT = False  # 关闭创建boss的开关
            st.ENEMY_START = True  # 打开检测boss飞机的开关


def boss_die():
    """所有的boss是否死亡检测"""
    boss_button = True  # 开始默认打开的
    for ele in screen_list:  # 如果遍历一次后发现还存在boss飞机,则关闭
        if isinstance(ele, BossEnemy):
            boss_button = False
    if boss_button:  # 如果没有boss飞机了
        st.BOSS_DIE = True
    return st.BOSS_DIE


def buff_make():
    """各种buff子弹有效时间计数函数"""
    if st.GOD_BUFF:  # 金币子弹buff出现,大于500帧数后消失
        st.BUFF_TIME += 1
        if st.BUFF_TIME >= 500:
            st.GOD_BUFF = False

    if st.LASER_BUFF:  # 激光子弹buff出现,大于500帧数后消失
        st.LASER_TIME += 1
        if st.LASER_TIME >= 500:
            st.LASER_BUFF = False

    if st.RAN_BUFF:  # 随机子弹buff出现
        st.RAN_TIME += 1
        if st.RAN_TIME >= 500:
            st.RAN_BUFF = False


def move_make(dict_key, hero_me):
    """控制飞机移动的方法"""
    global num
    for item in dict_key.items():  # 通过开关控制我方飞机移动
        if item[0]:
            # print(item[0])
            num += 1
            if num > 2:
                hero_me.hreo_move(item[1])
                num = 0


def clear_list():
    """清除相关列表中的元素函数"""
    bullet_list.clear()  # 清除发射出的列表
    bullet_del.clear()  # 清空该删除的列表
    screen_list.clear()  # 清空界面元素


cls = clear_list


def loop():
    """抽取主函数中循环的代码"""
    screen_list.extend(bullet_list)  # 将敌机产生的子弹加入显示列表
    # print(len(bullet_list))
    bullet_list.clear()  # 清除列表

    for bu in bullet_del:  # 从显示列表中删除应该消失的子弹
        if bu in screen_list:
            screen_list.remove(bu)
    bullet_del.clear()  # 清空列表

    for element in screen_list:  # 循环显示所有对象,默认多态
        element.draw()
        # print(len(screen_list))
        # print(screen_list)


def game_load(screen):
    """创建游戏登陆界面需要的图像"""
    # 创建开始界面背景
    Factory.beijing_act(0, 0, screen, st.BEIJING_2)
    # 创建积分界面
    Factory.beijing_act(640, 0, screen, st.IMAGE_BJ)
    # 创建游戏操作说明
    Factory.beijing_act(120, 50, screen, st.FUNCTION_1)
    # 创建标准模式按钮
    button1 = Factory.button1_act(220, 300, screen, st.BUTTON_A)
    # 困难模式按钮
    button2 = Factory.button1_act(220, 400, screen, st.BUTTON_B)
    # 退出按钮
    button3 = Factory.button1_act(220, 200, screen, st.BUTTON_C)
    # 生产一个开始按钮并加入显示列表
    Factory.button_act(230, 500, screen, st.BUTTON_START)

    integ(screen)  # 创建统计信息标签
    Factory.music_act(st.START_MUSIC)  # 游戏的开始音乐
    # print(len(screen_list))
    # print(len(list_game))
    return button1, button2, button3


def integ(screen):
    """创建游戏统计信息的显示文字"""
    # 取得一个随机数
    ran = random.randint(0, 4)
    # 创建角色头像标签
    Factory.beijing_act(640, 0, screen, st.BOY_IMAGE[ran])
    # 创建分数标签
    Factory.script_act(655, 325, screen, "分数", 50,
                       filename=st.SCRIPT, bg_script=(0, 255, 255))
    # 创建角色标签
    Factory.script_act(655, 150, screen, "角色", 50,
                       filename=st.SCRIPT, bg_script=(0, 255, 255))
    # 创建排名标签
    Factory.script_act(655, 500, screen, "排名", 50,
                       filename=st.SCRIPT, bg_script=(0, 255, 255))


def game_before(screen):
    """创建游戏之前的界面图像"""
    # 有主背景图片、飞机大战题目图片、游戏发言图片、作者图片、积分界面图片
    beijing_before = [[0, 0, st.MY_XING],
                      [100, 200, st.MY_READ],
                      [450, 380, st.MY_SELF],
                      [640, 0, st.IMAGE_BJ]
                      ]
    # "保护地球人人有责"的坐标列表
    script_before = ["保", "护", "地", "球", "人", "人", "有", "责"]
    for i, bj in enumerate(beijing_before):
        # 创建所有界面元素并添加
        Factory.beijing_act(bj[0], bj[1], screen, bj[2])
    for j, sb in enumerate(script_before):
        # 创建文字对象
        Factory.script_act(660, 10 + j * 83, screen, sb, 80, filename=st.SCRIPT1)

    Factory.music_act(st.START_MUSIC)  # 创建并播放音乐


def chars(screen):
    """显示“星河战争“四个字的动态效果生成器"""
    list_char = [(120, "星"), (220, "河"), (320, "战"), (420, "争")]

    for tp in list_char:
        # 创建一个文字
        script = Factory.script_act(tp[0], 100, screen, tp[1], 120, num=1, color=(0, 0, 255))
        # 创建一个爆炸
        Factory.any_blast(script, "big", 2)
        yield script


def game_fight(screen):
    """创建游戏战斗需要的图像并加载"""
    # 创建一个战斗界面背景
    beijing_1 = Factory.beijing_act(0, 0, screen, st.BEIJING_1)
    # 创建积分界面
    Factory.beijing_act(640, 0, screen, st.IMAGE_BJ)
    integ(screen)  # 创建统计信息标签
    # 创建我方飞机并设置初始位置
    hero_me = Factory.hreo_act(270, 600, screen, st.HREO_1)
    hero_me.button_fire = True  # 将我方飞机的开火开关打开
    return beijing_1, hero_me


def enemy_create(screen):
    """敌机的生成器,使用了迭代器的方式"""
    i = 0
    while i < 500:
        ran1 = random.randint(0, 2)  # 生成敌机的 出生位置
        ranx = random.randint(0, 20)  # 调整敌机生成的概率
        if ranx <= 14:
            ran2 = 0
        else:
            ran2 = 1
        # 创建敌方飞机
        enemy_plane = EnemyPlane(100 + ran1 * 200, -100, screen, dict_enemy[str(ran2)])
        yield enemy_plane
        i += 1
        # st.BOSS_CREAT = True


def stony_creat(screen):
    """陨石生成器"""
    ran1 = random.randint(0, 2)  # 生成出生位置
    ran2 = random.randint(0, 10)  # 设置出生概率
    if ran2 <= 2:  # 20%的出生概率
        stony_one = Stony(250 + ran1 * 100, -100, screen, st.STONY_BUFF)
        return stony_one
    else:
        return False


def delay_time(delay, time0=time.time()):
    """一个延时函数"""
    time1 = time.time()
    if time1 - time0 >= delay:
        return True
    else:
        return False


if __name__ == '__main__':
    pass

resource_game.py 所有的元素类和功能类模块

import random
import pygame
from . import setting as st
from game_file.tool import *


screen_list = []  # 创建一个显示列表全局
bullet_list = []  # 创建一个显示子弹的全局列表
bullet_del = []  # 创建一个该删除的元素列表
num1 = 0  # 创建一个爆炸效果的计数器


class Obj(object):
    """创建一个父类1"""
    # 构造位置属性
    def __init__(self, x, y, screen, filename):
        self.x = x
        self.y = y
        self.screen = screen
        self.name = filename
        self.image_1 = pygame.image.load_extended(self.name)  # 加载背景图片
        self.rect = self.image_1.get_rect()  # 获取图片的外接矩形

    def draw(self):  # 设置绘制的功能
        pass


class ScriptBase(Obj):
    """创建一个文字基类"""

    def __init__(self, x, y, screen, script, size,
                 filename=st.SCRIPT, color=(255, 255, 255),
                 bool_sc=True, bg_script=None):
        """
        构造函数,初始化文字的位置x,y,显示的窗口screen,文字script,
        字体大小size,字体的TTF文件filename,字体的颜色color,默认开启抗锯齿True,
        不定长参数为是否设置字的背景bg_script
        """
        self.x = x
        self.y = y
        self.screen = screen
        self.script = script
        self.size = size
        self.name = filename
        self.color = color
        self.bool_sc = bool_sc
        self.bg_script = bg_script

    def sc_act(self):
        """创建文字的函数"""
        # 创建一个文字对象
        my_font = pygame.font.Font(self.name, self.size)
        # 文件对象的显示参数
        text_surface = my_font.render(self.script, self.bool_sc,
                                      self.color, self.bg_script)
        return text_surface

    def draw(self):
        text = self.sc_act()
        # 显示创建的文字对象
        self.screen.blit(text, (self.x, self.y))

    def change_size(self):
        """文字的效果,如大小闪烁,移动变化等"""
        pass

    def change_color(self):
        pass


class ScriptNew(ScriptBase):
    """创建基本的文字"""
    def __init__(self, x, y, screen, script, size, *args):
        super().__init__(x, y, screen, script, size, *args)
        # 创建一个文字对象
        self.my_font = pygame.font.Font(self.name, self.size)
        # 文件对象的显示参数
        self.text_surface = self.my_font.render(self.script, self.bool_sc,
                                                self.color, self.bg_script)

    def draw(self):
        # 显示创建的文字对象
        self.screen.blit(self.text_surface, (self.x, self.y))


class ScriptLong(ScriptBase):
    """创建大段依次显示的文字"""
    def __init__(self, x, y, screen, script, size, *args):
        super().__init__(x, y, screen, script, size, *args)
        # 创建一个文字对象
        self.my_font = pygame.font.Font(self.name, self.size)
        self.fps = 0
        # 单个文字对象
        self.t = None
        # 创建一个文字图像列表
        self.text = []
        for x in range(len(self.script)):  # 创建单个的文字图像
            t = self.my_font.render(self.script[:x+1], self.bool_sc,
                                    self.color, self.bg_script)
            self.text.append(t)
        self.it = iter(self.text)  # 获得迭代器

    def draw(self):
        self.fps += 1
        if self.fps % 20 == 0:  # 每隔5帧数显示一个文字
            try:
                self.t = next(self.it)
            except StopIteration:
                pass
        if self.t:  # 如果对象不为空
            self.screen.blit(self.t, (self.x, self.y))


class ScriptMove(ScriptBase):
    """创建一个的大小变化和闪烁效果"""
    def __init__(self, x, y, screen, script, size, *args):
        super().__init__(x, y, screen, script, size, *args)
        # 创建一个闪烁速度的计数器
        self.fps = 0
        # 字体尺寸最小
        self.least = 80
        # 字体最大
        self.max = size
        # 设置变化的颜色
        self.list_color = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]

    def draw(self):
        self.fps += 1
        super().draw()
        if self.fps >= 20:  # 20帧数后开始变化
            self.change_size()  # 改变文字大小
            self.change_color()  # 改变文字颜色

    def change_size(self):
        """重写父类的方法"""
        # print("change执行了")
        if self.fps % 2 == 0 and self.size > self.least:  # 每过5帧数执行一次
            self.size -= 2
            self.x += 1
            self.y += 1
            # if self.size <= self.least:  # 达到最小时还原大小
            #     self.size = self.max

    def change_color(self):
        """文字颜色红绿蓝三色变化"""
        if self.fps % 5 == 0:
            ran = random.randint(0, 2)
            self.color = self.list_color[ran]


class ScriptEnd(ScriptBase):
    """创建一个文字由小到大的效果"""
    def __init__(self, x, y, screen, script, size, *args):
        super().__init__(x, y, screen, script, size, *args)
        # 创建一个闪烁速度的计数器
        self.fps = 0

    def change_size(self):
        if self.fps % 2 == 0 and self.size < 180:  # 每过5帧数执行一次
            self.size += 3
            self.x -= 1
            self.y -= 1

    def draw(self):
        self.fps += 1
        super().draw()
        self.change_size()


class ButtonGame(Obj):
    """创建一个游戏开始按钮"""

    def __init__(self, x, y, screen, list_image):
        self.x = x
        self.y = y
        self.screen = screen
        self.images = []  # 按钮的图片群
        self.fps = 0  # 按钮显示的计数器
        self.ran = 0  # 图片下标
        for image in list_image:  # 所有图片全部加载
            self.images.append(pygame.image.load_extended(image))

    def draw(self):
        self.fps += 1
        if self.fps % 10 == 0:  # 每过15帧显示一张按钮图片
            self.ran += 1
            if self.ran > 3:
                self.ran = 0
        self.screen.blit(self.images[self.ran], (self.x, self.y))  # 循环显示背景图片


class ModeButton(ButtonGame):
    """创建各种功能按钮"""

    def __init__(self, x, y, screen, list_image):
        super().__init__(x, y, screen, list_image)
        self.image_size = []
        self.button_make = False  # 创建一个按钮图片替换的开关
        for image1 in self.images:
            self.image_size.append(image1.get_rect())  # 获取图片的外接矩形

    def mouse_make(self, mouse_x, mouse_y):
        """根据光标位置控制显示的方法"""
        # 如果光标的坐标在图片按钮的范围之内
        if self.x <= mouse_x <= self.x + self.image_size[0].w \
                and self.y <= mouse_y <= self.y + self.image_size[0].h:
            self.button_make = True  # 显示黄色的图片
        else:
            self.button_make = False  # 显示绿色的图片

    def draw(self):  # 重写显示方法
        try:
            if not self.button_make:  # 如果替换开关是关闭的
                self.screen.blit(self.images[0], (self.x, self.y))  # 显示绿色的图片

            else:
                self.screen.blit(self.images[1], (self.x, self.y))  # 显示黄色的图片

        except Exception as re:
            print(re)


class Beijing(Obj):
    """创建一个背景类"""
    def __init__(self, x, y, screen, filename):
        super().__init__(x, y, screen, filename)
        self.num = -2000  # 设置图片最初位置

    def draw(self):  # 重写父类的方法
        if self.name == st.BEIJING_1:  # 如果是游戏战斗背景图
            self.y = self.num
            self.num += st.BEIJING_SPEED  # 使得背景图移动
            if self.num > -10:
                self.num = -2000
        self.screen.blit(self.image_1, (self.x, self.y))  # 循环显示背景图片


class Factory(object):
    """"创建一个万能的工厂,能够生产并自动将其添加到显示列表"""
    @staticmethod
    def beijing_act(x, y, screen, filename):
        """创造并显示静态的图片"""
        beijing = Beijing(x, y, screen, filename)
        screen_list.append(beijing)  # 将背景添加到显示列表
        return beijing

    @staticmethod
    def script_act(x, y, screen, script, size,
                   filename=st.SCRIPT2, num=0, color=(255, 0, 0),
                   bool_sc=True, bg_script=None):
        """创建一个柔性化制造各种效果文字的工厂"""
        ls = [x, y, screen, script, size,
              filename, color, bool_sc, bg_script
              ]
        if num == 0:  # 如果选择为0则创建基本的文字
            script = ScriptNew(*ls)

        elif num == 1:  # 如果选择为1则创建大小变化的文字
            script = ScriptMove(*ls)
        elif num == 2:
            script = ScriptEnd(*ls)  # 创建小变大的文字
        elif num == 3:
            script = ScriptLong(*ls)  # 创建长文字
        screen_list.append(script)  # 添加文字到显示列表
        return script

    @staticmethod
    def button1_act(x, y, screen, list_image):
        """创建普通按钮"""
        button = ModeButton(x, y, screen, list_image)
        screen_list.append(button)
        return button

    @staticmethod
    def button_act(x, y, screen, list_image):
        """按钮生成器"""
        button = ButtonGame(x, y, screen, list_image)
        screen_list.append(button)

    @staticmethod
    def star_act(x, y, screen, filename):
        """流星雨生成器"""
        show = Star(x, y, screen, filename)
        screen_list.append(show)

    @staticmethod
    def hreo_act(x, y, screen, filename):
        """生产我方的飞机"""
        my_plane = Hreo(x, y, screen, filename)
        screen_list.append(my_plane)
        return my_plane

    @staticmethod
    def any_blast(target1, blast_name, btitem=1):
        """爆炸的公共方法"""
        if btitem == 1:  # 如果选择短爆炸
            bst = SmallBlast(target1, blast_name)  # 创建一个爆炸的对象
        else:  # 长爆炸
            bst = LongBlast(target1, blast_name)  # 创建一个爆炸的对象
        screen_list.append(bst)  # 将爆炸效果添加到显示列表

    @staticmethod
    def boss_blast(element):
        """boss飞机爆炸的公共方法"""
        for i in range(0, 4):
            ran = random.randint(0, 4)  # 随机生成位置
            bst = LongBlast(element, 'big', -16 + 40*ran, -150 + i*40)
            screen_list.append(bst)

    @staticmethod
    def buff_act(ele, prob):
        """buff生成方法"""
        ran = random.randint(0, 10)   # 有一定概率出现buff
        if ran < prob:  # 调整概率
            buff = BuffBullet1(ele.x, ele.y, ele.screen, random.choice(st.LIST_BUFF))
            screen_list.append(buff)  # 添加到显示列表

    @staticmethod
    def music_act(name):
        """音乐播放方法"""
        music1 = MusicThis(name)
        music1.play_music()
        del music1

    @staticmethod
    def enemy_act(x, y, screen, filename):
        """创建一个敌方飞机的生产线"""
        if filename == st.ENEMY_3:  # 如果生产的是敌方boss飞机
            enemy = BossEnemy(x, y, screen, filename)
        else:  # 如果是其他的飞机
            enemy = EnemyPlane(x, y, screen, filename)
        screen_list.append(enemy)  # 添加到显示列表
        return enemy

    @staticmethod
    def bullet_act(element):
        bullets = []  # 子弹初始值为空
        """生产子弹"""
        if isinstance(element, Hreo):  # 如果发射子弹的是我方
            if st.GOD_BUFF:  # 如果金币buff开关打开
                bullet = GodBullet(element, 0, 0)
                bullets.append(bullet)
            elif st.LASER_BUFF:  # 如果是激光子弹开关打开
                for i in range(-1, 2):  # 创建3颗子弹
                    bullet = LaserBullet(element, i*40, 0)
                    bullets.append(bullet)
            elif st.RAN_BUFF:  # 如果是随机运动的子弹
                for i in range(0, 2):
                    bullet = RanBullet(element, -32 + i*64, 0)
                    bullets.append(bullet)
            else:  # 螺旋子弹
                bullet = LuoXBullet(element)
                bullets.append(bullet)

        elif isinstance(element, EnemyPlane):  # 若果放射子弹的是敌方
            if isinstance(element, BossEnemy):  # 如果是boss飞机
                for i in range(-1, 2):  # 创建3颗子弹
                    bullet = EneBullet(element, i*32, 0)
                    bullets.append(bullet)
            else:  # 如果是普通飞机
                bullet = EneBullet(element, 0, 0)
                bullets.append(bullet)

        else:
            bullet = EneBullet(element, 0, 0)
            bullets.append(bullet)
        if bullets:  # 如果不为空
            bullet_list.extend(bullets)


class Hreo(Obj):
    """创建一个我方飞机类"""

    def __init__(self, x, y, screen, filename):
        super().__init__(x, y, screen, filename)
        self.speed = st.HERO_SPEED  # 飞机的速度
        self.__blood = st.HERO_BLOOD   # 设置血量
        self.button_fire = False  # 一个控制开火的开关

    @property
    def blood(self):
        """创建血量访问方法"""
        return self.__blood

    @blood.setter
    def blood(self, new_blood):
        """血量设置方法"""
        self.__blood = new_blood

    def __del__(self):
        self.button_fire = False  # 关闭开火
        print("hero删除执行了")

    def get_fire(self):  # 设置类方法访问和修改类属性
        return self.button_fire

    def set_fire(self, bools):
        self.button_fire = bools

    def fire(self):
        """发射子弹"""
        Factory.music_act(st.FIRE_MUSIC)  # 播放音乐
        Factory.bullet_act(self)  # 调用工厂产生子弹并发射出去

    def hreo_move(self, strx):
        """飞机移动的方法"""
        if strx == 'up':  # 向上移动
            self.y -= self.speed
        elif strx == 'down':  # 向下移动
            self.y += self.speed
        elif strx == 'left':  # 向左移动
            self.x -= self.speed
        elif strx == 'right':  # 向右移动
            self.x += self.speed
        else:
            pass

    def ishit(self, ele):
        """飞机的碰撞检测执行函数"""
        # 忽略所有子弹、背景、爆炸图、本身、文字
        if isinstance(ele, (Beijing, Blast, Hreo, Bullet, ScriptBase)):
            # print("这是背景或本身")
            return False

        result = any_hit(self, ele)  # 调用公共方法检测碰撞

        if result:
            if isinstance(ele, EnemyPlane):  # 如果碰到敌方飞机
                # print("撞上了!")
                if ele.name == st.ENEMY_1:
                    self.__bloods(ele, 50, "big")
                elif ele.name == st.ENEMY_2:
                    self.__bloods(ele, 100, "big", btm=2)
                elif ele.name == st.ENEMY_3:
                    self.blood -= 5  # 自身血量减少
                    ele.blood -= 5  # boss血量减少5

            if isinstance(ele, BuffBullet1):  # 如果碰到的是buff
                bullet_del.append(ele)  # buff1消失
                ele.buff_creat()  # 调用方法产生效果

            if isinstance(ele, Stony):  # 如果碰到的是陨石
                self.__bloods(ele, 500, "big", 2)

    def __bloods(self, ele, blood_r, name, btm=1):
        """检测血量"""
        self.__blood -= blood_r  # 自身血量减少
        Factory.any_blast(ele, name, btm)  # 敌方飞机爆炸并删除
        bullet_del.append(ele)  # 删除敌方飞机

    def draw(self):  # 重写父类的方法
        self.screen.blit(self.image_1, (self.x, self.y))  # 显示我方飞机
        for ele in screen_list:  # 遍历显示列表检测碰撞
            # print(ele)
            self.ishit(ele)

        self.serc()  # 越界和血量检测

    def serc(self):
        """血量和越界检测"""
        if self.__blood <= 0:  # 如果血量少于0删除自己
            Factory.any_blast(self, 'big', 2)  # 产生爆炸
            self.button_fire = False  # 关闭开火开关
            # 创建“你输了”文字
            Factory.script_act(70, 250, self.screen, "你输了", 100, num=2)
            bullet_del.append(self)

        # 越界检测
        if self.x <= 0:
            self.x = 0
        elif self.x >= 540:
            self.x = 540
        if self.y <= 0:
            self.y = 0
        elif self.y >= 600:
            self.y = 600


class Bullet(Obj):
    """创建子弹类"""
    def __init__(self, element):
        self.screen = element.screen
        self.ele = element
        self.name = None
        self.image_bullet = None
        self.bullet_speed = None
        self.__blood = 50  # 设置血量

    def bullet_init(self, x1, y1, speed):
        """不同子弹初始化参数的函数"""
        self.x = self.ele.x + x1
        self.y = self.ele.y + y1
        self.image_bullet = pygame.image.load_extended(self.name)  # 加载背景图片
        self.rect = self.image_bullet.get_rect()   # 获得图片的尺寸
        self.bullet_speed = speed  # 设置子弹的速度

    @property
    def blood(self):
        """创建血量访问方法"""
        return self.__blood

    @blood.setter
    def blood(self, new_blood):
        """血量设置方法"""
        self.__blood = new_blood

    def draw(self):
        """
        修改数字,不要使用计数器来降低子弹的速度,因为计数器作为一个公共变量,
        不同的子弹数据会造成干扰,导致子弹移动出现问题
        """
        self.screen.blit(self.image_bullet, (self.x, self.y))   # 绘制子弹
        for ele in screen_list:  # 遍历显示列表检测碰撞
            # print(ele)
            self.ishit(ele)
        self.bullet_move()  # 子弹的移动

    def bullet_move(self):
        """子弹移动的函数"""
        if isinstance(self.ele, Hreo):  # 判断是那种飞机的子弹
            self.y -= self.bullet_speed
        else:
            self.y += self.bullet_speed
        self.bullet_out()  # 子弹越界检测

    def bullet_out(self):
        """判断子弹越界"""
        if self.y < -30 or self.y > 704:  # 判断子弹是否越界
            bullet_del.append(self)

    def ishit(self, ele):
        """子弹的碰撞检测函数"""
        # 忽略掉子弹本身、背景、爆炸、buff子弹
        if ele is self or isinstance(ele, (Beijing, Blast, BuffBullet1, ScriptBase)):
            # print("这是背景或本身")
            return False

        # 若果是我方飞机产生的子弹或流星雨产生的子弹
        if isinstance(self.ele, (Hreo, Star)):
            result = any_hit(self, ele)
            # 忽略本类对象
            if isinstance(ele, Bullet) and isinstance(ele.ele, (Hreo, Star)):
                return False
            else:
                if result:  # 发生了碰撞
                    # print("撞上了")
                    # 如果碰撞到敌方子弹
                    if isinstance(ele, Bullet) and isinstance(ele.ele, EnemyPlane):
                        self.hit_result(ele, "xiao")  # 调用效果函数
                    # 如果碰到的是敌方小飞机
                    elif ele.name == st.ENEMY_1 and isinstance(ele, EnemyPlane):
                        self.hit_result(ele)   # 调用效果函数
                    # 如果碰到的是敌方大飞机
                    elif ele.name == st.ENEMY_2 and isinstance(ele, EnemyPlane):
                        self.hit_result(ele, "big", 2)
                    # 如果是boss飞机
                    elif ele.name == st.ENEMY_3 and isinstance(ele, EnemyPlane):
                        self.hit_result(ele, 'big', 2)
                    # 如果碰到的是陨石
                    elif isinstance(ele, Stony):
                        self.hit_result(ele, "big", 2)
                        Factory.buff_act(ele, 1)  # 每次碰撞爆buff概率为10%

        else:  # 如果是敌方飞机产生的子弹
            result = any_hit(self, ele)
            if not isinstance(ele, Hreo):   # 忽略除了英雄飞机外的所有对象
                return False
            else:
                if result:  # 发生了碰撞
                    # print("撞上了")
                    self.hit_result(ele, "big", 2)  # 调用效果函数

    def hit_result(self, ele, blast_name="big", btm=1):
        """碰撞后产生的效果函数"""
        if self.__blood >= ele.blood:  # 如果子弹血量大于对方血量
            self.__blood -= ele.blood
            ele.blood = -1
        else:
            ele.blood -= self.blood
            self.__blood = 0
            bullet_del.append(self)

        if ele.blood > 0:  # 若果对方血量还大于0,产生小爆炸
            Factory.any_blast(ele, 'xiao')  # 产生一个小短爆炸效果
        else:  # 如果对方血量小于0,产生大爆炸,同时删除对方飞机
            if isinstance(ele, BossEnemy):  # 如果对方是boss飞机
                # 创建“你赢了”文字
                Factory.script_act(70, 250, self.screen, "你赢了", 100, num=2)
            else:
                Factory.any_blast(ele, blast_name, btm)
            bullet_del.append(ele)  # 将对方添加到删除列表

            if isinstance(ele, EnemyPlane):  # 如果是敌机被打爆,则敌机死亡计数器加1
                ele.set_enemy_die()

            if not isinstance(ele, Bullet):  # 如果对方不是子弹才能产生buff
                if isinstance(ele, Stony):  # 对方陨石爆炸
                    Factory.buff_act(ele, 5)  # 爆buff概率为30%
                else:  # 其他的爆炸
                    Factory.buff_act(ele, 3)  # 爆buff概率为20%


class RanBullet(Bullet):
    """创建随机跳弹"""
    def __init__(self, element, x1, y1):
        super().__init__(element)
        self.name = st.RAN_BULLET  # 得到子弹的图片作为名字
        self.__blood = 50  # 设置血量
        self.fps = 0  # 子弹移动换方向的时间
        self.ran = 0  # 子弹左右的方向
        if isinstance(self.ele, Hreo):  # 我方飞机
            self.bullet_init(48 + x1, -64 + y1, st.BULLET_SPEED+2)

    def bullet_move(self):
        """重写子弹移动的函数"""
        if isinstance(self.ele, Hreo):  # 判断是那种飞机的子弹
            self.y -= self.bullet_speed  # 向上运动
            self.fps += 1
            if self.fps % 10 == 0:  # 每10帧数改变方向
                self.ran = random.randint(0, 1)
            if self.ran == 0:
                self.x -= self.bullet_speed - 5
            else:
                self.x += self.bullet_speed - 5

        self.bullet_out()  # 子弹越界检测


class GodBullet(Bullet):
    """创建一个金币子弹类"""
    def __init__(self, element, x1, y1):
        super().__init__(element)
        self.name = st.GOD_BULLET  # 得到子弹的图片作为名字
        self.__blood = 200  # 设置血量
        if isinstance(self.ele, Hreo):  # 我方飞机
            self.bullet_init(25 + x1, -30 + y1, st.BULLET_SPEED+2)


class LaserBullet(Bullet):
    """创建激光子弹"""
    def __init__(self, element, x1, y1):
        super().__init__(element)
        self.name = st.LASER_BULLET  # 得到子弹的图片作为名字
        self.__blood = 100  # 设置血量
        if isinstance(self.ele, Hreo):  # 我方飞机
            self.bullet_init(40 + x1, -90 + y1, st.BULLET_SPEED)


class LuoXBullet(Bullet):
    """创建螺旋子弹"""
    def __init__(self, element):
        super().__init__(element)
        self.name = st.LUOXUAN_BULLET  # 得到子弹的图片作为名字
        self.__blood = 50  # 设置血量
        if isinstance(self.ele, Hreo):  # 我方飞机
            self.bullet_init(42, -20, st.BULLET_SPEED)


class EneBullet(Bullet):
    """创建普通子弹"""
    def __init__(self, element, x1, y1):
        super().__init__(element)
        self.name = st.MY_BULLET  # 得到子弹的图片作为名字
        self.__blood = 50  # 设置血量

        if isinstance(self.ele, EnemyPlane):  # 如果是敌机
            if self.ele.name == st.ENEMY_1:  # 敌方小飞机
                self.bullet_init(16 + x1, 32 + y1, st.BULLET_SPEED - 3)
            elif self.ele.name == st.ENEMY_2:  # 敌方中型飞机
                self.bullet_init(24 + x1, 64 + y1, st.BULLET_SPEED - 3)
            elif self.ele.name == st.ENEMY_3:  # 敌方boss飞机
                self.bullet_init(72 + x1, 220 + y1, st.BULLET_SPEED)

        if isinstance(self.ele, Star):  # 如果是流星雨
                self.bullet_init(x1, y1, st.BULLET_SPEED)


class Star(Obj):
    """一个下流星雨的类"""
    __button1 = None  # 创建控制单例模式开关
    __button2 = True

    def __init__(self, x, y, screen, filename):
        if self.__button2:
            super().__init__(x, y, screen, filename)
            self.fps = 0  # 创建时间计数
            self.num_shower = 0  # 创建流星雨下的次数计数
            # self.button_star = False  # 下雨的开关
            self.__button2 = False  # 保证只有一次初始化

    def __new__(cls, *args, **kwargs):
        if not cls.__button1:
            cls.__button1 = Obj.__new__(cls)
        return cls.__button1

    def draw(self):
        if st.SHOWER_BUFF:
            self.fps += 1
            if self.fps % 60 == 0:
                self.num_shower += 1
                for i in range(10):
                    bullet_new = EneBullet(self, i * 64, -32)
                    screen_list.append(bullet_new)  # 添加到显示列表
                # 五次后关闭流星雨
                if self.num_shower > 3:
                    self.fps = 0
                    self.num_shower = 0
                    st.SHOWER_BUFF = False


class Blast(Obj):
    """创建一个爆炸效果类"""
    def __init__(self, ele, name):
        self.num1 = 0
        self.screen = ele.screen
        self.name = name
        self.image_blast = []

        # 如果是敌机的子弹爆炸
        if isinstance(ele, Bullet) and not isinstance(ele.ele, Hreo):
            self.x = ele.x - 56
            self.y = ele.y - 32
        # 如果是敌方的小飞机爆炸
        elif ele.name == st.ENEMY_1 and isinstance(ele, EnemyPlane):
            self.x = ele.x - 40
            self.y = ele.y - 40
        # 如果是敌方的中型飞机爆炸
        elif ele.name == st.ENEMY_2 and isinstance(ele, EnemyPlane):
            self.x = ele.x - 32
            self.y = ele.y - 32
        # 如果是敌方的boss飞机爆炸
        elif ele.name == st.ENEMY_3 and isinstance(ele, BossEnemy):
            self.x = ele.x + 16
            self.y = ele.y + 150
        # 如果是我方飞机爆炸
        elif ele.name == st.HREO_1 and isinstance(ele, Hreo):
            self.x = ele.x - 14
            self.y = ele.y
        # 如果是文字
        elif isinstance(ele, ScriptBase):
            self.x = ele.x
            self.y = ele.y
        else:
            self.x = ele.x - 32
            self.y = ele.y - 32

        Factory.music_act(st.BLAST_MUSIC)  # 播放音乐

    def draw(self):
        pass

    def numx(self, n):
        """改变爆炸的大小"""
        if self.num1 > n:
            self.num1 = 0
            bullet_del.append(self)  # 爆炸完成后删除本身


class SmallBlast(Blast):
    """创建短爆炸"""

    def __init__(self, ele, name):
        super().__init__(ele, name)
        for image in st.LIST_BLAST:   # 加载爆炸图片资源
            self.image_blast.append(pygame.image.load_extended(image))

    def draw(self):  # 重写爆炸绘制方法
        self.screen.blit(self.image_blast[self.num1], (self.x, self.y))
        self.num1 += 1
        if self.name == "xiao":
            self.numx(3)
        elif self.name == "big":
            self.numx(7)


class LongBlast(Blast):
    """创建长爆炸"""
    def __init__(self, ele, name, x=0, y=0):
        super().__init__(ele, name)
        self.x += x
        self.y += y
        for image in st.LIST_BLAST_BIG:   # 加载爆炸图片资源
            self.image_blast.append(pygame.image.load_extended(image))

    def draw(self):
        """绘制长爆炸"""
        self.screen.blit(self.image_blast[self.num1], (self.x, self.y))
        self.num1 += 1
        if self.name == 'xiao':
            self.numx(7)
        elif self.name == 'big':
            self.numx(13)


class EnemyPlane(Obj):
    """创建一个敌方的飞机类1"""
    __enemy_die = 0  # 创建一个类属性记录杀死的敌机数量

    @classmethod
    def get_enemy_die(cls):  # 访问类属性方法
        return cls.__enemy_die

    @classmethod
    def set_enemy_die(cls, num=False):  # 设置类属性方法
        if num:
            cls.__enemy_die = 0  # 重新设置为0
        else:
            cls.__enemy_die += 1

    def __init__(self, x, y, screen, filename):
        super().__init__(x, y, screen, filename)
        self.button_fire = True  # 设置一个是否可以开火的开关
        self.derc = None  # 初始方向为向右
        self.time2 = time.time()  # 时间变量
        if self.name == st.ENEMY_1:  # 如果是敌方小飞机
            self.__blood = st.Small_Blood
            self.enemy_speed1 = st.ENEMY_DOWN_SPEED  # 小飞机设置成快速
        elif self.name == st.ENEMY_2:
            self.__blood = st.Middle_Blood
            self.enemy_speed1 = st.ENEMY_DOWN_SPEED1  # 中型飞机设置成中速
        elif self.name == st.ENEMY_3:
            self.__blood = st.Boss_Blood
            self.enemy_speed1 = st.ENEMY_DOWN_SPEED  # boss飞机设置成慢速

    @property
    def blood(self):
        """创建血量访问方法"""
        return self.__blood

    @blood.setter
    def blood(self, new_blood):
        """血量设置方法"""
        self.__blood = new_blood

    def __del__(self):
        self.button_fire = False  # 关闭开火的开关
        # print("敌机删除执行!")

    def enemy_shoot(self):  # 敌机发射子弹的方法
        ran = random.randint(0, 100)  # 敌机随机发射子弹
        if ran == 80:
            Factory.bullet_act(self)  # 调用工厂生产和装填子弹

    def draw(self):
        # 绘制敌机
        self.screen.blit(self.image_1, (self.x, self.y))
        self.enemy_move()  # 敌机移动
        if self.button_fire:  # 如果开火的开关是打开的
            self.enemy_shoot()  # 敌机发射子弹
        if self.__blood <= 0:  # 小于0删除自身
            bullet_del.append(self)

    def enemy_move(self):  # 使得敌方飞机移动
        """敌机移动的方法"""
        time1 = time.time()  # 敌机每隔1.5秒改变方向
        # print(timex)
        # print(time1 - timex)
        if time1 - self.time2 > 1.5:
            self.time2 = time1
            self.derc = random.randint(0, 3)  # 获取敌机移动的方向

        self.y += self.enemy_speed1  # 使得敌机保持向下,左右随机移动
        if self.derc == 0:
            self.x += st.ENEMY_LR_SPEED
        elif self.derc == 1:
            self.x -= st.ENEMY_LR_SPEED
        self.out_screen()  # 防止敌机左右出界
        self.go_screen()  # 防止敌机下出界

    def out_screen(self):
        """防止敌机左右出界"""
        if self.x <= 0:
            self.x = 0
        elif self.name == st.ENEMY_1 and self.x >= 592:  # 小飞机
            self.x = 592
        elif self.name == st.ENEMY_2 and self.x >= 576:  # 中飞机
            self.x = 576
        elif self.name == st.ENEMY_3 and self.x >= 480:  # boss飞机
            self.x = 480

    def go_screen(self):
        """敌机下出界删除"""
        if self.y > 710:
            bullet_del.append(self)


class BossEnemy(EnemyPlane):
    """创建敌方boss飞机类"""

    def __init__(self, x, y, screen, filename):
        super().__init__(x, y, screen, filename)
        self.time3 = time.time()  # 用来记录换方向的初始时间
        self.button_fire = False  # 开火的开关初始状态设为关闭

    def enemy_shoot(self):
        """重写父类发射子弹的方法"""
        ran = random.randint(0, 100)  # 敌机随机发射子弹
        if ran <= 10:  # 10%的时间发射子弹
            Factory.bullet_act(self)  # 调用工厂生产和装填子弹

    def enemy_move(self):
        """boss移动"""
        time1 = time.time()  # 记录boss移动的时间
        time3 = time.time()  # boss左右换方向的时间
        # print(timex)
        # print(time1 - timex)
        if time1 - self.time2 < 6:  # 如果小于六秒就一直向下移动
            self.y += self.enemy_speed1
        else:  # 大于6秒开始左右移动
            self.button_fire = True  # 打开开火的开关
            if time3 - self.time3 >= 2:
                self.time3 = time3
                while True:
                    derc = random.randint(0, 6)  # 获取敌机移动的方向
                    if self.derc != derc:
                        self.derc = derc
                        break

            if self.derc == 0:  # 向右边移动
                self.x += st.ENEMY_LR_SPEED + 3
            elif self.derc == 1:  # 向左移动
                self.x -= st.ENEMY_LR_SPEED + 3
            elif self.derc == 2:  # 向右弧形移动
                self.x += st.ENEMY_LR_SPEED + 3
                self.y += st.ENEMY_LR_SPEED + 3
            elif self.derc == 3:  # 向右边移动
                self.x += st.ENEMY_LR_SPEED + 3
                self.y -= st.ENEMY_LR_SPEED + 3
            elif self.derc == 4:  # 向左边移动
                self.x -= st.ENEMY_LR_SPEED + 3
                self.y += st.ENEMY_LR_SPEED + 3
            elif self.derc == 5:  # 向左上移动
                self.x -= st.ENEMY_LR_SPEED + 3
                self.y -= st.ENEMY_LR_SPEED + 3
            self.go_screen1()  # 防止上出界
        self.out_screen()  # 防止敌机左右出界
        self.go_screen()  # 防止敌机下出界

    def go_screen1(self):
        """防止敌机上出界"""
        if self.y <= 0:
            self.y = 0

    def go_screen(self):
        """防止敌机下出界"""
        if self.y >= 448:
            self.y = 448

    def draw(self):
        super().draw()
        if self.blood <= 0:
            Factory.boss_blast(self)  # 创建超极爆炸
            bullet_del.append(self)


class MusicThis(object):
    """创建一个音乐类管理音乐"""
    def __init__(self, filename, count=0):
        self.filename = filename
        self.count = count

    def play_music(self):
        """播放音乐"""
        pygame.mixer_music.load(self.filename)  # 添加音乐
        pygame.mixer_music.play(self.count)  # 播放音乐


class BuffBullet1(Obj):
    """创建一个子弹外挂管理的类"""
    def __init__(self, x, y, screen, filename):
        super().__init__(x, y, screen, filename)
        self.time = 0  # 设置一个计时器

    def buff_creat(self):
        """buff的开关控制"""
        if self.name == st.BUFF_1:  # 如果是流星雨buff
            st.SHOWER_BUFF = True  # 打开开关,在主函数中显示
            Factory.star_act(0, 0, self.screen, st.MY_BULLET)

        elif self.name == st.BUFF_2:  # 如果是金币子弹buff
            self.buff_control(n2=True)
            st.BUFF_TIME = 0  # 将金币buff时间计数器设为0

        elif self.name == st.BUFF_3:  # 如果是激光子弹buff
            self.buff_control(n3=True)
            st.LASER_TIME = 0  # 将buff时间计数器设为0

        elif self.name == st.BUFF_4:  # 如果是随机弹
            # 随机弹开关打开,其他的关闭
            BuffBullet1.buff_control(n1=True)
            st.RAN_TIME = 0  # 将时间计数器设为0

    @staticmethod
    def buff_control(n1=False, n2=False, n3=False):
        """创建管理子弹buff开关打开的函数"""
        st.RAN_BUFF = n1  # 随机弹开关
        st.GOD_BUFF = n2  # 金币子弹buff开关
        st.LASER_BUFF = n3  # 激光子弹buff开关

    def draw(self):
        # 循环显示背景图
        self.screen.blit(self.image_1, (self.x, self.y))
        self.y += st.BUFF_SPEED  # buff移动
        self.time += 1
        if self.time > 400:  # buff超过6秒后自动删除
            bullet_del.append(self)
            self.time = 0
        if self.y < -30 or self.y > 704:  # 判断buff是否越界
            bullet_del.append(self)


class Stony(Obj):
    """创建一个陨石类"""
    def __init__(self, x, y, screen, filename):
        """定义构造属性"""
        super().__init__(x, y, screen, filename)
        self.drec = random.randint(0, 1)  # 创建一个移动的左右随机方向
        self.__blood = 500  # 设置血量

    @property
    def blood(self):
        """创建血量访问方法"""
        return self.__blood

    @blood.setter
    def blood(self, new_blood):
        """血量设置方法"""
        self.__blood = new_blood

    def draw(self):
        # 循环显示背景图
        self.screen.blit(self.image_1, (self.x, self.y))
        if self.__blood <= 0:  # 血量小于0
            bullet_del.append(self)
        self.y += st.STONY_SPEED  # 移动
        if self.drec == 0:
            self.x += st.STONY_SPEED - 4.2
        else:
            self.x -= st.STONY_SPEED - 4.2
        # 判断是否越界
        if self.y < -150 or self.y > 750 or self.x < -100 or self.x > 640:
            bullet_del.append(self)

tool.py提供一些公共使用的工具方法

# coding=utf-8
import time

def any_hit(target, element):
    """"检测两个物体发生碰撞函数"""
    # 定义四个开关
    button1 = False
    button2 = False
    button3 = False
    button4 = False
    # 获取传入的类的尺寸
    ele_rect = element.rect
    x1 = element.x
    y1 = element.y
    w1 = ele_rect.w
    h1 = ele_rect.h

    # 碰撞判断
    if x1 < target.x + target.rect.w < x1 + w1 or x1 < target.x < x1 + w1:
        button1 = True
    if y1 < target.y < y1 + h1 or y1 < target.y + target.rect.h < y1 + h1:
        button2 = True
    if target.x < x1 + w1 < target.x + target.rect.w or target.x < x1 < target.x + target.rect.w:
        button3 = True
    if target.y < y1 < target.y + target.rect.h or target.y < y1 + h1 < target.y + target.rect.h:
        button4 = True
    if (button1 and button2) or (button3 and button4):
        return True
    else:
        return False


def delays(delay, time0=time.time()):
    class MyDelay(object):
        """创建一个带参数的类装饰器,用来对函数进行延时执行,每过
           delay时间执行一次
        """

        def __init__(self, fun):
            self.sec = delay
            self.time = time0
            self.__fun = fun

        def __call__(self, *args, **kwargs):
            time1 = time.time()
            if time1 - self.time >= self.sec:
                self.__fun(*args, **kwargs)
                self.time = time1

    return MyDelay


def delay_fps(fps, fps0=0):
    class FpsDelay(object):
        """创建一个根据固定帧数延时执行的类装饰器,每过fps帧数执行一次"""

        def __init__(self, fun):
            self.fps = fps
            self.fps0 = fps0
            self.__fun = fun

        def __call__(self, *args, **kwargs):
            self.fps0 += 1
            # print(self.fps0)
            if self.fps0 % self.fps == 0:
                self.__fun(*args, **kwargs)

    return FpsDelay


def delay_run(fps, fps0=0):
    """创建一个帧数 延时执行的装饰器"""

    def delay(func):
        def new_run(*args, **kwargs):
            nonlocal fps0
            fps0 += 1
            if fps0 % fps == 0:
                res = func(*args, **kwargs)
                return res

        return new_run

    return delay


def delay_time(time1, time0=time.time()):
    """创建一个延时间的装饰器"""

    def delay(func):
        def new_run(*args, **kwargs):
            nonlocal time0
            time2 = time.time()
            if time2 - time0 >= time1:
                time0 = time2
                res = func(*args, **kwargs)
                return res

        return new_run

    return delay


def print_say():
    __a = 0
    print(locals())


if __name__ == "__main__":
    class Person(object):
        def __init__(self, name, age, taste):
            self.name = name
            self._age = age
            self.__taste = taste
            print(locals())
    print(dir(Person))

setting.py创建存储所有游戏资源的模块

# 设置屏幕
SCREEN_WIDTH = 768  # 屏幕的宽度
SCREEN_HIGHT = 704  # 屏幕的高度

# 设置背景
BEIJING_SPEED = 3  # 设置背景移动速度

# 设置游戏前言界面字体显示参数
FRAMES = 40  # 每隔frames帧数显示一个字
WIN_OVER_FRAMES = 200  # 多少帧数后界面切换

# 设置游戏背景诉说界面的参数
WIN_FONT_FRAMES = 500  # 多少帧数后界面结束

# 我方飞机的参数
HERO_SPEED = 10  # 设置我方飞机移动的速度
HERO_BLOOD = 2000  # 我方血量

# 我方子弹的参数
BULLET_SPEED = 10  # 设置我方子弹的速度

# 设置敌机的血量
Small_Blood = 100  # 小敌机
Middle_Blood = 200  # 中型飞机
Big_Blood = 500  # 大型
Boss_Blood = 3000  # 敌方boss

# 敌机的数目
ENEMY_NUM = 50  # 普通飞机的上限
BOSS_NUM = 1  # boss飞机的上限

'''流星雨的速度'''
SHOWER_SPEED = 20
'''设置小敌机的速度'''
ENEMY_DOWN_SPEED = 1
ENEMY_LR_SPEED = 1
'''设置中型敌机的速度'''
ENEMY_DOWN_SPEED1 = 0.8
ENEMY_LR_SPEED1 = 1
'''设置大敌机的速度'''
ENEMY_DOWN_SPEED2 = 0.5
ENEMY_LR_SPEED2 = 0.5
"""设置子弹的大小"""
BULLET_BIG = 16


"""敌方飞机产生速度调节器"""
ENEMY_CREATE1 = 80
ENEMY_CREATE2 = 40
"""游戏buff的移动速度"""
BUFF_SPEED = 5
"""陨石移动速度"""
STONY_SPEED = 5


"""金币buff的时间计数器"""
BUFF_TIME = 0
"""激光buff时间计数器"""
LASER_TIME = 0
"""随机子弹buff时间"""
RAN_TIME = 0


"""文字字体文件"""
SCRIPT = './rec/font_file/songti.TTF'
SCRIPT1 = './rec/font_file/jingdian.TTF'
SCRIPT2 = './rec/font_file/kong.TTF'

# 图片资源
"""背景图片"""
BEIJING_1 = 'rec/images/beijing_3.jpg'
"""积分界面背景图片"""
IMAGE_BJ = 'rec/images/image_bj2.jpg'
'''开始界面图片'''
BEIJING_2 = 'rec/images/kong.jpg'
'''我方飞机'''
HREO_1 = 'rec/images/hero1.png'
'''我方普通子弹'''
MY_BULLET = 'rec/images/shot_bottom.gif'
"""buff子弹螺旋弹"""
LUOXUAN_BULLET = 'rec/images/bullets.png'
"""buff金币弹"""
GOD_BULLET = 'rec/images/moneybullet.png'
"""buff激光子弹"""
LASER_BULLET = 'rec/images/buffbullet2.png'
"""随机运动子弹"""
RAN_BULLET = 'rec/images/bzx.png'
'''敌方飞机1'''
ENEMY_1 = 'rec/images/enemy_1.gif'
''''敌方飞机2'''
ENEMY_2 = 'rec/images/enemy_2.png'
'''敌方飞机3'''
ENEMY_3 = 'rec/images/enemy_3.gif'
"""陨石图片"""
STONY_BUFF = 'rec/images/buff3.png'
"""标准模式按钮"""
BUTTON_1 = 'rec/images/moshi_2.PNG'
BUTTON_2 = 'rec/images/moshi2.PNG'
BUTTON_A = [BUTTON_2, BUTTON_1]
"""困难模式按钮"""
BUTTON_3 = 'rec/images/moshi1.PNG'
BUTTON_4 = 'rec/images/moshi_1.PNG'
BUTTON_B = [BUTTON_4, BUTTON_3]
"""飞机大战名字"""
PLANE_NAME = 'rec/images/name.png'
"""退出按钮"""
BUTTON_5 = 'rec/images/goout1.png'
BUTTON_6 = 'rec/images/goout2.png'
BUTTON_C = [BUTTON_5, BUTTON_6]
"""结束界面退出游戏按钮"""
BUTTON_7 = 'rec/images/outgame3.png'
BUTTON_8 = 'rec/images/outgame4.png'
BUTTON_D = [BUTTON_7, BUTTON_8]
"""结束界面重新开始按钮"""
BUTTON_9 = 'rec/images/restart3.png'
BUTTON_10 = 'rec/images/restart4.png'
BUTTON_E = [BUTTON_9, BUTTON_10]
"""游戏下一关按钮"""
BUTTON_11 = 'rec/images/next3.png'
BUTTON_12 = 'rec/images/next4.png'
BUTTON_F = [BUTTON_11, BUTTON_12]
"""游戏操作说明"""
FUNCTION_1 = 'rec/images/func.png'
"""游戏buff图片"""
BUFF_1 = 'rec/images/buff1.png'
BUFF_2 = 'rec/images/moneybuff.png'
BUFF_3 = 'rec/images/bulletn.png'
BUFF_4 = 'rec/images/buff_random.png'

"""游戏进入界面的前言"""
MY_READ = 'rec/images/mylaung1.png'
MY_XING = 'rec/images/xing1.jpg'
MY_SELF = 'rec/images/me.png'
MY_TEXT = 'rec/images/bg.png'
"""创建一个BUFF列表"""
LIST_BUFF = [BUFF_1, BUFF_2, BUFF_3, BUFF_4]
"""游戏开始按钮"""
BUTTON_START1 = 'rec/images/start.png'
BUTTON_START2 = 'rec/images/start1.png'
BUTTON_START3 = 'rec/images/start2.png'
BUTTON_START4 = 'rec/images/start3.png'
"""一个开始的按钮列表"""
BUTTON_START = [BUTTON_START1,
                BUTTON_START2,
                BUTTON_START3,
                BUTTON_START4]
"""爆炸效果图1"""
LIST_BLAST = ['rec/images/blast_1.gif',
              'rec/images/blast_2.gif',
              'rec/images/blast_3.gif',
              'rec/images/blast_4.gif',
              'rec/images/blast_5.gif',
              'rec/images/blast_6.gif',
              'rec/images/blast_7.gif',
              'rec/images/blast_8.gif' ]
"""超大爆炸效果图"""
LIST_BLAST_BIG = ['rec/images/bz0.png',
                  'rec/images/bz1.png',
                  'rec/images/bz2.png',
                  'rec/images/bz3.png',
                  'rec/images/bz4.png',
                  'rec/images/bz5.png',
                  'rec/images/bz6.png',
                  'rec/images/bz7.png',
                  'rec/images/bz8.png',
                  'rec/images/bz9.png',
                  'rec/images/bz10.png',
                  'rec/images/bz11.png',
                  'rec/images/bz12.png',
                  'rec/images/bz13.png',
                  'rec/images/bz14.png']

"""男生角色图片"""
BOY_IMAGE = ['rec/images/boy0.jpg',
             'rec/images/boy1.jpg',
             'rec/images/boy2.jpg',
             'rec/images/boy3.jpg',
             'rec/images/boy4.jpg'
             ]
"""女生角色图片"""
GIRL_IMAGE = ['rec/images/girl0.jpg',
              'rec/images/girl1.jpg',
              'rec/images/girl2.jpg',
              'rec/images/girl3.jpg',
              'rec/images/girl4.jpg'
              ]


'''音乐资源'''
FIRE_MUSIC = 'rec/music/fire.wav'
"""爆炸音乐"""
BLAST_MUSIC = 'rec/music/blast.mp3'
"""游戏开始音乐"""
START_MUSIC = 'rec/music/chao.mp3'

# 开关资源
"""上按键开关"""
KEY_UP = False
"""下按键开关"""
KEY_DOWN = False
"""左按键开关"""
KEY_LEFT = False
"""右按键开关"""
KEY_RIGHT = False
"""游戏模式切换开关"""
GAME_MOSHI = True
"""创建按钮颜色变化开关"""
BUTTON_COLOR = True

"""流星雨buff的打开开关"""
SHOWER_BUFF = False
"""金币子弹buff的开关"""
GOD_BUFF = False
"""激光子弹buff开关"""
LASER_BUFF = False
"""随机弹控制开关"""
RAN_BUFF = False

"""boss出现的开关"""
BOSS_CREAT = False
"""boss是否全部死亡"""
BOSS_DIE = False
"敌机是否可以生产开关"
ENEMY_START = False
"""敌方生成器的开关"""
ENEMY_MAKE = True


'''登陆界面开关'''
SCREEN_CHANGE = False
"""游戏进入前的界面控制开关"""
GAME_BEFORE = False
"""游戏历史背景开关"""
GAME_SAY = False
"""战斗界面控制开关"""
GAME_FIGHT = False
"""游戏结束界面控制开关"""
GAME_END = False

_init_.py

  • _init_.py 文件的作用是将文件夹变为一个Python模块,Python 中的每个模块的包中,都有_init_.py文件。
  • 通常_init_.py文件为空,但是我们还可以为它增加其他的功能。我们在导入一个包时,实际上是导入了它的_init_.py文件。
__all__ = ["game_windows", "setting", "tool", "resource_game"]

main.py 游戏启动模块

# coding:utf-8
from game_file.game_windows import main


if __name__ == '__main__':
    main()

源码及文件下载:

链接:https://pan.baidu.com/s/1f26Au3GMHO18OBYP1yMVpw
提取码:bi10

食用指南:进入the_war_of_sky目录,终端输入:python main.py
python之星河战争游戏_第5张图片

python之星河战争游戏_第6张图片

你可能感兴趣的:(python,pygame,程序人生)