Python飞机大战游戏

# 导入模块顺序:官方标准模块、第三方模块、应用程序模块
import random
import pygame


SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
FRAME_PER_SEC = 60
CREATE_ENEMY_EVENT = pygame.USEREVENT
HERO_FIRE_EVENT = pygame.USEREVENT+1

# 定义子类,继承自Sprite类
# 精灵和精灵组
"""
简化开发步骤(图像加载、位置变化、绘制图像)提供的两个类
pygame.sprite.Sprite(存储图像数据和位置)
pygame.sprite.Group
update更新精灵位置
精灵组
update:让组中所有精灵调用update方法
draw:将组中所有精灵的图像各自绘制到不同的位置
"""


class GameSprite(pygame.sprite.Sprite):
    # 如果父类不是object的基类,在初始化方法中必须主动调用父类的初始化方法
    def __init__(self, image_name, speed=1):
        # 调用父类的初始化方法
        super().__init__()
        # 定义对象的属性,图像、位置、速度
        self.image = pygame.image.load(image_name)
        self.rect = self.image.get_rect()
        self.speed = speed

    def update(self):
        self.rect.y += self.speed


class Background(GameSprite):

    def __init__(self, is_alt=False):
        super().__init__("./images/background.png")
        if is_alt:
            self.rect.y = -self.rect.height

    def update(self):
        super().update()
        if self.rect.y > SCREEN_RECT.height:
            self.rect.y = -self.rect.height


class Enemy(GameSprite):

    def __init__(self):
        # 创建精灵
        super().__init__("./images/enemy1.png")
        # 指定初始随机速度和随机位置
        self.speed = random.randint(1, 3)
        self.rect.bottom = 0
        max_x = SCREEN_RECT.width-self.rect.width
        self.rect.x = random.randint(0, max_x)

    def update(self):
        super().update()
        # 敌机飞离屏幕,从精灵组删除
        if self.rect.y >= SCREEN_RECT.height:
            # 将它从所有精灵组移出,精灵被自动销毁,__del__方法自动被调用
            self.kill()

    def __del__(self):
        pass


class Hero(GameSprite):

    def __init__(self):
        super().__init__("./images/me1.png", 0)
        self.rect.bottom = SCREEN_RECT.bottom-120
        self.rect.centerx = SCREEN_RECT.centerx
        self.bullets = pygame.sprite.Group()

    def update(self):
        self.rect.x += self.speed
        if self.rect.x <= 0:
            self.rect.x = 0
        elif self.rect.right > SCREEN_RECT.right:
            self.rect.right = SCREEN_RECT.right

    def fire(self):
        for i in (0, 1, 2):
            bullet = Bullet()
            # 跟随英雄移动
            bullet.rect.bottom = self.rect.y-20*i
            bullet.rect.centerx = self.rect.centerx
            self.bullets.add(bullet)


class Bullet(GameSprite):
    def __init__(self):
        super().__init__("./images/bullet1.png", -2)

    def update(self):
        super().update()
        if self.rect.bottom < 0:
            self.kill()

    def __del__(self):
        pass

# 飞机大战游戏
from sprites import *


class PlaneGame(object):

    def __init__(self):
        # 游戏初始化
        # 1、使用pygame创建图形窗口
        # 创建游戏主窗口
        # 初始化游戏显示窗口 480*700指定屏幕的宽和高(默认屏幕大小),是否是全屏(默认不传递),颜色位数(默认自动匹配),一般只需要使用元组传递第一个参数即可
        # 返回结果就是游戏的主窗口
        self. screen = pygame.display.set_mode(SCREEN_RECT.size)
        # 2、设置游戏时钟,创建时钟对象
        self.clock = pygame.time.Clock()
        # 3、调用私有方法,创建精灵和精灵组
        self.__create_sprites()
        # 4、设置定时器事件,每隔一秒出现一架敌机,每隔0.5秒发射一次子弹,每次连发三枚
        pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
        pygame.time.set_timer(HERO_FIRE_EVENT, 500)

    def __create_sprites(self):
        # 游戏坐标系:原点左上角,x轴水平向右增加,y轴水平向下增加
        # 分别表示x y width weight,hero_rect也有这4个和size属性
        # 创建背景精灵和精灵组
        bg1 = Background()
        bg2 = Background(is_alt=True)
        self.bg_group = pygame.sprite.Group(bg1, bg2)
        self.enemy_group = pygame.sprite.Group()
        self.hero = Hero()
        self.hero_group = pygame.sprite.Group(self.hero)

    def start_game(self):
        # 游戏开始
        # 导入并初始化所有pygame模块,这样才能使用pygame的其他模块
        pygame.init()
        # 为使游戏启动后不会立即退出增加的一个游戏循环,本质就是一个无限循环,游戏循环意味着游戏正式开始
        # 设置刷新频率60、检测用户交互、更新所有图像位置、更新屏幕显示
        while True:
            # 1、循环中调用tick(帧率)方法
            self.clock.tick(FRAME_PER_SEC)
            # 2、监听事件
            self.__event_handler()
            # 3、碰撞检测
            self.__check_collide()
            # 4、更新/绘制精灵组
            self.__update_sprites()
            # 5、更新屏幕显示
            pygame.display.update()

    def __event_handler(self):
        # 事件监听
        event_list = pygame.event.get()
        for event in event_list:
            if event.type == pygame.QUIT:
                self.__game_over()
            elif event.type == CREATE_ENEMY_EVENT:
                # 到了敌机出场的时间
                enemy1 = Enemy()
                self.enemy_group.add(enemy1)
            # elif event.type == pygame.K_DOWN and event.type == pygame.K_RIGHT:
            # 不能识别连续按键
            elif event.type == HERO_FIRE_EVENT:
                self.hero.fire()
        keys_pressed = pygame.key.get_pressed()
        if keys_pressed[pygame.K_RIGHT]:
            self.hero.speed = 2
        elif keys_pressed[pygame.K_LEFT]:
            self.hero.speed = -2
        else:
            self.hero.speed = 0

    def __check_collide(self):
        # 两个精灵组中所有精灵的碰撞检测,dokill为True,发生碰撞的精灵自动移除,collided计算碰撞的回调函数
        # 子弹摧毁敌机
        pygame.sprite.groupcollide(self.hero.bullets,self.enemy_group,True,True)
        # 某个精灵和指定精灵组中的精灵碰撞
        # 敌机撞毁英雄
        enemies = pygame.sprite.spritecollide(self.hero,self.enemy_group,True)
        if len(enemies)>0:
            self.hero.kill()
            PlaneGame.__game_over()

    def __update_sprites(self):
        # 更新/绘制精灵组
        # self.screen.blit(bgImg, (0, 0))   self.screen.blit(hero, hero_rect)
        self.bg_group.update()
        self.bg_group.draw(self.screen)
        self.enemy_group.update()
        self.enemy_group.draw(self.screen)
        self.hero_group.update()
        self.hero_group.draw(self.screen)
        self.hero.bullets.update()
        self.hero.bullets.draw(self.screen)

    @staticmethod
    def __game_over():
        # 游戏结束
        pygame.quit()
        # 直接退出系统,终止当前正在执行的程序
        exit()


if __name__ == '__main__':
    # 创建游戏对象
    game = PlaneGame()
    # 启动游戏
    game.start_game()

综合体现了Python的面向对象编程的特性,并且对于pygame有了一定的理解。

posted @   [Crystal]  阅读(37)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示