Pygame框架简单实现飞机大战(附有详细注释)

飞机大战主游戏类

"""
项目名称:简单飞机大战游戏
基于框架:Pygame
开发日期:2020.07
开发人员:Y
版本:****
"""


import sys  # 导入内置模块sys 调用sys.exit()
import pygame  # 导入第三方模块pygame
from plane_sprites import *  # 导入自定义模块内所有工具


class PlayGame(object):  # 定义开始游戏主类 继承object基类
    def __init__(self):  # 定义初始化方法
        self.srceen = pygame.display.set_mode(SRCEEN_SIZE.size)  # 设置游戏主窗口
        self.clock = pygame.time.Clock()  # 设置游戏时钟 用于刷新屏幕帧率
        self.__creat_sprites()  # 调用私有方法实现添加精灵类内容
        pygame.display.set_caption('飞机大战')  # 设置窗口标题
        pygame.time.set_timer(CREAT_ENEMY_EVENT, 1000)  # 设置事件定时器 用于每隔一段时间执行一次事件
        pygame.time.set_timer(FIRE_BULLTE, 300)  # 设置事件定时器 用于每隔一段时间执行一次事件

    def start_game(self):  # 定义开始游戏方法
        while True:  # 游戏循环
            self.clock.tick(CLOCK_TICK)  # 利用时钟设置刷新帧率
            self.__event_hander()  # 调用私有方法实现监听事件
            self.__check_collide()  # 调用私有方法检测碰撞
            self.__update_sprites()  # 调用私有方法更新和绘制精灵组
            pygame.display.flip()  # 更新窗口显示
            # pygame.display.update()  # 更新窗口显示

    def __creat_sprites(self):  # 定义添加精灵组方法
        bj1 = Background()  # 利用背景类创建背景对象1 默认参数Flase 表示第一张图像,需要与屏幕重合
        bj2 = Background(True) # 利用背景类创建背景对象2 参数True 表示另一张图像, 在屏幕的正上方
        self.bj_group = pygame.sprite.Group(bj1, bj2)  # 设置背景精灵组
        self.emeny_group = pygame.sprite.Group()  # 提前设置敌机精灵组 但并不设置敌机对象
        # 敌机类对象是定时被创建的,因此在初始化方法中,不需要创建敌机对象
        self.hero = Hero()  # 利用英雄类创建英雄对象 注意:后续对英雄做碰撞检测及发射操作,所有需要单独设置为属性
        self.hero_group = pygame.sprite.Group(self.hero)  # 设置英雄精灵组

    def __event_hander(self):  # 定义监听事件方法
        for event in pygame.event.get():  # 循环监听所有事件
            if event.type == pygame.QUIT:  # 如果是单击退出按钮事件
                PlayGame.__game_over()  # 调用私有方法实现结束游戏
            elif event.type == CREAT_ENEMY_EVENT:  # 如果是执行自定义事件创建敌机
                emeny1 = Enemy("./images/enemy1.png")  # 利用敌机类创建敌机1
                emeny2 = Enemy("./images/enemy2.png")  # 利用敌机类创建敌机2
                emeny3 = Enemy("./images/enemy3_n1.png")
                self.emeny_group.add(emeny1, emeny2, emeny3)   # 对之前设置好的敌机精灵组进行添加精灵对象
            elif event.type == FIRE_BULLTE:  # 如果是执行自定义事件发射子弹
                self.hero.fire()  # 调用英雄对象的发射子弹方法
        key_tuple = pygame.key.get_pressed()  # 捕获键盘按键返回值为元组
        if key_tuple[pygame.K_RIGHT]:  # 判断捕获键盘按键为右键
            self.hero.speed = 4  # 设置英雄类对象的速度为4 向右移动
        elif key_tuple[pygame.K_LEFT]:  # 判断捕获键盘按键为左键
            self.hero.speed = -4   # 设置英雄类对象的速度为-4 向左移动
        else:                     # 否则
            self.hero.speed = 0    # 捕获其余任何按键英雄类对象速度不变 不移动

    def __check_collide(self):  # 定义检测碰撞方法
        pygame.sprite.groupcollide(self.hero.bullet_group, self.emeny_group, True, True)
        # 两个精灵组中所有的精灵的碰撞检测 属性True, 则发生碰撞的精灵将被自动移除
        enemies = pygame.sprite.spritecollide(self.hero, self.emeny_group, True)
        # 判断某个精灵和指定精灵组中的精灵的碰撞 属性True,则指定精灵组中发生碰撞的精灵将被自动移除
        # 返回精灵组中跟精灵发生碰撞的精灵列表
        if len(enemies) > 0:  # 判断敌机精灵组内精灵是否存在 若存在
            self.hero.kill()  # 碰撞导致英雄销毁
            PlayGame.game_over()  # 调用类中结束游戏方法 退出游戏

    def __update_sprites(self):  # 定义精灵组更新和绘制方法
        self.bj_group.update()  # 更新背景类精灵
        self.bj_group.draw(self.srceen)  # 绘制背景类精灵
        self.emeny_group.update()  # 更新敌机类精灵
        self.emeny_group.draw(self.srceen)  # 绘制敌机类精灵
        self.hero_group.update()  # 更新英雄类精灵
        self.hero_group.draw(self.srceen)  # 绘制英雄类精灵
        self.hero.bullet_group.update()  # 更新英雄子弹类精灵
        self.hero.bullet_group.draw(self.srceen)  # 绘制英雄子弹类精灵

    @staticmethod  # 声明定义静态方法
    def __game_over():  # 定义静态方法
        print("游戏结束")  # 控制台打印游戏结束
        pygame.quit()  # 卸载所有pygame模块工具
        sys.exit()  # 退出程序


if __name__ == '__main__':  # 判断当前执行
    playgame = PlayGame()  # 创建开始游戏对象
    playgame.start_game()  # 调用开始游戏对象的开始方法

游戏工具类

"""
项目名称:简单飞机大战游戏
基于框架:Pygame
开发日期:2020.07
开发人员:Y
版本:****
"""

import random  # 导入内置模块 random 调用randint方法
import pygame  # 导入第三方模块pygame

SRCEEN_SIZE = pygame.Rect(0, 0, 480, 700)  # 利用Rect方法定义窗口大小常量
CLOCK_TICK = 60  # 定义时钟帧率常量
CREAT_ENEMY_EVENT = pygame.USEREVENT  # 自定义创建敌机事件
FIRE_BULLTE = pygame.USEREVENT + 1  # 自定义发射子弹事件


class GameSprites(pygame.sprite.Sprite):  # 定义游戏精灵类 继承pygame.sprite.Sprite
    def __init__(self, image_name, speed=1):  # 定义初始化方法
        super().__init__()  # 因未继承object基类 定义初始化方法需要先super()下父类的 __init_方法
        self.image = pygame.image.load(image_name)  # 定义实例属性image为加载图片至内存中
        self.rect = self.image.get_rect()  # 定义实例属性rect为获取图片的矩形区域(0, 0, image.width, image.height)
        self.speed = speed  # 定义实例属性speed为运动速度 实质为移动的幅度,幅度大则速度快

    def update(self):  # 定义更新数据方法实现移动image
        self.rect.y += self.speed  # 移动image的Y轴距离为向下speed距离


class Background(GameSprites):  # 定义背景精灵类 继承游戏精灵类
    def __init__(self, is_alt=False):  # 在父类(游戏精灵类)基础上定义初始化方法 is_alt缺省参数用于判断是否为第二张image
        super().__init__("./images/background.png")
        # 因未继承object基类 定义初始化方法需要先super()下父类的 __init_方法 并以背景图为image为参数
        if is_alt:  # 判断是否为第二张image 如果是
            self.rect.y = -self.rect.height
            # 将第二张image的Y轴坐标设置为本身image.height的负值 用来实现将第二张image置于第一张image上方

    def update(self):  # 在父类(游戏精灵类)基础上修改 更新数据方法实现移动background_image
        super().update()  # 继承父类(游戏精灵类)的移动方式 按照speed向下移动
        if self.rect.y >= SRCEEN_SIZE.height:
            # 判断background_image在Y轴距离是否大于等于窗口高度 如果是
            # 表示第一张image全部下滑出窗口
            self.rect.y = -self.rect.height  # 需要重新将该image置于第二张image上方


class Enemy(GameSprites):  # 定义敌机精灵类 继承游戏精灵类
    def __init__(self, image):  # 在父类(游戏精灵类)基础上修改定义初始化方法 自定义参数image用于实现多种形式敌机
        super().__init__(image)
        # 因未继承object基类 定义初始化方法需要先super()下父类的 __init_方法 并以自定义背景图为image为参数
        self.speed = random.randint(1, 5)  # 修改敌机类image移动幅度(速度)为1--5随机值
        self.rect.bottom = 0  # 定义敌机类image的底部为0 表示每次从窗口最顶部驶入 美化效果
        MAX_WIDTH = SRCEEN_SIZE.width - self.rect.width
        # 定义常量为敌机对象出现时的image.x最大值 防止跑出窗口界面或只有敌机部分驶入窗口
        # 最大宽度 = 窗口宽度 - 敌机image的宽度
        self.rect.x = random.randint(0, MAX_WIDTH)
        # 设置敌机image的出现范围为限制在窗口内

    def update(self):  # 在父类(游戏精灵类)基础上修改 更新数据方法实现移动emeny_image
        super().update()  # 继承父类(游戏精灵类)的移动方式 按照speed向下移动
        if self.rect.y >= SRCEEN_SIZE.height:  # 判断敌机对象的Y轴距离是否超过窗口高度 如果是 表示敌机对象驶出窗口
            # print("敌机销毁")
            self.kill()  # 敌机对象驶出窗口后进行销毁 从内存中释放敌机image 减轻计算机内存压力

    def __del__(self):  # 定义敌机对象销毁前的动作,如爆炸动画,碰撞音频等等
        pass  # pass语句占位 待开发。。

class Hero(GameSprites):  # 定义英雄精灵类 继承游戏精灵类
    def __init__(self):  # 在父类(游戏精灵类)基础上修改定义初始化方法 实现英雄类image初始位置以及移动限制
        super().__init__("./images/me1.png", 0)
        # 因未继承object基类 定义初始化方法需要先super()下父类的 __init_方法 并以自定义英雄类image
        self.rect.centerx = SRCEEN_SIZE.centerx  # 限制英雄类对象只可以在X轴(水平方向)移动
        self.rect.bottom = SRCEEN_SIZE.bottom - 120  # 设置英雄类对象出现时底部位置为窗口底部上120px
        self.bullet_group = pygame.sprite.Group()  # 注意:内置子弹类精灵组为英雄类实例属性 提前设置子弹精灵组

    def update(self, *args):  # 注意:此方法不是在父类(游戏精灵类)基础上修改 更新数据方法实现移动hero_image
        # 因为英雄类对象不需要从上向下移动,无需继承父类(游戏精灵类)的update方法
        self.rect.x += self.speed  # 设置移动实例属性 在X轴水平方向以speed速度(幅度)移动
        if self.rect.x < 0:  # 判断英雄类实例在X轴坐标是否小于0 即是否移出窗口左侧 如果是
            self.rect.x = 0  # 重置(限制)英雄实例在X轴方向坐标为0 即窗口最左侧
        elif self.rect.right > SRCEEN_SIZE.right:   # 判断英雄类实例在X轴坐标是否大于窗口最右侧 即是否移除窗口右侧 如果是
            self.rect.right = SRCEEN_SIZE.right  # 重置(限制)英雄实例在X轴方向坐标为窗口最右侧 即窗口最右侧

    def fire(self):  # 英雄类精灵实例定义发射子弹方法
        print("发射子弹。。。")  # 控制台打印发射子弹。。。字样
        for i in (0, 1, 2):  # for计次循环用于实现子弹连发
            bullte = Bullet()  # 利用子弹精灵类创建子弹实例
            bullte.rect.bottom = self.rect.y - i * 20  # 设置子弹初始位置的最底部为英雄类对象Y轴方向的上方 i*20 px的距离
            bullte.rect.centerx = self.rect.centerx  # 限制子弹类对象位置始终为英雄类对象的X轴中间
            self.bullet_group.add(bullte)  # 对之前设置好的子弹精灵组进行添加精灵对象


class Bullet(GameSprites):  # 定义子弹精灵类 继承游戏精灵类
    def __init__(self): # 在父类(游戏精灵类)基础上修改定义初始化方法 实现子弹类image以及speed为-x 即向上移动speed
        super().__init__("./images/bullet1.png", -2)

    def update(self, *args): # 在父类(游戏精灵类)基础上 更新数据方法实现移动bullet_image
        super().update()  # 继承父类(游戏精灵类)的移动方式 按照speed向上移动
        if self.rect.bottom < 0:  # 判断子弹对象的Y轴距离是否超过窗口高度 如果是 表示子弹对象驶出窗口
            self.kill()  # 子弹对象驶出窗口后进行销毁 从内存中释放子弹image 减轻计算机内存压力

游戏截图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42842018/article/details/107774712