python3 武装飞船游戏实战 代码及详细注释

项目描述:

        制作一款2D的游戏飞机大战,在游戏中,玩家控制一艘飞船最初出现在屏幕底部中央的飞船。玩家可以使用箭头左右移动飞船,空格射击。游戏开始,一群不明生物飞在天空,并像屏幕下方移动,玩家需要击杀这些不明生物,随着击杀的次数,不明生物的移动生物速度更快,只要有生物撞到玩家或达到底部,玩家损失一艘飞船,损失你三艘飞船以后,游戏结束。 

软件描述:

        pycharm 2022.2 专业版 

        python3.10(pygame)

游戏效果预览:

                                                         注意以下代码只用来学习 借鉴 !自娱自乐ha !

图片素材请自取:  图片有水印 如果需要没有水印的请私聊我 ~

 

 

 

目录

环境安装:

代码:

 1、主文件: aircraft_battle.py 

2、设置文件:aircraft_battle_set.py

3、飞船 文件: aircraft_battle_ship.py

4、子弹文件: aircraft_bullet.py

5、外星飞船文件:Alien_spacecraft.py

6、游戏统计文件:game_stats.py

7、游戏按键文件:button.py

8、游戏计分文件:scoreboard.py


环境安装:

        安装pygame

        1、在pycharm打开终端(在右下角)输入一下命令安装

python3 -m pip install --user pygame

代码:

主运行文件:aircraft_battle.py 

设置文件:aircraft_battle_set.py

飞船 文件: aircraft_battle_ship.py

子弹文件: aircraft_bullet.py

外星飞船文件:Alien_spacecraft.py

游戏统计文件:game_stats.py

游戏按键文件:button.py

游戏计分文件:scoreboard.py

images图片存放位置  

注意:按目录格式放好 运行即可

目录结构:

 1、主文件: aircraft_battle.py 

# -*- coding: GBK -*-
import sys, pygame, time
from aircraft_battle_set import Settings
from aircraft_battle_ship import Ship
from aircraft_bullet import *
from Alien_spacecraft import *
from game_stats import *
from button import *
from scoreboard import *


class AircraftBattle:
    """管理游戏资源和行为的类"""

    def __init__(self):
        """初始化游戏资源"""
        pygame.init()  # 初始化背景设置
        self.settings = Settings()
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))  # 创建显示窗口 单位为px(像素)1200px宽 200px高
        pygame.display.set_caption("飞机大战")  # 窗口标题
        # 创建一个用于存储游戏统计信息的实例
        self.stats = GameStats(self)
        # 创建计分器
        self.sb = Scoreboard(self)

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()  # 编组 用于存储所有有效子弹
        self.aliens = pygame.sprite.Group()

        self._create_fleet()

        # 创建 Play 按钮
        self.play_button = Button(self, "Play")

        if not self.stats.game_active:
            self.play_button.draw_button()

    def Fullscreen(self):
        # 全屏运行全屏模式下不支持鼠标点击退出,只能输入Q退出
        # 全屏与小窗口来回切换会发生外星飞船位置错乱
        self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)  # 传入0,0参数以及FULLSCREEN:覆盖整个显示器
        self.settings.screen_width = self.screen.get_rect().width  # 由于无法估计屏幕大小所以使用width与height来更新设置
        self.settings.screen_height = self.screen.get_rect().height
        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()  # 编组 用于存储所有有效子弹
        self.aliens = pygame.sprite.Group()

        self._create_fleet()


        # 创建 Play 按钮
        self.play_button = Button(self, "Play")

    def _check_events(self):
        """响应按键与鼠标响应"""
        for event in pygame.event.get():  # 循环事件
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:  # 检测与按钮相关的鼠标事件
                mouse_pos = pygame.mouse.get_pos()  # pygame.mouse.get_pos() 将返回一个元组,其中包含x,y的坐标
                self._check_play_button(mouse_pos)  # 将返回的值传给_check_play_button方法

    def _check_play_button(self, mouse_pos):
        """在玩家单机Play按钮时开始新游戏"""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)

        # collidepoint 这个方法检测鼠标单击位置是否在play按钮的矩形内,如果是就设置为True 开始游戏
        if button_clicked and not self.stats.game_active:
            self.stats.game_active = True
            # 重置游戏统计信息
            self.settings.initialize_dynamic_settings()
            self.stats.reset_stats()  # 重置信息,并提供给玩家三架飞机
            # 方法代码执行完毕后,运行游戏

            # 清空剩余子弹以及外星飞船 # 游戏开始后清空编组
            self.aliens.empty()  # 清空外星飞船编组
            self.bullets.empty()  # 清空子弹编组

            # 创建一群新的外星飞船并让飞船居中
            self._create_fleet()
            self.ship.center_ship()

            # 游戏开始时,更新等级图像
            self.sb.prep_score()
            self.sb.prep_level()
            self.sb.prep_ships()

            # 隐藏光标
            pygame.mouse.set_visible(False)

    def _check_keydown_events(self, event):  # 响应按键
        if event.key == pygame.K_RIGHT:
            # 向右移动飞船
            self.ship.moving_right = True

            # 向左移动
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True

            # 向下移动
        elif event.key == pygame.K_DOWN:
            self.ship.moving_xia = True

            # 向上移动
        elif event.key == pygame.K_UP:
            self.ship.moving_shang = True
        # 空格发射子弹
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()
        # 如果用户摁倒Q 既退出
        elif event.key == pygame.K_q:
            sys.exit()
        # 按键 1 控制全屏  # 注意在操作的时候 飞机会恢复到初始位置
        elif event.key == pygame.K_1:
            self.Fullscreen()
        #  按键 2 控制窗口化  # 注意在操作的时候 飞机会恢复到初始位置
        # elif event.key == pygame.K_2:
        #     self.windows()

    def _check_keyup_events(self, event):
        # 松开按键以后改为FALSE 停止移动
        if event.key == pygame.K_RIGHT:  # 松开按键以后停止向右移动
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:  # 松开按键以后停止向左移动
            self.ship.moving_left = False
        # elif event.key == pygame.K_DOWN:  # 松开按键以后停止向下移动
        #     self.ship.moving_xia = False
        # elif event.key == pygame.K_UP:  # 松开按键以后停止向上移动
        #     self.ship.moving_shang = False

    def _fire_bullet(self):
        """创建一颗子弹,并将其加入到编组bullets中"""
        if len(self.bullets) < self.settings.bullet_allowed:  # 判断 bullets的长度,如果小于10 就创建一颗新子弹,但如果有未消失的三颗子弹,按下空格后不触发子弹
            new_bullet = Bullet(self)  # 定义子弹
            self.bullets.add(new_bullet)  # 将子弹 加入编组当中

    def _ship_hit(self):
        """响应飞船被撞击"""
        if self.stats.ship_left > 0:
            # 将 ships_left 减一 并更新记牌器
            self.stats.ship_left -= 1  # 飞船撞到外星飞船以后数量 - 1
            self.sb.prep_ships()
            # 清空余下的外星飞船和子弹 , 因为是编组的形式,所以直接清空编组
            self.aliens.empty()
            self.bullets.empty()

            # 创建一批新的外星飞船,并将飞船恢复到初始化位置
            self._create_fleet()
            self.ship.center_ship()

            # 暂停
            time.sleep(0.5)  # 暂停0.5 能让玩家看到被撞击
        else:
            self.stats.game_active = False
            pygame.mouse.set_visible(True)  # 鼠标光标

    def _update_bullets(self):
        """更新子弹位置并删除消失的子弹"""
        self.bullets.update()
        # 删除消失的子弹
        # 子弹 在到达屏幕顶端后消失,是因为pygame无法在屏幕外绘制,但出去的子弹依然存在,它们将继续消耗你内存和cpu,需要将屏幕外的子弹删除
        for bullet in self.bullets.copy():  # 因为不能从for循环遍历的列表中删除元素,所以必须遍历编组的副本,所以我们用copy俩循环
            if bullet.rect.bottom <= 0:  # 如果子弹从顶部消失,y的值就为负数或者0 ,就将其从列表中删除
                self.bullets.remove(bullet)

        # print(len(self.bullets)) # 查看屏幕内子弹存在的数量
        self._check_bullet_alien_collisions()

        # 检测外星飞船与 飞船之间的碰撞
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()  # 将方法加入到这个碰撞判断中
        # 检查是否有外星飞船达到了屏幕底端
        self._check_aliens_bottom()

    def _check_aliens_bottom(self):
        """检查外星飞船是否到达底部"""
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                # 像飞船被 碰撞一样 处理掉
                self._ship_hit()
                break

    def _check_bullet_alien_collisions(self):
        # 检查子弹是否击中外星飞船
        # 如果是,就删除对应的子弹和外星飞船
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)
        # sprite.groupcollide 将一个编组中每个元素的rect同另一个编组中的每个元素rect进行比较。
        if collisions:
            # 与外星飞船碰撞的子弹都是字典 collisions 中的一个键,每颗子弹相关的值都是一个列表,其中包含该子弹击中的外星人
            for aliens in collisions.values():  # 循环 字典 collisions 确保每个消灭的都进入得分
                self.stats.score += self.settings.alien_points * len(aliens)
                # 每个值都是一个列表,包含被同一颗子弹击中的所有外星飞船,对于每个列表,都将其包含的外星人数量乘以一个外星人的分数,并将分数加入当前得分
            self.sb.prep_score()

            self.sb.check_high_score()
        if not self.aliens:
            # 删除现有的子弹并新建外星飞船
            self.bullets.empty()
            self._create_fleet()  # 重新创建外星飞船群
            self.settings.increase_speed()

            # 提高等级  # 当消灭一群外星飞船的时候等级加一
            self.stats.level += 1
            self.sb.prep_level()

    def _update_screen(self):
        """更新屏幕上的图像,并切换到新屏幕"""
        # 每次循环时都重绘屏幕。

        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()

        for bullet in self.bullets.sprites():  # 方法 bullets.sprites 返回的是一个列表,遍历编组中的内容并对每部分内容调用draw_bullet,形成子弹样式
            bullet.draw_bullet()

        self.aliens.draw(self.screen)  # 外星飞船编组调用 draw方法

        # 显示得分
        self.sb.show_score()

        # 如果游戏处于非活动状态下,就绘制Play按钮
        if not self.stats.game_active:
            self.play_button.draw_button()

        pygame.display.flip()

    def _create_fleet(self):
        """创建外星人飞船群"""
        # 创建一个外星人飞船并计算一行可容纳多少个
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size  # 使用属性size,该属性为一个元组,包含rect对象的宽度与高度

        # 计算两边空白宽度 (屏幕两边留下一定的边距,将其设置为外星飞船的宽度,因有两个边距,所以用于存放外星飞船的水平空间 = 屏幕宽度 - 外星飞船宽度的两倍)
        available_space_x = self.settings.screen_width - (2 * alien_width)
        # 计算外星飞船之间的间距 (外星飞船所需要的间距为外星飞船的两倍,一个宽度存放外星飞船,另一个存放飞船间距)
        # 为确定一行可容纳多少飞船,将空间 除以 外星飞船宽度的两倍, 这里用的 “//" 为整除运算符
        number_aliens_x = available_space_x // (2 * alien_width)

        # 计算屏幕可容纳多少外星飞船
        ship_height = self.ship.rect.height
        # 计算可用垂直空间 = 屏幕高度 - 第一行外星飞船的上边距(外星飞船高度)、飞船高度以及飞船群最初与飞船之间的间距(外星人高度的两倍)
        available_space_y = (self.settings.screen_height - (3 * alien_height) - ship_height)
        # 每行下方留出一定的空白区域,计算可容纳行数,将可用的垂直空间 除以 外星飞船高度的两倍(行数只能是整数)
        number_rows = available_space_y // (2 * alien_height)

        # 创建外星飞船群
        for row_number in range(number_rows):  # 将上述计算出来的高度变为一个循环的数,用来创建多行外星飞船
            # 创建第一行外星人飞船
            for alien_number in range(number_aliens_x):  # 内部循环用来创建一行循环
                self._create_alien(alien_number, row_number)  # row_number 传递一个行号实参,将每行都沿屏幕依次向下放置

    def _create_alien(self, alien_number, row_number):
        # 创建一个外星人飞船并将其加入当前行
        alien = Alien(self)  # 创建 单个 外星飞船
        alien_width, alien_height = alien.rect.size
        # 通过 x 坐标 将其加入当前行,将每个 外星飞船往右推一个飞船宽度,在将外星飞船宽度乘以2,得到每个外星飞船占据的空间,包括飞船的间距
        alien.x = alien_width + 2 * alien_width * alien_number
        # 在据此计算当前外星飞船当前位置,使用 飞船的 x 属性来设置其位置
        alien.rect.x = alien.x

        # 修改 外星飞船的 y 坐标 并在第一行外星飞船上方流出与外星飞船等高的空白区域
        # 相邻外星飞船 行的y 坐标 相差 外星飞船的两倍,因此高度乘以2 在乘以行号,第一行为0 因此第一行不变
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)  # 最后将所有创建的外星飞船 加入到编组当中

    def _update_aliens(self):
        """更新外星飞船舰群中所有外星飞船的位置"""
        self._check_fleet_edges()
        self.aliens.update()

    def _check_fleet_edges(self):
        """外星飞船到达边缘采取措施"""
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        """将整群外星飞船向下移动,并改变方向"""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1  # 这里-1 是向左移动

    def run_game(self):
        """开始游戏的主循环"""
        while True:
            self._check_events()
            if self.stats.game_active:  # stats.game_active 为真的时候游戏继续,否则不运行游戏
                self.ship.update()
                self._update_bullets()
                self._update_screen()
            # 调用更新外星飞船位置的方法
            self._update_aliens()

            # 让最近绘制的屏幕可见
            pygame.display.flip()


if __name__ == "__main__":
    # 创建实例并运行游戏
    ai = AircraftBattle()
    ai.run_game()

2、设置文件:aircraft_battle_set.py

# -*- coding: GBK -*-
class Settings:
    """存储游戏中所有的设置类"""

    def __init__(self):
        """初始化游戏设置"""
        # 屏幕设置
        self.screen_width = 1200
        self.screen_height = 800
        # 设置背景颜色
        self.bg_color = (230, 230, 230)

        # 飞船移动速度设置  #每次移动 1.5个像素 px
        self.ship_speed = 1.5
        # 飞船设置
        self.ship_limit = 3  # 创建飞船数量

        # 子弹设置
        self.bullet_speed = 1.5  # 设置子弹速度
        self.bullet_width = 3  # 设置子弹像素宽为3
        self.bullet_height = 15   # 设置子弹像素高为 15
        self.bullet_color = (121, 176, 214)  # 设置子弹颜色
        self.bullet_allowed = 20  # 限制同屏子弹最大数量为 10

        # 外星飞船设置
        self.alien_speed = 1.0  # 飞船移动速度
        self.fleet_drop_speed = 10  # 飞船每次向下移动的像素
        # fleet_direction 为 1 表示向右移动 为 -1 表示向左移动
        self.fleet_direction = 1

        # 加快游戏节奏的速度
        self.speedup_scale = 1.1  # 控制游戏节奏的加快速度
        # 分数越高 便提升速度
        self.score_scale = 1.5  # 将分数提高速度设置为1.5

        self.initialize_dynamic_settings()  # 玩家每提高一级 游戏的节奏就翻倍

    def initialize_dynamic_settings(self):
        """初始化随游戏进行而变化设置"""
        self.ship_seed = 1.5
        self.bullet_speed = 3
        self.alien_speed = 1.0

        # fleet_direction 为1 表示向右移动 为 -1 向左移动
        self.fleet_direction = 1

        # 外星飞船击落计分
        self.alien_points = 50  # 随着游戏的进行 将提高分数,确保每次开启新游戏 都重置此分数 设定alien_plints

    def increase_speed(self):
        """提高速度设置和击中外星飞船分数"""
        self.ship_speed *= self.speedup_scale
        self.bullet_speed *= self.speedup_scale
        self.alien_speed *= self.speedup_scale
        self.alien_points = int(self.alien_points * self.score_scale)  # 游戏节奏加快的同时,提高每个外星飞船被击中的分数

3、飞船 文件: aircraft_battle_ship.py

# -*- coding: GBK -*-
import pygame
from pygame.sprite import Sprite


class Ship(Sprite):
    """管理飞船的类"""

    def __init__(self, ai_game):
        """初始化飞船并设置其初始化位置"""
        super().__init__()

        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.screen_rect = ai_game.screen.get_rect()  # 使用方法get_rect()访问屏幕的属性rect,并赋给.self.screen_rect,这样就能够将飞船放到屏幕中央

        # 加载飞船图像并获取外连接矩形
        self.image = pygame.image.load('images/ship.png')  # 加载图像
        self.rect = self.image.get_rect()  # 指定飞船位置,用get_rect获取屏幕属性没用来指定飞船位置

        # 对于每艘飞船,都将其放在屏幕底部的中央
        self.rect.midbottom = self.screen_rect.midbottom

        # 在飞船的属性x,y中存储小数值
        self.x = float(self.rect.x)
        self.y = float(self.rect.y)

        # 移动标志
        self.moving_right = False  # 向右移动
        self.moving_left = False  # 向左移动
        self.moving_shang = False  # 向上移动
        self.moving_xia = False  # 向下移动

    def update(self):
        """根据移动标志调整飞船的位置"""
        # 限制飞船活动范围
        if self.moving_right and self.rect.right < self.screen_rect.right:
            self.x += self.settings.ship_speed  # 向右移动
        if self.moving_left and self.rect.left > 0:
            self.x -= self.settings.ship_speed  # 向左移动

        # if self.moving_shang and self.rect.top > 0:
        #     self.y -= self.settings.ship_speed  # 向上移动
        # if self.moving_xia and self.rect.bottom < self.screen_rect.bottom:
        #     self.y += self.settings.ship_speed  # 向下移动

        # 根据self.x更新rect对象
        self.rect.x = self.x
        self.rect.y = self.y

    def blitme(self):
        """在指定位置绘画飞船"""
        self.screen.blit(self.image, self.rect)

    # 处理rect对象时,可以使用矩形四角和中心的x坐标和y坐标。可通过设置这些值来指定矩形位置。要让游戏元素居中,可以

    def center_ship(self):
        """让飞船在屏幕底端居中"""
        self.rect.midbottom = self.screen_rect.midbottom
        self.x = float(self.rect.x)

4、子弹文件: aircraft_bullet.py

# -*- coding: GBK -*-
import pygame
from pygame.sprite import Sprite


class Bullet(Sprite):
    """管理飞机所发射子弹的类"""

    def __init__(self, ai_game):
        """在飞机当前位置创建一个子弹对象"""
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.color = self.settings.bullet_color

        # 在(0,0)处创建一个表示子弹的矩形,在设置正确的位置
        self.rect = pygame.Rect(0, 0, self.settings.bullet_width,
                                self.settings.bullet_height)  # 创建子弹的属性rect,子弹并非基于图像,因此必须用pygame.Rect创建一个矩形
        self.rect.midtop = ai_game.ship.rect.midtop  # 将子弹的rect.midtop设置为飞船的rect.midtop


        # 存储用小数表示子弹位置
        self.y = float(self.rect.y)

    def update(self):
        """向上移动子弹"""
        # 更新 子弹位置的小数点
        self.y -= self.settings.bullet_speed  # 子弹发射后向上移动,意味着y坐标将不断减小,并更新子弹位置
        # 更新 子弹 的 rect 位置
        self.rect.y = self.y  # 更新子弹矩形的位置

    def draw_bullet(self):
        """在屏幕上绘制子弹"""
        pygame.draw.rect(self.screen, self.color, self.rect)  # draw.rect 函数使用存储在self.color中的颜色填充表示子弹的矩形占据的屏幕的部分

5、外星飞船文件:Alien_spacecraft.py

# -*- coding: GBK -*-
import pygame
from pygame.sprite import Sprite


class Alien(Sprite):
    """表示单个外星人的类"""

    def __init__(self, ai_game):
        """初始化外星人飞船位置"""
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings

        # 加载外星人图像冰着吃其 rect 属性
        self.image = pygame.image.load("images/alien.png")
        self.rect = self.image.get_rect()

        # 每个外星飞船最初都在屏幕左上角附近
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        # 存储外星人的精准水平位置
        self.x = float(self.rect.x)

    def check_edges(self):
        """
        检查外星飞船是否撞到了屏幕边缘
        如果外星飞船位于屏幕边缘就返回True
        """
        screen_rect = self.screen.get_rect()
        # 如果 rect 的属性 right大于屏幕的rect 的 right属性,就说明外星飞船位于右边缘,反之在左边
        if self.rect.right >= screen_rect.right or self.rect.left <= 0:
            return True

    def update(self):
        """向右移动外星飞船"""
        self.x += (self.settings.alien_speed * self.settings.fleet_direction)  # 使用属性 self.x 跟踪外星飞船的准确位置
        self.rect.x = self.x  # self.x 的值来更新 外星飞船的位置

6、游戏统计文件:game_stats.py

# -*- coding: GBK -*-

class GameStats:
    """跟踪游戏的统计信息"""

    def __init__(self, ai_game):
        """初始化信息统计表"""
        self.settings = ai_game.settings
        self.reset_stats()
        self.game_active = False  # 让游戏一开始处于非活动状态

        # # 游戏结束设置
        # # 游戏刚启动时设置为 True
        # self.game_active = True

        # 最高分初始化值
        self.high_score = 0

    def reset_stats(self):
        """初始化在游戏运行期间可能变化的统计信息"""
        self.ship_left = self.settings.ship_limit
        self.score = 0  # 初始化分数
        # 玩家等级
        self.level = 1  # 初始玩家等级

7、游戏按键文件:button.py

# -*- coding: GBK -*-
import pygame.font


class Button:

    def __init__(self, ai_game, msg):
        """
        初始化按钮的属性
        msg 按钮中显示文本
        """
        self.screen = ai_game.screen
        self.screen_rect = self.screen.get_rect()

        # 设置按钮的尺寸和其他属性
        self.width, self.height = 200, 50  # 设置按钮尺寸
        self.button_color = (0, 255, 0)  # 按钮背景颜色
        self.text_color = (255, 255, 255)  # 按钮文本颜色
        self.font = pygame.font.SysFont(None, 48)  # pygame.font 函数可以将文本渲染到屏幕上,SysFont 指定字体
        # None 表示使用默认字体 , 48 表示文本的字号

        # 创建按钮的rect对象,并使其居中
        self.rect = pygame.Rect(0, 0, self.width, self.height)  # 居中
        self.rect.center = self.screen_rect.center

        # 按钮的标签只需创建一次
        self._prep_msg(msg)  # 调用函数进行渲染
        # pygame处理文本的方式就是将要显示的字符串渲染为图像

    def _prep_msg(self, msg):  # 接受实参self 以及要渲染为图像的文本msg
        """将msg渲染为图像,并使其在按钮上居中"""
        # font.renderc 函数: 将存储在msg中的文本转为图,在括号内的参数中布尔值(True)作用就是指定开启还是关闭反锯齿功能
        # text_color 文本颜色
        # button_color 背景色
        self.msg_image = self.font.render(msg, True, self.text_color, self.button_color)

        self.msg_image_rect = self.msg_image.get_rect()  # 根据文本图像创建一个矩形,并将其中心点 设置为中心点
        self.msg_image_rect.center = self.rect.center  # 让文本上居中

    def draw_button(self):
        # 绘制一个用颜色填充的按钮,在绘制文本
        self.screen.fill(self.button_color, self.rect)  # 使用 screen.fill绘制按钮的矩形
        self.screen.blit(self.msg_image, self.msg_image_rect)  # 在使用 screen.blit 在调用函数并向它传递一副图像以及与该图相关联的rect

8、游戏计分文件:scoreboard.py

# -*- coding: GBK -*-
import pygame.font
from pygame.sprite import Group
from aircraft_battle_ship import Ship


class Scoreboard:
    """显示得分信息的类"""

    def __init__(self, ai_game):
        """初始化显示得分涉及的属性"""
        self.screen = ai_game.screen
        self.ai_game = ai_game
        self.screen_rect = self.screen.get_rect()
        self.settings = ai_game.settings
        self.stats = ai_game.stats

        # 显示得分信息时使用的字体设置
        self.text_color = (30, 30, 30)  # 设置文本颜色
        self.font = pygame.font.SysFont(None, 48)  # 设置字体,以及字体大小
        # 准备初始得分图像
        self.prep_score()
        self.prep_heigh_score()
        self.prep_level()
        self.prep_ships()

    def prep_score(self):
        """将得分转换为渲染图"""
        rounded_score = round(self.stats.score, - 1)
        # round 函数 让小数精确到小数点后的某一位,其中小数点位数是由第二个实参指定,然而为负数,round将舍入到最近的10倍,如10,100,1000等

        score_str = "{:,}".format(rounded_score)
        # score_str = str(self.stats.score)  # 将数值转换为字符串
        self.score_image = self.font.render(score_str, True, self.text_color, self.settings.bg_color)

        # 在屏幕右上角显示得分
        # 将得分放置屏幕又上角,并在得分增大导致数变宽时让其向右延伸
        self.score_rect = self.score_image.get_rect()  # 确保得分始终锚定在屏幕右边,定义一个score_rect
        self.score_rect.right = self.screen_rect.right - 20  # 屏幕右边缘相距20 px
        self.score_rect.top = 20  # 让其边缘与屏幕边缘也相距20px

    def show_score(self):
        """在屏幕上显示得分、等级和剩余飞船"""
        self.screen.blit(self.score_image, self.score_rect)  # 得分
        self.screen.blit(self.high_score_image, self.high_score_rect)  # 最高分
        self.screen.blit(self.level_image, self.level_rect)  # 等级
        self.ships.draw(self.screen)  # 剩余飞船

    def prep_heigh_score(self):
        """将最高得分转换为渲染的图像"""
        high_score = round(self.stats.high_score, -1)
        high_score_str = "{:,}".format(high_score)
        self.high_score_image = self.font.render(high_score_str, True, self.text_color, self.settings.bg_color)

        # 将最高得分放在屏幕顶部中央
        self.high_score_rect = self.high_score_image.get_rect()
        self.high_score_rect.centerx = self.screen_rect.centerx
        self.high_score_rect.top = self.score_rect.top

    def check_high_score(self):
        """检查是否诞生了新的最高分"""
        if self.stats.score > self.stats.high_score:  # 如果得的分数大于 最高分则替换最高分的值
            self.stats.high_score = self.stats.score
            self.prep_heigh_score()

    def prep_level(self):
        """将等级转为渲染图片"""
        level_str = str(self.stats.level)
        self.level_image = self.font.render(level_str, True, self.text_color, self.settings.bg_color)

        # 将等级放在得分下
        self.level_rect = self.level_image.get_rect()
        self.level_rect.right = self.score_rect.right
        self.level_rect.top = self.score_rect.bottom + 10  # 与上面图像的属性大于10 px 以便得分和等级之间留出一定缝隙

    def prep_ships(self):
        """显示剩余飞船"""
        self.ships = Group()  # 创建一个空编组
        for ship_number in range(self.stats.ship_left):  # 根据玩家剩余飞船运行一个循环
            ship = Ship(self.ai_game)  # 设定一个需要添加编组的值
            ship.rect.x = 10 + ship_number * ship.rect.width  # 将飞船放置屏幕左上角,并设置每艘飞船左边距为 10 px
            ship.rect.y = 10  # 在设置飞船距离 y 坐标距离屏幕上方10px
            self.ships.add(ship)  # 设定好后 加入编组

猜你喜欢

转载自blog.csdn.net/weixin_58279299/article/details/125658009