Python14_项目一 :外星人入侵游戏05 06(增加play按钮,增加记分牌,并且使外星人移动等级提升)

这两天的真的很忙。。

就一直没有更新博客。今天抽时间,整理一下项目一所剩余的部分。

对于项目一,确实有些杂,但是我们只要理清其中的思路即可。毕竟第一次的项目,往后要不断回顾才是。

这样吧,我附上整个项目的代码。有什么不懂的地方可以留言问我。

alien_invasion.py代码

# 02 import sys
import pygame
from settings import Setting  # 01
from ship import Ship  # 01
import game_function as gf  # 02
from pygame.sprite import Group  # 03 pygame.sprite.Group 类类似于列表,但提供了有助于开发游戏的额外功能
# from aliens import Alien           # 04
from game_stats import GameStats  # 04
from button import Button  # 05
from scoreboard import Scoreboard  # 05


def run_game():  # 初始化游戏,并且创建一个屏幕对象
    pygame.init()  # 初始化背景设置,让Pygame能够正确地工作
    # 01 screen = pygame.display.set_mode((1200, 800))     # 创建一个名为screen 的显示窗口,括号里是元组!!!
    # 01                                                   # 这个游戏的所有图形元素都将在其中绘制
    ai_set = Setting()  # 因为导入类而做了代码替换
    screen = pygame.display.set_mode(
        (ai_set.screen_width, ai_set.screen_height)
    )
    # 01 bg_color = (230,230,230)         # 设置背景颜色

    pygame.display.set_caption('外星人入侵')
    # 创建一个play按钮
    play_button = Button(ai_set, screen, 'Play')
    # 创建一个用于存储游戏统计信息的实例 并【创建记分牌】
    stats = GameStats(ai_set)
    sb = Scoreboard(ai_set, screen, stats)

    # 创建一艘飞船对象
    ship = Ship(ai_set, screen)
    # 03 导入Group类并且创建一个Group实例,用于存储子弹的编组
    bullets = Group()
    # 04 创建一个外星人,编组
    # alien = Alien(ai_set,screen)
    aliens = Group()
    # 04 创建外星人群
    gf.create_fleet(ai_set, screen, ship, aliens)

    # 为让程序响应事件,我们编写一个事件循环,以侦听事件,并根据发生的事件执行相应的任务。
    while True:  # 游戏的主循环
        # 02 for event in pygame.event.get():    # 监视键盘和鼠标
        # 02     if event.type == pygame.QUIT:   #编写一系列的if 语句来检测并响应特定的事件
        # 02         sys.exit()                  # 我们调用sys.exit() 来退出游戏
        gf.check_event(ai_set, screen, stats, sb, play_button, ship, aliens, bullets)  # 02 03 05 06
        if stats.game_active:
            ship.update()  # 02

            gf.update_bullet(ai_set, screen, stats, sb, ship, aliens, bullets)  # 03 04 05
            gf.update_aliens(ai_set, screen, stats, sb, ship, aliens, bullets)  # 04 06
            # 03 bullets.update()          # 03
            # # 03 删除已经消失,看不到的子弹
            # for bull in bullets.copy():
            #     if bull.rect.bottom <= 0:
            #         bullets.remove(bull)
            # print(len(bullets))

            # 01screen.fill(bg_color)                # 每次循环都重绘屏幕
            # 02 screen.fill(ai_set.bg_color)
            # 02 ship.blitme()                       # 调用blitme函数,使飞船出现
            # 02 pygame.display.flip()               # 让最近绘制的屏幕可见

        gf.update_screen(ai_set, screen, stats, sb, ship, aliens, bullets, play_button)  # 02 03 04 05


run_game()
input()

game_function.py代码

import sys
import pygame
from settings import Setting
from bullet import Bullet  # 03
from aliens import Alien  # 04
from time import sleep  # 04
from game_stats import GameStats  # 05


# 响应按键 03
def check_keydown(event, ai_settings, screen, ship, bullets):
    if event.key == pygame.K_RIGHT:
        # 向右移动飞船
        ship.moving_right = True
        # ship.rect.centerx += 10

    elif event.key == pygame.K_LEFT:
        # 向左移动飞船
        # ship.rect.centerx -= 10
        ship.moving_left = True

    # 03 创建一颗子弹,并将其加入到编组bullets中
    elif event.key == pygame.K_SPACE:
        if len(bullets) < ai_settings.bullet_allowed:  # 限制三个子弹
            # 玩家按空格键时,创建一颗新子弹(一个名为new_bullet 的Bullet 实例),
            new_bullet = Bullet(ai_settings, screen, ship)
            # 并使用方法add() 将其加入到编组bullets中
            bullets.add(new_bullet)

    # 04 按q结束
    elif event.key == pygame.K_q:
        sys.exit()


# 响应松开 03
def check_keyup(event, ship):
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False


# 响应按键和鼠标事件
def check_event(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets):  # 03

    for i in pygame.event.get():
        if i.type == pygame.QUIT:
            sys.exit()

        elif i.type == pygame.KEYDOWN:
            check_keydown(i, ai_setting, screen, ship, bullets)  # 重构
        # 03   if i.key == pygame.K_RIGHT:
        # 03        # 向右移动飞船
        # 03        ship.moving_right = True
        # 03        # ship.rect.centerx += 10
        # 03    elif i.key == pygame.K_LEFT:
        # 03        # 向左移动飞船
        # 03        # ship.rect.centerx -= 10
        # 03        ship.moving_left = True

        elif i.type == pygame.KEYUP:
            check_keyup(i, ship)  # 重构
            # 03 if i.key == pygame.K_RIGHT:
            # 03    ship.moving_right = False
            # 03 elif i.key == pygame.K_LEFT:
            # 03    ship.moving_left = False

        # 05 鼠标点击事件
        elif i.type == pygame.MOUSEBUTTONDOWN:
            # 无论玩家单击屏幕的什么地方,Pygame都将检测到一个MOUSEBUTTONDOWN 事件
            # 但我们只想让这个游戏在玩家用鼠标单击Play按钮时作出响应
            # 为此,我们使用了pygame.mouse.get_pos() ,它返回一个元组,其中包含玩家单击时鼠标的x 和y 坐标
            mouse_x, mouse_y = pygame.mouse.get_pos()
            # 我们将这些值传递给函数check_play_button()
            # 而这个函数使用collidepoint() 检查鼠标单击位置是否在Play按钮的rect 内
            check_play_button(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y)


# 05 在玩家单击play按钮时开始新的游戏
def check_play_button(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y):
    # 仅当玩家单击了Play按钮且 游戏当前处于非活动状态时,游戏才重新开始
    # collidepoint() 检查鼠标单击位置是否在Play按钮的rect 内
    button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)

    if button_clicked and not stats.game_active:  # 控制仅仅在按钮区域,且 游戏停止状态 才会重置

        # 重置游戏的设置,如初始速度等
        ai_setting.initialize_dynamic_settings()

        # 隐藏光标,直到游戏重开时出现,修改visible状态的代码写到ship_hit()中
        pygame.mouse.set_visible(False)
        # 重置游戏统计信息
        stats.reset_stats()
        stats.game_active = True

        # 06 为确保开始新游戏时更新记分和等级图像,在按钮Play被单击时触发重置
        sb.prep_score()
        sb.prep_high_score()
        sb.prep_level()
        # 06 我们在开始新游戏时调用prep_ships()
        sb.prep_ship()

        # 清空外星人列表和子弹列表
        aliens.empty()
        bullets.empty()

        # 创建一群新的外星人,并让飞船居中
        create_fleet(ai_setting, screen, ship, aliens)
        ship.center_ship()  # ship.py中的函数


# -------------------------------------更新屏幕-------------------------------------
# 更新屏幕上的图像,并切换到新屏幕
def update_screen(ai_setting, screen, stats, sb, ship, aliens, bullets, play_button):
    # 每次循环时都重绘屏幕
    screen.fill(ai_setting.bg_color)
    # 03 在飞船和外星人后面重绘所有子弹
    # 为在屏幕上绘制发射的所有子弹,我们遍历编组bullets 中的精灵,并对每个精灵都调用draw_bullet()
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    # 04 alien.blitme()
    aliens.draw(screen)  # 04 绘制外星人,使用的是内置draw函数

    # 06 显示得分
    sb.show_score()

    # 05 如果处于非游戏状态,就绘制play按钮
    if not stats.game_active:
        play_button.draw_button()  # 此函数在button.py文件
    # 让最近绘制的屏幕可见
    pygame.display.flip()


# -------------------------------------以下是子弹----------------------------------------------

# 03 更新子弹位置,并删除已经消失的子弹
def update_bullet(ai_setting, screen, stats, sb, ship, aliens, bullets):  # 05
    bullets.update()  # 更新子弹位置

    # 03 删除已经消失,看不到的子弹
    for bull in bullets.copy():
        if bull.rect.bottom <= 0:
            bullets.remove(bull)
    print(len(bullets))
    # ----- 04 检查是否碰撞-------
    check_bullet_alien_collision(ai_setting, screen, stats, sb, ship, aliens, bullets)  # 05


# 检查子弹和外星人是否碰撞
def check_bullet_alien_collision(ai_setting, screen, stats, sb, ship, aliens, bullets):
    # 方法sprite.groupcollide() 将每颗子弹的rect 同每个外星人的rect 进行比较,并返回一个字典,
    # 其中包含发生了碰撞的子弹和外星人。在这个字典中,每个键都是一颗子弹,而相应的值都是被击中的外星人
    # 检查是否有子弹击中了外星人
    # 如果是这样,就删除相应的子弹和外星人
    collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

    # 05 若碰撞则加分
    if collisions:
        # 如果字典collisions 存在,我们就遍历其中的所有值。
        # 别忘了,每个值都是一个列表,包含被同一颗子弹击中的所有外星人。
        # 对于每个列表,都将一个外星人的点数乘以其中包含的外星人数量,并将结果加入到当前得分中
        for alie in collisions.values():
            # 有子弹撞到时,Pygame返回一个字典(collisions )。
            # 我们检查这个字典是否存在,如果存在,就将得分加上一个外星人值的点数
            stats.score += ai_setting.alien_point * len(alie)
            sb.prep_score()  # 此函数在scoreboard.py文件中
        check_high_score(stats, sb)  # 此函数在本页最后

    # 如果外星人编组为空,则删除现有子弹并新建一群外星人
    # 06 如果整群外星人都被消灭,就提高一个等级
    if len(aliens) == 0:
        bullets.empty()
        ai_setting.increase_speed()  # 增加游戏节奏

        # 06 提高等级
        stats.level += 1
        sb.prep_level()

        create_fleet(ai_setting, screen, ship, aliens)
        # ai_setting.fleet_drop_speed += 20           # 自己加的----------------------------------------------------


# -------------------------------------以下是外星人 04 --------------------------------------------
# 04 创建外星人群
def create_fleet(ai_setting, screen, ship, aliens):
    # 创建一个外星人,并计算一行可容纳多少个外星人
    # 外星人间距为外星人宽度

    # 我们先创建一个外星人,这个外星人不是外星人群的成员,因此没有将它加入到编组aliens 中
    ali = Alien(ai_setting, screen)
    number_alien_x = get_number_aliens_x(ai_setting, ali.rect.width)  # 04 重构create_fleet
    number_rows = get_number_row(ai_setting, ship.rect.height, ali.rect.height)
    # 04 # 我们从外星人的rect 属性中获取外星人宽度,并将这个值存储到alien_width 中,以免反复访问属性rect
    # 04 ali_width = ali.rect.width
    # 04 # 我们计算可用于放置外星人的水平空间,以及其中可容纳多少个外星人。
    # 04 available_space_x = ai_setting.screen_width - 2 * ali_width
    # 04 number_alien_x = int(available_space_x / (2 * ali_width))

    # 创建第一行外星人
    for row_num in range(number_rows):
        for ali_num in range(number_alien_x):
            #  创建一个外星人,并加入当前行
            # alien = Alien(ai_setting,screen)            # 通过设置x 坐标将其加入当前行
            # alien.x = ali_width + 2 * ali_width * ali_num
            # alien.rect.x = alien.x
            # aliens.add(alien)
            create_alien(ai_setting, screen, aliens, ali_num, row_num)  # 04 重构create_fleet


# 计算每行可容纳多少个外星人
def get_number_aliens_x(ai_setting, alien_width):
    available_space_x = ai_setting.screen_width - 2 * alien_width
    number_alien_x = int(available_space_x / (2 * alien_width))
    return number_alien_x


# 计算屏幕可容纳多少行外星人
def get_number_row(ai_setting, ship_height, alien_height):
    available_space_y = (ai_setting.screen_height - (3 * alien_height) - 3.5 * ship_height)
    number_rows = int(available_space_y / (2 * alien_height))
    return number_rows


# 创建一个外星人并将其放在当前行
def create_alien(ai_setting, screen, aliens, alien_number, row_number):
    alien = Alien(ai_setting, screen)  # 通过设置x 坐标将其加入当前行
    alien_width = alien.rect.width
    alien.x = alien_width + 2 * alien_width * alien_number
    alien.rect.x = alien.x
    alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number  # 创建时,计算y的坐标
    aliens.add(alien)


# 更新外星人群中所有外星人位置
def update_aliens(ai_set, screen, stats, sb, ship, alie, bullets):
    # 检查是否有外星人到达屏幕边,然后更新所有外星人的位置
    check_fleet_edges(ai_set, alie)
    alie.update()
    # 04 检测外星人和飞船之间的碰撞
    # 方法spritecollideany() 接受两个实参:一个精灵和一个编组。
    # 它检查编组是否有成员与精灵发生了碰撞,并在找到与精灵发生了碰撞的成员后就停止遍历编组。
    if pygame.sprite.spritecollideany(ship, alie):
        ship_hit(ai_set, screen, stats, sb, ship, alie, bullets)

    # 检测是否有外星人到达屏幕底部
    check_aliens_bottom(ai_set, screen, stats, sb, ship, alie, bullets)


# 检测是否有外星人到达的屏幕底端
def check_aliens_bottom(ai_setting, screen, stats, sb, ship, aliens, bullets):
    screen_rect = screen.get_rect()
    for ali in aliens.sprites():
        if ali.rect.bottom >= screen_rect.bottom:
            # 像飞船撞到外星人一样处理
            ship_hit(ai_setting, screen, stats, sb, ship, aliens, bullets)
            break


# 响应被外星人撞到的飞船
def ship_hit(ai_setting, screen, stats, sb, ship, aliens, bullets):
    if stats.ships_left > 0:
        # 将ships_left减一
        stats.ships_left -= 1

        # 我们还在飞船被外星人撞到时调用prep_ships() ,从而在玩家损失一艘飞船时更新飞船图像:
        sb.prep_ship()

        # 清空外星人和子弹列表
        aliens.empty()
        bullets.empty()
        # 重新创建一群新的外星人,并将飞船放到屏幕底部
        create_fleet(ai_setting, screen, ship, aliens)
        ship.center_ship()  # ship.py中的函数
        # 暂停0.5秒
        sleep(0.5)
    else:
        stats.game_active = False
        # 使光标出现
        pygame.mouse.set_visible(True)


# 有外星人到达边缘时,采取相应的措施
def check_fleet_edges(ai_setting, aliens):
    for ali in aliens.sprites():  # 我们遍历外星人群,并对其中的每个外星人调用check_edge()
        if ali.check_edge():  # aliens.py中有此函数
            change_fleet_direction(ai_setting, aliens)
            break


# 将整群外星人下移,并改变它们的方向
def change_fleet_direction(ai_set, aliens):
    for ali in aliens.sprites():
        ali.rect.y += ai_set.fleet_drop_speed
    ai_set.fleet_direction *= -1


# ---------------------------------------以下是检测是否诞生最高分----------------------------------------
def check_high_score(stats, sb):
    if stats.score > stats.high_score:
        stats.high_score = stats.score
        sb.prep_high_score()

 ship.py代码

import pygame
from pygame.sprite import Sprite  # 06


class Ship(Sprite):
    def __init__(self, ai_setting, screen):  # 初始化飞船,并设置初始位置
        super().__init__()  # 06 继承初始化
        self.screen = screen
        self.ai_setting = ai_setting  # 02
        # 加载飞船图像并获取其外接矩形
        self.image = pygame.image.load('.\\feii.bmp')
        self.rect = self.image.get_rect()  # 我们使用get_rect() 获取相应surface的属性rect
        self.screen_rect = self.screen.get_rect()

        # 将每艘新飞船放在屏幕底部中央
        # 要将游戏元素居中,可设置相应rect 对象的属性center 、centerx 或centery 。
        self.rect.centerx = self.screen_rect.centerx
        # 要让游戏元素与屏幕边缘对齐,可使用属性top 、bottom 、left 或right ;
        # 要调整游戏元素的水平或垂直位置,可使用属性x 和y ,它们分别是相应矩形左上角的 x 和 y 坐标。
        self.rect.bottom = self.screen_rect.bottom
        # 在飞船的属性center中存储小数数值
        self.center = float(self.rect.centerx)  # 小数形式的位移可以更好的控制飞船移动

        # 移动标志,# 02
        # 飞船不动时,标志moving_right将为False 。
        # 玩家按下右箭头键时,我们将这个标志设置为True ;而玩家松开时,我们将这个标志重新设置为False
        self.moving_right = False
        self.moving_left = False
        self.moving_up = False
        self.moving_down = False

    # 根据移动标志,移动飞船 # 02
    def update(self):
        if self.moving_right and self.rect.right < self.screen_rect.right:  # 控制飞船移动的左右范围
            # 02 self.rect.centerx += 1
            # 02 更新飞船的center值,而不是rect
            self.center += self.ai_setting.ship_speed_factor
        if self.moving_left and self.rect.left > 0:
            # 02 self.rect.centerx -= 1
            self.center -= self.ai_setting.ship_speed_factor

        # 根据self.center更新rect对象
        self.rect.centerx = self.center

    # 我们定义了方法blitme() ,它根据self.rect 指定的位置将图像绘制到屏幕上
    # 在指定位置绘制飞船
    def blitme(self):
        self.screen.blit(self.image, self.rect)  # 把image这个surface对象贴到rect的位置

    # 让飞船在屏幕上居中
    def center_ship(self):
        self.center = self.screen_rect.centerx

aliens.py代码

import pygame
from pygame.sprite import Sprite


# 表示单个外星人的类
class Alien(Sprite):
    # 初始化外星人并设置其起始位置
    def __init__(self, ai_setting, screen):
        super().__init__()
        self.screen = screen
        self.ai_setting = ai_setting

        # 加载外星人图形,并设置其rect属性
        self.image = pygame.image.load(r'.\\alien-1.bmp')
        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 blitme(self):
        self.screen.blit(self.image, self.rect)

    # 如果外星人处于屏幕边缘,就返回True,此函数会在game_function中用到
    # 如果外星人处于屏幕边缘,就返回True,此函数会在game_function中用到
    def check_edge(self):
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right:
            return True
        elif self.rect.left <= screen_rect.left:
            return True

    # 向左或向右移动外星人
    def update(self, *args):
        self.x += self.ai_setting.alien_speed_factor * self.ai_setting.fleet_direction
        self.rect.x = self.x

 bullet.py代码

import pygame
from pygame.sprite import Sprite  # 导入精灵


# 一个对飞船发射的子弹进行管理的类
class Bullet(Sprite):
    def __init__(self, ai_setting, screen, ship):
        # 在飞船所处的位置创建一个子弹对象
        super().__init__()  # 初始化父类 2.7写法super(Bullet,self).__init__()
        self.screen = screen

        # 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
        # 我们创建了子弹的属性rect 。子弹并非基于图像的,因此我们必须使用pygame.Rect()类从空白开始创建一个矩形
        # 我们在(0, 0)处创建这个矩形,但接下来的两行代码将其移到了正确的位置
        # self.rect = pygame.Rect(0,0,ai_setting.bullet_width,ai_setting.bullet_height)-------原版,下两行DIY-------
        self.image = pygame.image.load('.\\Heart7.bmp')
        self.rect = self.image.get_rect()
        # 我们将子弹的centerx设置为飞船的rect.centerx 。
        # 子弹应从飞船顶部射出,因此我们将表示子弹的rect的top属性设置为飞船的rect的top属性,
        # 让子弹看起来像是从飞船中射出的
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top

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

        self.color = ai_setting.bullet_color
        self.speed = ai_setting.bullet_speed_factor

    # 向上移动子弹
    def update(self, *args):
        # 更新表示子弹位置的小数值
        self.y -= self.speed / 2
        # 更新表示子弹位置的rect的位置
        self.rect.y = self.y

    # 在屏幕上绘制子弹
    def draw_bullet(self):
        # 函数draw.rect()使用存储在self.color中的颜色填充表示子弹的rect占据的屏幕部分
        # pygame.draw.rect(self.screen,self.color,self.rect)-----------------------原版,下一行DIY-------------------
        self.screen.blit(self.image, self.rect)

 button.py代码

import pygame.sysfont


class Button():
    # 初始化按钮属性
    def __init__(self, ai_setting, screen, msg):
        self.screen = screen
        self.screen_rect = screen.get_rect()

        # 设置按钮的尺寸和其他属性
        self.width, self.height = 200, 50
        self.button_color = (0, 255, 0)
        self.text_color = (255, 255, 255)
        self.font = pygame.sysfont.SysFont('arial', 48)

        # 创建按钮的rect对象,并使其居中
        # 为让按钮在屏幕上居中,我们创建一个表示按钮的rect 对象
        # 并将其center 属性设置为屏幕的center 属性
        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.center = self.screen_rect.center

        # 按钮的标签只需创建一次
        # Pygame通过将你要显示的字符串渲染为图像来处理文本。我们调用prep_msg() 来处理这样的渲染
        self.prep_msg(msg)

    # 将msg渲染为图像,并使其在按钮上居中
    def prep_msg(self, msg):
        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

    # 最后,我们创建方法draw_button() ,通过调用它可将这个按钮显示到屏幕上
    def draw_button(self):
        # 绘制一个用颜色填充的按钮,再绘制文本
        self.screen.fill(self.button_color, self.rect)
        self.screen.blit(self.msg_image, self.msg_image_rect)

game_stats.py代码

# 跟踪游戏的统计信息
class GameStats():
    # 初始化统计信息
    def __init__(self, ai_setting):
        self.ai_setting = ai_setting
        self.reset_stats()
        # # 游戏刚开始时处于活动状态
        # self.game_active = True
        # 游戏刚开始时处于停止状态,直到play按钮按下
        self.game_active = False  # 05

        # 在任何情况下都不重置最高分
        self.high_score = 0

    # 初始化在游戏运行期间可能变化的统计信息
    def reset_stats(self):
        self.ships_left = self.ai_setting.ship_limit
        self.score = 0  # 05 记分,在每次游戏开始时,重置记分
        self.level = 1  # 06 等级

scoreboard.py代码

import pygame.sysfont
from pygame.sprite import Group  # 06
from ship import Ship  # 06


# 显示得分信息的类
class Scoreboard():

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

        # 显示得分信息时使用的字体设置
        self.text_color = (30, 30, 30)
        self.font = pygame.sysfont.SysFont('arial', 48)

        # 准备初始得分图像
        self.prep_score()  # 为将要显示的文本转换为图像
        # 准备最高分的图像
        self.prep_high_score()
        # 06 准备显示等级的图像
        self.prep_level()
        # 06 准备显示剩余飞船的图像
        self.prep_ship()

    # 将得分转换为一副渲染的图像
    def prep_score(self):
        round_score = round(self.stats.score)
        score_str = '{:,}'.format(round_score)
        self.score_image = self.font.render(score_str, True, self.text_color, self.ai_setting.bg_color)

        # 将得分放到屏幕右上角
        self.score_rect = self.score_image.get_rect()
        self.score_rect.right = self.screen_rect.right - 20
        self.score_rect.top = 20  # 让其上边缘与屏幕上边缘也相距20像素

    # 将最高分渲染为图像
    def prep_high_score(self):
        high_score = round(self.stats.high_score)
        high_score_str = '{:,}'.format(high_score)
        self.high_score_image = self.font.render(high_score_str, True, self.text_color, self.ai_setting.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.screen_rect.top

    # 06 等级渲染为图像
    def prep_level(self):
        self.leve_image = self.font.render(str(self.stats.level), True, self.text_color, self.ai_setting.bg_color)

        # 将等级放在得分下方
        self.level_rect = self.leve_image.get_rect()
        self.level_rect.right = self.screen_rect.right - 20
        self.level_rect.top = self.score_rect.bottom + 10

    # 06 显示剩余多少飞船
    def prep_ship(self):
        # 方法prep_ships() 创建一个空编组self.ships ,用于存储飞船实例
        self.ships = Group()
        # 为填充这个编组,根据玩家还有多少艘飞船运行一个循环相应的次数
        for ship_num in range(self.stats.ships_left):
            # 在这个循环中,我们创建一艘新飞船,并设置其x 坐标,
            # 让整个飞船编组都位于屏幕左边,且每艘飞船的左边距都为10像素
            # 我们还将y 坐标设置为离屏幕上边缘10像素,让所有飞船都与得分图像对齐
            ship = Ship(self.ai_setting, self.screen)
            ship.rect.x = 10 + ship_num * ship.rect.width
            ship.rect.y = 10
            # 最后,我们将每艘新飞船都添加到编组ships 中
            self.ships.add(ship)

    # 在屏幕上显示得分
    def show_score(self):
        # 这个方法将得分图像显示到屏幕上,并将其放在score_rect 指定的位置
        self.screen.blit(self.score_image, self.score_rect)
        self.screen.blit(self.high_score_image, self.high_score_rect)
        self.screen.blit(self.leve_image, self.level_rect)  # 06

        # 为在屏幕上显示飞船,我们对编组调用了draw() 。Pygame将绘制每艘飞船。
        self.ships.draw(self.screen)

settings.py代码

class Setting():  # 存储《外星人入侵》中所有的设置类
    def __init__(self):  # 初始化游戏设置
        self.screen_width = 1200  # 屏幕设置
        self.screen_height = 800
        self.bg_color = (230, 230, 230)

        # self.ship_speed_factor = 2.5    # 02 设置飞船速度

        # 03 子弹设置
        # 05 self.bullet_speed_factor = 3    # 子弹速度
        self.bullet_width = 500  # 子弹宽度
        self.bullet_height = 3  # 子弹长度
        self.bullet_color = 60, 60, 60  # 子弹颜色
        self.bullet_allowed = 3  # 限制子弹数量为3

        # 04 外星人设置
        # 05 self.alien_speed_factor = 1
        self.fleet_drop_speed = 10
        # 05 # fleet_direction为1表示向右移动,为-1表示向左移动
        # self.fleet_direction = 1

        # 04 飞船设置
        self.ship_limit = 2

        # 以什么样的速度加快游戏节奏
        self.speedup_scale = 1.1
        # 玩家每提高一个等级,游戏都变得更难,因此处于较高的等级时,外星人的点数应更高。
        # 外星人点数的提高速度
        self.score_scale = 1.5

        # 05 我们将动态变量 和 静态变量分开
        # 调用initialize_dynamic_settings() ,以初始化随游戏进行而变化的属性
        self.initialize_dynamic_settings()

    # 05 初始化随游戏进行而变化的设置
    def initialize_dynamic_settings(self):
        self.bullet_speed_factor = 3  # 子弹速度
        self.alien_speed_factor = 0.8
        self.ship_speed_factor = 1.5  # 02 设置飞船速度

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

        # 05 记分
        # 随着游戏的进行,我们将提高每个外星人值的点数。
        # 为确保每次开始新游戏时这个值都会被重置,我们在initialize_dynamic_settings() 中设置它。
        self.alien_point = 50

    # 05 每当玩家提高一个等级时,我们都使用increase_speed() 来提高飞船、子弹和外星人的速度
    # 提高速度
    def increase_speed(self):
        self.ship_speed_factor *= self.speedup_scale
        self.alien_speed_factor *= self.speedup_scale
        self.ship_speed_factor *= self.speedup_scale

        self.alien_point = int(self.alien_point * self.score_scale)

猜你喜欢

转载自blog.csdn.net/qq_35069382/article/details/81382862
今日推荐