python快速编程入门第二版 飞机大战

这篇具有很好参考价值的文章主要介绍了python快速编程入门第二版 飞机大战。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

飞机大战(完整版)



前言

飞机大战游戏以太空主题的画面为背景,由玩家通过键盘控制英雄,飞机向敌机总部发动进攻,在进攻的过程中既可以让英雄飞机发射子弹或引爆炸弹炸毁敌机获得分数,也可以拾取道具增强英雄的战斗力,一旦被敌机撞毁且生命值为0则游戏结束。


一、项目准备

项目模块
项目有game.py,game_items.py,game_hub.py,game_music.py四个文件
python飞机大战开始界面,python,pygame,开发语言

二、使用步骤

1.game.yp类

游戏主模块,封装game类并负责启动游戏

代码如下:

import random
import pygame
from game_items import *
from game_hud import *
from game_music import *


class Game(object):
    """游戏类"""
    def __init__(self):
        # 1. 游戏主窗口
        self.main_window = pygame.display.set_mode(SCREEN_RECT.size)
        pygame.display.set_caption("飞机大战")

        # 2. 游戏状态属性
        self.is_game_over = True                        # 游戏结束标记
        self.is_pause = False                           # 游戏暂停标记

        # 3. 精灵组属性
        self.all_group = pygame.sprite.Group()          # 所有精灵组
        self.enemies_group = pygame.sprite.Group()      # 敌机精灵组
        self.supplies_group = pygame.sprite.Group()     # 道具精灵组

        # 4. 创建精灵
        # 背景精灵,交替滚动
        self.all_group.add(Background(False), Background(True))

        # 指示器面板
        self.hud_panel = HUDPanel(self.all_group)

        # 创建敌机
        self.create_enemies()

        # 英雄精灵
        self.hero = Hero(self.all_group)

        # 设置面板中炸弹数量
        self.hud_panel.show_bomb(self.hero.bomb_count)

        # 创建道具
        self.create_supplies()

        # 5. 创建音乐播放器
        self.player = MusicPlayer("game_music.wav")
        self.player.play_music()

    def create_supplies(self):
        """创建道具"""
        Supply(0, self.supplies_group, self.all_group)
        Supply(1, self.supplies_group, self.all_group)

        # 设置 30s 投放道具定时器事件
        pygame.time.set_timer(THROW_SUPPLY_EVENT, 10000)

    def create_enemies(self):
        """根据游戏级别创建不同数量的敌机"""

        # 敌机精灵组中的精灵数量
        count = len(self.enemies_group.sprites())
        # 要添加到的精灵组
        groups = (self.all_group, self.enemies_group)

        # 判断游戏级别及已有的敌机数量
        if self.hud_panel.level == 1 and count == 0:        # 关卡 1
            for i in range(16):
                Enemy(0, 3, *groups)
        elif self.hud_panel.level == 2 and count == 16:     # 关卡 2
            # 1> 增加敌机的最大速度
            for enemy in self.enemies_group.sprites():
                enemy.max_speed = 5
            # 2> 创建敌机
            for i in range(8):
                Enemy(0, 5, *groups)
            for i in range(2):
                Enemy(1, 1, *groups)
        elif self.hud_panel.level == 3 and count == 26:     # 关卡 3
            # 1> 增加敌机的最大速度
            for enemy in self.enemies_group.sprites():
                enemy.max_speed = 7 if enemy.kind == 0 else 3
            # 2> 创建敌机
            for i in range(8):
                Enemy(0, 7, *groups)
            for i in range(2):
                Enemy(1, 3, *groups)
            for i in range(2):
                Enemy(2, 1, *groups)

    def reset_game(self):
        """重设游戏"""
        self.is_game_over = False               # 游戏结束标记
        self.is_pause = False                   # 游戏暂停标记

        self.hud_panel.reset_panel()            # 重置指示器面板

        # 设置英雄的初始位置
        self.hero.rect.midbottom = HERO_DEFAULT_MID_BOTTOM

        # 清空所有敌机
        for enemy in self.enemies_group:
            enemy.kill()

        # 清空残留子弹
        for bullet in self.hero.bullets_group:
            bullet.kill()

        # 重新创建敌机
        self.create_enemies()

    def event_handler(self):
        """事件监听

        :return: 如果监听到退出事件,返回 True,否则返回 False
        """
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                if self.is_game_over:           # 游戏已经结束
                    self.reset_game()
                else:                           # 切换暂停状态
                    self.is_pause = not self.is_pause

                    # 暂停或恢复背景音乐
                    self.player.pause_music(self.is_pause)

            # 判断是否正在游戏
            if not self.is_game_over and not self.is_pause:
                # 监听关闭子弹增强事件
                if event.type == BULLET_ENHANCED_OFF_EVENT:
                    self.hero.bullets_kind = 0

                    pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 0)

                # 监听投放道具事件
                if event.type == THROW_SUPPLY_EVENT:
                    self.player.play_sound("supply.wav")

                    supply = random.choice(self.supplies_group.sprites())

                    supply.throw_supply()

                # 监听发射子弹事件
                if event.type == HERO_FIRE_EVENT:
                    self.player.play_sound("bullet.wav")

                    self.hero.fire(self.all_group)

                # 监听取消英雄无敌事件
                if event.type == HERO_POWER_OFF_EVENT:
                    print("取消无敌状态...")

                    # 设置英雄属性
                    self.hero.is_power = False

                    # 取消定时器
                    pygame.time.set_timer(HERO_POWER_OFF_EVENT, 0)

                # 监听英雄牺牲事件
                if event.type == HERO_DEAD_EVENT:
                    print("英雄牺牲了...")

                    # 生命计数 -1
                    self.hud_panel.lives_count -= 1

                    # 更新生命计数显示
                    self.hud_panel.show_lives()
                    # 更新炸弹显示
                    self.hud_panel.show_bomb(self.hero.bomb_count)

                # 监听玩家按下字母 b,引爆炸弹
                if event.type == pygame.KEYDOWN and event.key == pygame.K_b:
                    # 如果英雄没有牺牲同时有炸弹
                    if self.hero.hp > 0 and self.hero.bomb_count > 0:
                        self.player.play_sound("use_bomb.wav")

                    # 引爆炸弹
                    score = self.hero.blowup(self.enemies_group)

                    # 更新炸弹数量显示
                    self.hud_panel.show_bomb(self.hero.bomb_count)

                    # 更新游戏得分,如果游戏等级提升,创建新的敌机
                    if self.hud_panel.increase_score(score):
                        self.create_enemies()

        return False

    def start(self):
        """开始游戏"""

        clock = pygame.time.Clock()             # 游戏时钟
        frame_counter = 0                       # 逐帧动画计数器

        while True:
            # 生命计数等于 0,表示游戏结束
            self.is_game_over = self.hud_panel.lives_count == 0

            if self.event_handler():            # 事件监听
                self.hud_panel.save_best_score()

                return

            # 判断游戏状态
            if self.is_game_over:
                self.hud_panel.panel_pause(True, self.all_group)
            elif self.is_pause:
                self.hud_panel.panel_pause(False, self.all_group)
            else:
                self.hud_panel.panel_resume(self.all_group)

                # 碰撞检测
                self.check_collide()

                # 获得当前时刻的按键元组
                keys = pygame.key.get_pressed()
                # 水平移动基数
                move_hor = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
                # 垂直移动基数
                move_ver = keys[pygame.K_DOWN] - keys[pygame.K_UP]

                # 修改逐帧动画计数器
                frame_counter = (frame_counter + 1) % FRAME_INTERVAL

                # 更新 all_group 中所有精灵内容
                self.all_group.update(frame_counter == 0, move_hor, move_ver)

            # 绘制 all_group 中的所有精灵
            self.all_group.draw(self.main_window)

            pygame.display.update()             # 更新显示
            clock.tick(60)                      # 设置刷新帧率

    def check_collide(self):
        """碰撞检测"""

        # 1. 检测英雄飞机和敌机的碰撞 - 如果英雄处于无敌状态,彼此不能碰撞
        if not self.hero.is_power:
            enemies = pygame.sprite.spritecollide(self.hero,
                                                  self.enemies_group,
                                                  False,
                                                  pygame.sprite.collide_mask)

            # 过滤掉已经被摧毁的敌机
            enemies = list(filter(lambda x: x.hp > 0, enemies))

            # 是否撞到敌机
            if enemies:
                # 播放英雄被撞毁音效
                self.player.play_sound(self.hero.wav_name)

                self.hero.hp = 0                # 英雄被撞毁

            for enemy in enemies:
                enemy.hp = 0                    # 敌机同样被撞毁

        # 2. 检测敌机被子弹击中
        hit_enemies = pygame.sprite.groupcollide(self.enemies_group,
                                                 self.hero.bullets_group,
                                                 False,
                                                 False,
                                                 pygame.sprite.collide_mask)

        # 遍历字典
        for enemy in hit_enemies:

            # 已经被摧毁的敌机不需要浪费子弹
            if enemy.hp <= 0:
                continue

            # 遍历击中敌机的子弹列表
            for bullet in hit_enemies[enemy]:

                # 1> 将子弹从所有精灵组中清除
                bullet.kill()

                # 2> 修改敌机的生命值
                enemy.hp -= bullet.damage

                # 3> 如果敌机没有被摧毁,继续下一颗子弹
                if enemy.hp > 0:
                    continue

                # 4> 修改游戏得分并判断是否升级
                if self.hud_panel.increase_score(enemy.value):
                    # 播放升级音效
                    self.player.play_sound("upgrade.wav")

                    self.create_enemies()

                # 播放敌机炸弹音效
                self.player.play_sound(enemy.wav_name)

                # 5> 退出遍历子弹列表循环
                break

        # 3. 英雄拾取道具
        supplies = pygame.sprite.spritecollide(self.hero,
                                               self.supplies_group,
                                               False,
                                               pygame.sprite.collide_mask)
        if supplies:
            supply = supplies[0]

            # 播放使用道具音效
            self.player.play_sound(supply.wav_name)

            # 将道具设置到游戏窗口下方
            supply.rect.y = SCREEN_RECT.h

            # 判断道具类型
            if supply.kind == 0:                # 炸弹补给
                self.hero.bomb_count += 1
                self.hud_panel.show_bomb(self.hero.bomb_count)
            else:                               # 设置子弹增强
                self.hero.bullets_kind = 1

                # 设置关闭子弹增强的定时器事件
                pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 8000)


if __name__ == '__main__':
    pygame.init()

    Game().start()

    pygame.quit()

2.game_items类

游戏元素模块,封装英雄飞机,子弹,敌机,道具等游戏元素类,并定义全局变量

代码如下(示例):

import random
import pygame

# 全局常量定义
SCREEN_RECT = pygame.Rect(0, 0, 480, 700)       # 游戏主窗口矩形区域
FRAME_INTERVAL = 10                             # 逐帧动画间隔帧数

HERO_BOMB_COUNT = 3                             # 英雄默认炸弹数量
# 英雄默认初始位置
HERO_DEFAULT_MID_BOTTOM = (SCREEN_RECT.centerx,
                           SCREEN_RECT.bottom - 90)

HERO_DEAD_EVENT = pygame.USEREVENT              # 英雄牺牲事件
HERO_POWER_OFF_EVENT = pygame.USEREVENT + 1     # 取消英雄无敌事件
HERO_FIRE_EVENT = pygame.USEREVENT + 2          # 英雄发射子弹事件

THROW_SUPPLY_EVENT = pygame.USEREVENT + 3       # 投放道具事件
BULLET_ENHANCED_OFF_EVENT = pygame.USEREVENT + 4  # 关闭子弹增强事件


class Label(pygame.sprite.Sprite):
    """文本标签精灵"""

    font_path = "./res/font/MarkerFelt.ttc"     # 字体文件路径

    def __init__(self, text, size, color, *groups):
        """初始化方法

        :param text: 文本内容
        :param size: 字体大小
        :param color: 字体颜色
        :param groups: 要添加到的精灵组
        """
        super().__init__(*groups)

        self.font = pygame.font.Font(self.font_path, size)
        self.color = color

        self.image = self.font.render(text, True, self.color)
        self.rect = self.image.get_rect()

    def set_text(self, text):
        """设置文本,使用指定的文本重新渲染 image,并且更新 rect

        :param text: 文本内容
        """
        self.image = self.font.render(text, True, self.color)
        self.rect = self.image.get_rect()


class GameSprite(pygame.sprite.Sprite):
    """游戏精灵类"""

    res_path = "./res/images/"                  # 图片资源路径

    def __init__(self, image_name, speed, *groups):
        """初始化方法

        :param image_name: 要加载的图片文件名
        :param speed: 移动速度,0 表示静止
        :param groups: 要添加到的精灵组,不传则不添加
        """
        super().__init__(*groups)

        self.image = pygame.image.load(self.res_path + image_name)  # 图像
        self.rect = self.image.get_rect()       # 矩形区域,默认在左上角
        self.speed = speed                      # 移动速度

        # 图像遮罩,可以提高碰撞检测的执行性能
        self.mask = pygame.mask.from_surface(self.image)

    def update(self, *args):
        """更新精灵位置,默认在垂直方向移动

        :param args:
        """
        self.rect.y += self.speed


class StatusButton(GameSprite):
    """状态按钮类"""

    def __init__(self, image_names, *groups):
        """初始化方法

        :param image_names: 要加载的图像名称列表
        :param groups: 要添加到的精灵组
        """
        super().__init__(image_names[0], 0, *groups)

        # 加载图像
        self.images = [pygame.image.load(self.res_path + name)
                       for name in image_names]

    def switch_status(self, is_pause):
        """切换状态

        :param is_pause: 是否暂停
        """
        self.image = self.images[1 if is_pause else 0]


class Background(GameSprite):
    """背景精灵类"""

    def __init__(self, is_alt, *groups):

        super().__init__("background.png", 1, *groups)

        # 判断是否是另 1 个精灵
        if is_alt:
            self.rect.y = -self.rect.h          # 设置到游戏窗口正上方

    def update(self, *args):

        super().update(*args)                   # 向下运动

        # 判断是否移出游戏窗口
        if self.rect.y >= self.rect.h:
            self.rect.y = -self.rect.h


class Plane(GameSprite):
    """飞机类"""

    def __init__(self, hp, speed, value, wav_name,
                 normal_names, hurt_name, destroy_names, *groups):
        """初始化方法

        :param hp: 生命值
        :param speed: 速度
        :param value: 得分
        :param wav_name: 音频文件名
        :param normal_names: 正常飞行图像名称列表
        :param hurt_name: 受伤图像文件名
        :param destroy_names: 被摧毁图像文件名
        :param groups: 要添加到的精灵组
        """

        super().__init__(normal_names[0], speed, *groups)

        # 飞机属性
        self.hp = hp
        self.max_hp = hp
        self.value = value
        self.wav_name = wav_name

        # 图像属性
        # 1> 正常图像列表及索引
        self.normal_images = [pygame.image.load(self.res_path + name)
                              for name in normal_names]
        self.normal_index = 0
        # 2> 受伤图像
        self.hurt_image = pygame.image.load(self.res_path + hurt_name)
        # 3> 被摧毁图像列表及索引
        self.destroy_images = [pygame.image.load(self.res_path + name)
                               for name in destroy_names]
        self.destroy_index = 0

    def reset_plane(self):
        """重置飞机"""
        self.hp = self.max_hp                   # 生命值

        self.normal_index = 0                   # 正常状态图像索引
        self.destroy_index = 0                  # 被摧毁状态图像索引

        self.image = self.normal_images[0]      # 恢复正常图像

    def update(self, *args):

        # 如果第 0 个参数为 False,不需要更新图像,直接返回
        if not args[0]:
            return

        # 判断飞机状态
        if self.hp == self.max_hp:              # 未受伤
            self.image = self.normal_images[self.normal_index]

            count = len(self.normal_images)
            self.normal_index = (self.normal_index + 1) % count
        elif self.hp > 0:                       # 受伤
            self.image = self.hurt_image
        else:                                   # 被摧毁
            # 判断是否显示到最后一张图像,如果是说明飞机完全被摧毁
            if self.destroy_index < len(self.destroy_images):
                self.image = self.destroy_images[self.destroy_index]

                self.destroy_index += 1
            else:
                self.reset_plane()              # 重置飞机


class Enemy(Plane):
    """敌机类"""

    def __init__(self, kind, max_speed, *groups):
        """初始化方法

        :param kind: 敌机类型 0 小敌机 1 中敌机 2 大敌机
        :param max_speed: 最大速度
        :param groups: 要添加到的精灵组
        """
        # 1. 记录敌机类型和最大速度
        self.kind = kind
        self.max_speed = max_speed

        # 2. 根据类型调用父类方法传递不同参数
        if kind == 0:
            super().__init__(1, 1, 1000, "enemy1_down.wav",
                             ["enemy1.png"],
                             "enemy1.png",
                             ["enemy1_down%d.png" % i for i in range(1, 5)],
                             *groups)
        elif kind == 1:
            super().__init__(6, 1, 6000, "enemy2_down.wav",
                             ["enemy2.png"],
                             "enemy2_hit.png",
                             ["enemy2_down%d.png" % i for i in range(1, 5)],
                             *groups)
        else:
            super().__init__(15, 1, 15000, "enemy3_down.wav",
                             ["enemy3_n1.png", "enemy3_n2.png"],
                             "enemy3_hit.png",
                             ["enemy3_down%d.png" % i for i in range(1, 7)],
                             *groups)

        # 3. 调用重置飞机方法,设置敌机初始位置和速度
        self.reset_plane()

    def reset_plane(self):
        """重置飞机"""
        super().reset_plane()

        # 设置初始随机位置
        x = random.randint(0, SCREEN_RECT.w - self.rect.w)
        y = random.randint(0, SCREEN_RECT.h - self.rect.h) - SCREEN_RECT.h

        self.rect.topleft = (x, y)

        # 设置初始速度
        self.speed = random.randint(1, self.max_speed)

    def update(self, *args):
        """更新图像和位置"""

        # 调用父类方法更新飞机图像 - 注意 args 需要拆包
        super().update(*args)

        # 判断敌机是否被摧毁,否则使用速度更新飞机位置
        if self.hp > 0:
            self.rect.y += self.speed

        # 判断是否飞出屏幕,如果是,重置飞机
        if self.rect.y >= SCREEN_RECT.h:
            self.reset_plane()


class Hero(Plane):
    """英雄类"""

    def __init__(self, *groups):
        """初始化方法

        :param groups: 要添加到的精灵组
        """
        super().__init__(1000, 5, 0, "me_down.wav",
                         ["me%d.png" % i for i in range(1, 3)],
                         "me1.png",
                         ["me_destroy_%d.png" % i for i in range(1, 5)],
                         *groups)

        self.is_power = False                       # 无敌标记
        self.bomb_count = HERO_BOMB_COUNT           # 炸弹数量

        self.bullets_kind = 0                       # 子弹类型
        self.bullets_group = pygame.sprite.Group()  # 子弹精灵组

        # 初始位置
        self.rect.midbottom = HERO_DEFAULT_MID_BOTTOM

        # 设置 0.2 秒发射子弹定时器事件
        pygame.time.set_timer(HERO_FIRE_EVENT, 200)

    def reset_plane(self):
        """重置英雄"""

        # 调用父类方法重置图像相关属性
        super().reset_plane()

        self.is_power = True                    # 无敌标记

        self.bomb_count = HERO_BOMB_COUNT       # 炸弹数量
        self.bullets_kind = 0                   # 子弹类型

        # 发布英雄牺牲事件
        pygame.event.post(pygame.event.Event(HERO_DEAD_EVENT))

        # 设置 3 秒之后取消无敌定时器事件
        pygame.time.set_timer(HERO_POWER_OFF_EVENT, 3000)

    def update(self, *args):
        """更新英雄的图像及矩形区域

        :param args: 0 更新图像标记 1 水平移动基数 2 垂直移动基数
        """

        # 调用父类方法更新飞机图像 - 注意 args 需要拆包
        super().update(*args)

        # 如果没有传递方向基数或者英雄被撞毁,直接返回
        if len(args) != 3 or self.hp <= 0:
            return

        # 调整水平移动距离
        self.rect.x += args[1] * self.speed
        self.rect.y += args[2] * self.speed

        # 限定在游戏窗口内部移动
        self.rect.x = 0 if self.rect.x < 0 else self.rect.x
        if self.rect.right > SCREEN_RECT.right:
            self.rect.right = SCREEN_RECT.right

        self.rect.y = 0 if self.rect.y < 0 else self.rect.y
        if self.rect.bottom > SCREEN_RECT.bottom:
            self.rect.bottom = SCREEN_RECT.bottom

    def blowup(self, enemies_group):
        """引爆炸弹

        :param enemies_group: 敌机精灵组
        :return: 累计得分
        """

        # 1. 如果没有足够数量的炸弹或者英雄被撞毁,直接返回
        if self.bomb_count <= 0 or self.hp <= 0:
            return 0

        self.bomb_count -= 1                    # 炸弹数量 - 1
        score = 0                               # 本次得分
        count = 0                               # 炸毁数量

        # 2. 遍历敌机精灵组,将游戏窗口内的敌机引爆
        for enemy in enemies_group.sprites():

            # 判断敌机是否进入游戏窗口
            if enemy.rect.bottom > 0:
                score += enemy.value            # 计算得分
                count += 1                      # 累计数量

                enemy.hp = 0                    # 摧毁敌机

        print("炸毁了 %d 架敌机,得分 %d" % (count, score))

        return score

    def fire(self, display_group):
        """发射子弹

        :param display_group: 要添加的显示精灵组
        """
        # 需要将子弹精灵添加到两个精灵组
        groups = (self.bullets_group, display_group)

        # 测试子弹增强效果
        # self.bullets_kind = 1

        for i in range(3):
            # 创建子弹精灵
            bullet1 = Bullet(self.bullets_kind, *groups)

            # 计算子弹的垂直位置
            y = self.rect.y - i * 15

            # 判断子弹类型
            if self.bullets_kind == 0:
                bullet1.rect.midbottom = (self.rect.centerx, y)
            else:
                bullet1.rect.midbottom = (self.rect.centerx - 20, y)

                # 再创建一颗子弹
                bullet2 = Bullet(self.bullets_kind, *groups)
                bullet2.rect.midbottom = (self.rect.centerx + 20, y)


class Bullet(GameSprite):
    """子弹类"""

    def __init__(self, kind, *groups):
        """初始化方法

        :param kind: 子弹类型
        :param groups: 要添加到的精灵组
        """

        image_name = "bullet1.png" if kind == 0 else "bullet2.png"
        super().__init__(image_name, -12, *groups)

        self.damage = 1                         # 杀伤力

    def update(self, *args):

        super().update(*args)                   # 向上移动

        # 判断是否从上方飞出窗口
        if self.rect.bottom < 0:
            self.kill()


class Supply(GameSprite):
    """道具类"""

    def __init__(self, kind, *groups):
        """初始化方法

        :param kind: 道具类型
        :param groups: 要添加到的精灵组
        """

        # 调用父类方法
        image_name = "%s_supply.png" % ("bomb" if kind == 0 else "bullet")
        super().__init__(image_name, 5, *groups)

        # 道具类型
        self.kind = kind
        # 音频文件名
        self.wav_name = "get_%s.wav" % ("bomb" if kind == 0 else "bullet")

        # 初始位置
        self.rect.y = SCREEN_RECT.h

    def throw_supply(self):
        """投放道具"""
        self.rect.bottom = 0
        self.rect.x = random.randint(0, SCREEN_RECT.w - self.rect.w)

    def update(self, *args):
        """更新位置,在屏幕下方不移动"""

        if self.rect.h > SCREEN_RECT.h:
            return

        # 调用父类方法,沿垂直方向移动位置
        super().update(*args)

3.game_hub类

import pygame
from game_items import *


class HUDPanel(object):
    """指示器面板类"""

    margin = 10                                 # 精灵之间的间距
    white = (255, 255, 255)                     # 白色
    gray = (64, 64, 64)                         # 灰色

    reward_score = 100000                       # 奖励分值
    level2_score = 10000                        # 级别 2 分值
    level3_score = 50000                        # 级别 3 分值

    record_filename = "record.txt"              # 最好成绩文件名

    def __init__(self, display_group):
        """初始化方法

        :param display_group: 面板中的精灵要被添加到的显示精灵组
        """

        # 1. 游戏属性
        self.score = 0                          # 游戏得分
        self.lives_count = 3                    # 生命计数
        self.level = 1                          # 游戏级别
        self.best_score = 0                     # 最好成绩

        self.load_best_score()                  # 加载最好成绩

        # 2. 创建图像精灵
        # 1> 状态精灵
        self.status_sprite = StatusButton(("pause.png", "resume.png"), display_group)
        self.status_sprite.rect.topleft = (self.margin, self.margin)

        # 2> 炸弹精灵
        self.bomb_sprite = GameSprite("bomb.png", 0, display_group)
        self.bomb_sprite.rect.x = self.margin
        self.bomb_sprite.rect.bottom = SCREEN_RECT.bottom - self.margin

        # 3> 生命计数精灵
        self.lives_sprite = GameSprite("life.png", 0, display_group)
        self.lives_sprite.rect.right = SCREEN_RECT.right - self.margin
        self.lives_sprite.rect.bottom = SCREEN_RECT.bottom - self.margin

        # 3. 创建标签精灵
        # 1> 分数标签
        self.score_label = Label("%d" % self.score, 32, self.gray, display_group)
        self.score_label.rect.midleft = (self.status_sprite.rect.right + self.margin,
                                         self.status_sprite.rect.centery)

        # 2> 炸弹标签
        self.bomb_label = Label("X 3", 32, self.gray, display_group)
        self.bomb_label.rect.midleft = (self.bomb_sprite.rect.right + self.margin,
                                        self.bomb_sprite.rect.centery)

        # 3> 生命计数标签
        self.lives_label = Label("X %d" % self.lives_count, 32, self.gray, display_group)
        self.lives_label.rect.midright = (SCREEN_RECT.right - self.margin,
                                          self.bomb_label.rect.centery)
        # 调整生命计数精灵位置
        self.lives_sprite.rect.right = self.lives_label.rect.left - self.margin

        # 4> 最好成绩标签
        self.best_label = Label("Best: %d" % self.best_score, 36, self.white)

        # 5> 状态标签
        self.status_label = Label("Game Over!", 48, self.white)

        # 6> 提示标签
        self.tip_label = Label("Press spacebar to play again.", 22, self.white)

    def reset_panel(self):
        """重置面板"""

        # 1. 游戏属性
        self.score = 0                          # 游戏得分
        self.lives_count = 3                    # 生命计数

        # 2. 标签显示
        self.increase_score(0)                  # 增加 0 分
        self.show_bomb(3)                       # 炸弹数量
        self.show_lives()                       # 生命计数标签

    def panel_pause(self, is_game_over, display_group):
        """面板暂停

        :param is_game_over: 是否因为游戏结束需要暂停
        :param display_group: 显示精灵组
        """
        # 判断是否已经添加了精灵,如果是直接返回
        if display_group.has(self.status_label,
                             self.tip_label,
                             self.best_label):
            return

        # 根据是否结束游戏决定要显示的文字
        text = "Game Over!" if is_game_over else "Game Paused!"
        tip = "Press spacebar to "
        tip += "play again." if is_game_over else "continue."

        # 设置标签文字
        self.best_label.set_text("Best: %d" % self.best_score)
        self.status_label.set_text(text)
        self.tip_label.set_text(tip)

        # 设置标签位置
        self.best_label.rect.center = SCREEN_RECT.center

        best_rect = self.best_label.rect
        self.status_label.rect.midbottom = (best_rect.centerx,
                                            best_rect.y - 2 * self.margin)
        self.tip_label.rect.midtop = (best_rect.centerx,
                                      best_rect.bottom + 8 * self.margin)

        # 添加到精灵组
        display_group.add(self.best_label, self.status_label, self.tip_label)

        # 切换状态精灵状态
        self.status_sprite.switch_status(True)

    def panel_resume(self, display_group):
        """面板恢复

        :param display_group: 显示精灵组
        """
        # 从精灵组移除 3 个标签精灵
        display_group.remove(self.status_label,
                             self.tip_label,
                             self.best_label)

        # 切换状态精灵状态
        self.status_sprite.switch_status(False)

    def show_bomb(self, count):
        """显示炸弹数量

        :param count: 要显示的炸弹数量
        """
        # 设置炸弹标签文字
        self.bomb_label.set_text("X %d" % count)

        # 设置炸弹标签位置
        self.bomb_label.rect.midleft = (self.bomb_sprite.rect.right + self.margin,
                                        self.bomb_sprite.rect.centery)

    def show_lives(self):
        """显示生命计数
        """
        # 设置生命计数标签文字
        self.lives_label.set_text("X %d" % self.lives_count)

        # 设置生命计数标签位置
        self.lives_label.rect.midright = (SCREEN_RECT.right - self.margin,
                                          self.bomb_label.rect.centery)
        # 调整生命计数精灵位置
        self.lives_sprite.rect.right = self.lives_label.rect.left - self.margin

    def increase_score(self, enemy_score):
        """增加游戏得分

        :param enemy_score: 摧毁敌机的分值
        :return: 增加 enemy_score 后,游戏级别是否提升
        """

        # 1. 游戏得分
        score = self.score + enemy_score

        # 2. 判断是否奖励生命
        if score // self.reward_score != self.score // self.reward_score:
            self.lives_count += 1
            self.show_lives()

        self.score = score

        # 3. 最好成绩
        self.best_score = score if score > self.best_score else self.best_score

        # 4. 游戏级别
        if score < self.level2_score:
            level = 1
        elif score < self.level3_score:
            level = 2
        else:
            level = 3

        is_upgrade = level != self.level
        self.level = level

        # 5. 修改得分标签内容和位置
        self.score_label.set_text("%d" % self.score)
        self.score_label.rect.midleft = (self.status_sprite.rect.right + self.margin,
                                         self.status_sprite.rect.centery)

        return is_upgrade

    def save_best_score(self):
        """将最好成绩写入 record.txt"""

        file = open(self.record_filename, "w")

        file.write("%d" % self.best_score)

        file.close()

    def load_best_score(self):
        """从 record.txt 加载最好成绩"""

        try:
            file = open(self.record_filename)

            txt = file.readline()

            file.close()

            self.best_score = int(txt)
        except (FileNotFoundError, ValueError):
            print("文件不存在或者类型转换错误")

4.game_music类

游戏音乐模块,封装音乐播放器类

import os   # 需要遍历 res/sound 目录下的文件
import pygame


class MusicPlayer(object):
    """音乐播放器类"""

    res_path = "./res/sound/"                   # 声音资源路径

    def __init__(self, music_file):
        """初始化方法

        :param music_file: 背景音乐文件名
        """
        # 1. 加载背景音乐
        pygame.mixer.music.load(self.res_path + music_file)
        pygame.mixer.music.set_volume(0.2)

        # 2. 加载音效字典
        # 1> 定义音效字典属性
        self.sound_dict = {}

        # 2> 获取目录下的文件列表
        files = os.listdir(self.res_path)

        # 3> 遍历文件列表
        for file_name in files:

            # 排除背景音乐
            if file_name == music_file:
                continue

            # 创建声音对象
            sound = pygame.mixer.Sound(self.res_path + file_name)

            # 添加到音效字典,使用文件名作为字典的 key
            self.sound_dict[file_name] = sound

    def play_sound(self, wav_name):
        """播放音效

        :param wav_name: 音效文件名
        """
        self.sound_dict[wav_name].play()

    @staticmethod
    def play_music():
        pygame.mixer.music.play(-1)

    @staticmethod
    def pause_music(is_pause):
        if is_pause:
            pygame.mixer.music.pause()
        else:
            pygame.mixer.music.unpause()

结果展示

python飞机大战开始界面,python,pygame,开发语言

计科在读,才疏学浅,有问题欢迎指正。源码以上传,小伙伴们,快动手试试吧!
链接:https://pan.baidu.com/s/192CCs9aPYIQaVAqIPTliGA?pwd=wstt
提取码:wstt
联系方式:2673628721文章来源地址https://www.toymoban.com/news/detail-539534.html

到了这里,关于python快速编程入门第二版 飞机大战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python实现飞机大战

    2024年03月24日
    浏览(47)
  • python项目:飞机大战已封装(第一部分)第二部分在飞机大战专辑,后期合并

    图片资源已经展示在了顶部 上面我们用import进行了导包以方便后期调用,并用pygame.init()进行了初始化,pygame的所有使用都需要初始化,然后用pygame.display.set_mode创建游戏总画布注意总画布大小要与背景图相关联 英雄子弹类解析 在许多射击游戏中,子弹类是基本的组成部分之

    2024年04月17日
    浏览(37)
  • python——飞机大战小游戏

    目录 1、导入模块 2、窗口操作 3、事件操作 4、长按事件 5、添加游戏背景 6、添加英雄飞机 7、获取飞机的图片矩形 8、基本游戏窗口 9、添加游戏窗口图片 10、英雄飞机登场 11、英雄飞机装备子弹并发射 1、enemy_plane 2、game_main 3、game_map 4、game_score 5、hero_plane 6、plane_bullet 先安

    2024年02月03日
    浏览(61)
  • Python飞机大战小游戏

    游戏规则:键盘上下左右键控制飞机移动 游戏展示图片: 源码: 第一个py命名为:plane_main.py 第二py命名为:plane_sprites.py 素材图片image关注私信我获取!!!

    2024年02月10日
    浏览(52)
  • Python——飞机大战(day10)

    一、面向过程实现 二、面向对象 plane pro需求的描述: 存在四个对象: 我方飞机、敌方飞机、我方子弹、敌方子弹 功能: 背景音乐的添加 我方飞机可以移动【根据按键来控制的】 敌方飞机也可以移动【随机的自动移动】 双方飞机都可以发送子弹 步骤: 1.创建一个窗口 2.创建

    2023年04月09日
    浏览(33)
  • python飞机大战实战演练代码

    # 以下是飞机大战的精灵组函数

    2024年02月08日
    浏览(45)
  • python---简单游戏制作(飞机大战)

    1.开发软件 pycharm 编程软件 pygame 第三方库 sprite Group 2.技术介绍      pycharm: PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外,该IDE提供

    2024年02月12日
    浏览(46)
  • python小游戏开发(飞机大战)

    目录 一:背景       1. pygame 模块初识 二.项目设计内容 开发一款飞机大战游戏,要求: (1)实现飞机的移动、子弹发射,对本次游戏有一个初步的编写及认识。 (2)飞机的持续按键移动和飞机自爆优化。 (3)进行基类的抽取,使代码更具有层次性和简化重复代码。 (

    2024年02月16日
    浏览(46)
  • Python代码下的飞机大战

    飞机大战项目 本项目的优点就是,不需要你创建很多复杂的文件夹,单个操作台就可以完成飞机大战游戏的基础版本。如果你感兴趣,就快去试一试吧!素材链接也在下面喽,快去开启你的游戏之旅吧! 素材链接:链接:https://pan.baidu.com/s/1Mb5w-_I-oUi-W0n0jHFYXw 百度网盘提取码

    2024年04月10日
    浏览(40)
  • 用python写(飞机大战小游戏)

    w\\\'cwc下面我们进入详细教程:   一、首先我们先建一个文件夹 planewars(名字随便取):  然后用我们python中的pycharm打开这个文件,我们飞机大战的项目就在这进行 二、我们要写这个小游戏要用到pygame模         补充: Pygame是一个利用SDL库的写就的游戏库,Pygame就是Python中使用

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包