Python3 armed spaceship game actual combat code and detailed notes

project description:

        Make a 2D game Airplane Wars where the player controls a spaceship that initially appears at the bottom center of the screen. Players can use the arrows to move the spaceship left and right, space to shoot. At the beginning of the game, a group of unknown creatures fly in the sky and move like the bottom of the screen. Players need to kill these unknown creatures. With the number of kills, the moving speed of unknown creatures is faster. As long as there are creatures hitting the player or reaching the bottom, The player loses one spaceship, and after losing three of your spaceships, the game ends. 

Software description:

        pycharm 2022.2 Professional Edition 

        python3.10 (pygame)

Game effect preview:

                                                         Note that the following code is only for learning and reference! Entertain yourself ha!

Please take the picture material by yourself: If the picture has a watermark, if you need it without a watermark, please chat with me privately~

 

 

 

Table of contents

Environment installation:

code:

 1. Main file: aircraft_battle.py 

2. Setting file: aircraft_battle_set.py

3. Spaceship file: aircraft_battle_ship.py

4. Bullet file: aircraft_bullet.py

5. Alien spacecraft file: Alien_spacecraft.py

6. Game statistics file: game_stats.py

7. Game button file: button.py

8. Game scoring file: scoreboard.py


Environment installation:

        installpygame

        1. Open the terminal in pycharm (in the lower right corner) and enter the command to install

python3 -m pip install --user pygame

code:

Main running file: aircraft_battle.py 

Setup file: aircraft_battle_set.py

Ship file: aircraft_battle_ship.py

Bullet file:  aircraft_bullet.py

Alien Spacecraft File: Alien_spacecraft.py

Game statistics file: game_stats.py

Game button file: button.py

Game scoring file: scoreboard.py

images image storage location  

Note: Just put it in the directory format and run it

Directory Structure:

 1. Main file:  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. Setting file: 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. Spaceship file: 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. Bullet file:  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 file: 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 statistics file: 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. Game button file: 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. Game scoring file: 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)  # 设定好后 加入编组

Guess you like

Origin blog.csdn.net/weixin_58279299/article/details/125658009