python基于pygame基础上开发飞机大战游戏

  • 文件目录
  •  constant.py:存放一些常量(速度,尺寸。。)的文件
    
  •  game_sprite:设计精灵的文件
    
  •  game_maneger.py:管理游戏进行的文件
    

contant.py

import pygame
import random
import os


# 定义游戏帧率
GAME_FRAME = 60
# 定义游戏窗口的大小
SCREEN_RECT = pygame.Rect(0, 0, 480, 600)
# 定义间距
MARGIN = 20
# 自定义创建敌方陨石的事件
EVENT_CREATE_STONE = pygame.USEREVENT
EVENT_CREATE_PLANE = pygame.USEREVENT + 1
# 定义所有陨石的文件名
# , 'meteorBrown_small1.png', 'meteorBrown_small2.png'
STONE_LIST = ['meteorBrown_big1.png', 'meteorBrown_big2.png', 'meteorBrown_med1.png', 'meteorBrown_med3.png']
# 图片所在的文件夹路径
IMAGE_FOLDER = os.path.join(os.path.dirname(__file__), 'img')

# 准备爆炸精灵字典
exp_animation = {'regular': [],'sonic': []}
for i in range(9):
    # 加载regular动画
    file_name_re = f'regularExplosion0{i}.png'
    exp_1 = pygame.image.load(os.path.join(IMAGE_FOLDER, file_name_re))
    exp_animation['regular'].append(exp_1)
    # 加载sonic动画
    file_name_so = f'sonicExplosion0{i}.png'
    exp_2 = pygame.image.load(os.path.join(IMAGE_FOLDER, file_name_so))
    exp_animation['sonic'].append(exp_2)

game_sprite.py

from constant import *

# 精灵的分析:
# 玩家飞机 玩家飞机的子弹 敌方飞机 敌方飞机的子弹 背景                     爆炸效果

# 继承关系
class GameSprite(pygame.sprite.Sprite):
    """游戏精灵的基类"""
    def __init__(self, img_src, speed=1):
        # 调用父类的初始化方法
        super().__init__()
        # 通过路径(图片)加载精灵
        self.image = pygame.image.load(img_src)
        # 获取image的大小
        self.rect = self.image.get_rect()
        self.speed = speed

    def update(self):
        """更新精灵的方法(自动被调用的)"""
        super().update()
        # 默认所有精灵都是向下移动
        self.rect.y += self.speed


class Background(GameSprite):
    def __init__(self, isFirst=True):
        super().__init__(img_src='./img/bg.png')   
        if not isFirst:
            # 如果你不是第一张图片
            # 此时设置第二张背景图的位置
            self.rect.y = -self.rect.height

    def update(self):
        super().update()
        # 判断当背景移动到windwow外的时候,改变移出屏幕的那张背景的位置
        if self.rect.y > SCREEN_RECT.height:
            self.rect.y = -self.rect.height


#玩家精灵类
class Player(GameSprite):
    def __init__(self):
        super().__init__(img_src='./img/player.png')
        # 是否存活
        self.islive = True
        # 改变加载的图像的尺寸
        self.image = pygame.transform.scale(self.image, (50, 38))
        # 获取精灵的大小
        self.rect = self.image.get_rect()
        # 给飞机设置初始位置
        # 设置飞机水平居中
        self.rect.centerx = SCREEN_RECT.width * .5
        self.rect.bottom = SCREEN_RECT.height - MARGIN
        # 给玩家飞机定义初始的水平速度
        self.speedx = 0
        self.speedy = 0
        # 定义子弹精灵组
        self.bullet_group = pygame.sprite.Group()

    def update(self):
        # 初始化水平速度
        self.speedx = 0
        self.speedy = 0

        # 获取用户的按键情况
        keystate = pygame.key.get_pressed()

        if keystate[pygame.K_LEFT]:
            self.speedx = -4
        if keystate[pygame.K_RIGHT]:
            self.speedx = 4
        if keystate[pygame.K_UP]:
            self.speedy = -4
        if keystate[pygame.K_DOWN]:
            self.speedy = 4
        
        # 改变自身x
        self.rect.x += self.speedx
        self.rect.y += self.speedy

        # 如何设置飞机的边界(确保飞机飞不出屏幕外)
        # 左边
        if self.rect.x < 0:
            self.rect.x = 0
        # 右边
        if self.rect.x > SCREEN_RECT.width - self.rect.width:
            self.rect.right = SCREEN_RECT.right

        # 上边
        if self.rect.y < 0:
            self.rect.top = 0    
        # 下边
        if self.rect.y > SCREEN_RECT.height - self.rect.height:
            self.rect.bottom = SCREEN_RECT.bottom

    def fire(self):
        # 创建子弹
        b = Bullet()
        # 初始化子弹的位置
        b.rect.bottom = self.rect.y - MARGIN
        b.rect.centerx = self.rect.centerx
        # 将子弹加入到子弹精灵组
        self.bullet_group.add(b)


#子弹精灵类
class Bullet(GameSprite):
    def __init__(self):
        super().__init__(img_src='./img/bullet.png', speed=-5)

    def update(self):
        super().update()
        # 如果子弹飞出屏幕外,处理掉这个精灵
        if self.rect.bottom < 0:
            self.kill()


#敌人精灵类
class Enemy(GameSprite):
    def __init__(self, stone_name):
        print(stone_name)
        super().__init__(img_src=f'./img/{stone_name}')

        # 设置石头的随机速度
        self.speedy = random.randint(2, 3)
        self.speedx = random.randint(-1, 2)

        # 设置石头的初始位置
        self.rect.bottom = -10
        self.rect.x = random.randint(0, SCREEN_RECT.width - self.rect.width)

    def update(self):
        super().update()
        # 叠加随机x速度
        self.rect.x += self.speedx
        self.rect.y += self.speedy

        # 判断陨石飞出边界
        if self.rect.y >= SCREEN_RECT.height or \
                  self.rect.left < -2 * MARGIN or \
                  self.rect.right > SCREEN_RECT.width + 2 * MARGIN:
            self.kill()

    def __del__(self):
        print("陨石被销毁了------------------>")

    
#精灵爆炸类
class Explosion(pygame.sprite.Sprite):
    def __init__(self, pos, anim_key):
        super().__init__()

        self.key = anim_key
        # 展示第一张
        self.image = exp_animation[self.key][0]
        self.rect = self.image.get_rect()
        # 给第一张图像初始化位置
        self.rect.center = pos

        # 索引
        self.index = 0
        self.frame_rate = 2
        
        self.last_time = pygame.time.get_ticks()
    
    def update(self):
        # 1. 获取当前帧的时间
        now_time = pygame.time.get_ticks()
        if now_time - self.last_time > self.frame_rate:
            # 记录上一帧的时间
            self.last_time = now_time
            # 控制索引递增
            self.index += 1

            if self.index == len(exp_animation[self.key]):
                self.kill()
            else:
                # 如果能来到这里,就开始切换下一张图片
                # 记录位置
                cur_pos = self.rect.center
                # 取出图像
                self.image = exp_animation[self.key][self.index]
                self.rect = self.image.get_rect()
                self.rect.center = cur_pos

game_manager.py

from game_sprite import *


class GameManager:
    def __init__(self):
        """游戏初始化阶段"""
        pygame.init()
        # 1. 设置游戏的窗口
        self.window = pygame.display.set_mode(SCREEN_RECT.size)
        # 2. 创建精灵
        self.create_sprite()
        # 3. 设置循环条件
        self.isRunning = True
        # 4. 设置游戏帧率
        # 4.1 创建时钟对象
        self.clock = pygame.time.Clock()
        self.clock.tick(GAME_FRAME)
        # 5. 设置定时器事件
        pygame.time.set_timer(EVENT_CREATE_STONE, 1000)

    def create_sprite(self):
        """创建游戏精灵"""
        # 1. 创建背景精灵类对象
        self.b1 = Background()
        self.b2 = Background(isFirst=False)
        # 2. 创建背景精灵组
        self.bg_group = pygame.sprite.Group(self.b1, self.b2)

        # 3. 创建玩家精灵
        self.player = Player()
        self.player_group = pygame.sprite.Group(self.player)

        # 4. 创建陨石精灵组
        self.stone_group = pygame.sprite.Group()

        # 5. 创建爆炸精灵组
        self.exp_group = pygame.sprite.Group()
        
    def update_sprites(self):
        """更新精灵""" 
        # 更新精灵组
        self.bg_group.update()
        self.bg_group.draw(self.window)

        # 更新玩家精灵组
        self.player_group.update()
        self.player_group.draw(self.window)

        # 更新子弹精灵组
        self.player.bullet_group.update()
        self.player.bullet_group.draw(self.window)

        # 更新陨石精灵组
        self.stone_group.update()
        self.stone_group.draw(self.window)

        # 更新爆炸精灵组
        self.exp_group.update()
        self.exp_group.draw(self.window)

    def event_handle(self):
        """事件监听"""
        for event in pygame.event.get():
            # print(event)
            if event.type == pygame.QUIT:
                self.isRunning = False
                self.game_over()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    # 让玩家飞机开火
                    self.player.fire()
            elif event.type == EVENT_CREATE_STONE:
                for _ in range(3):
                    # 获取随机索引
                    random_index = random.randint(0, len(STONE_LIST) - 1)
                    # 利用随机出来的索引去列表中取出对应的文件名
                    file_name = STONE_LIST[random_index]
                    # 创建陨石
                    enemy = Enemy(stone_name=file_name)
                    # 将陨石加入到陨石精灵组中
                    self.stone_group.add(enemy)
            

    def collide(self):
        """碰撞检测"""
        # 检测玩家的子弹精灵组和敌人精灵组之间的碰撞
        # groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict
        hit = pygame.sprite.groupcollide(self.player.bullet_group, self.stone_group, True, True)
        for h in hit:
            pos = h.rect.center
            # 生成爆炸精灵
            exp = Explosion(pos, 'regular')
            # 爆炸精灵加入到精灵组中
            self.exp_group.add(exp)


        # 玩家和敌人之间的碰撞检测
        # spritecollide(sprite, group, dokill, collided = None) -> Sprite_list
        # hit = pygame.sprite.spritecollide(self.player, self.stone_group, True)
        # if(self.player.islive):
        #     # -生命
        #     self.player.islive = False
        # else:
        #     self.player.kill()
        #     self.isRunning = False
        

        
    def gaming(self):
        """游戏阶段"""
        while self.isRunning:
            # 更新精灵组(绘制)
            self.update_sprites()
            # 事件监听
            self.event_handle()
            # 检测碰撞
            self.collide()
            # 刷新屏幕
            pygame.display.update()
        self.game_over()

    def game_over(self):
        """游戏结束"""
        pygame.quit()


if __name__ == "__main__":
    GameManager().gaming()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值