Python笔记16-实战小游戏飞机大战(下)


我们会添加一个Play按钮,用于根据需要启动游戏以及在游戏结束后重启游戏,还会修改这个游戏,使其随玩家等级提高而加快节奏。

play按钮

添加一个Play按钮,它在游戏开始前出现,并在游戏结束后再次出现,让玩家能够开始新游戏
让游戏一开始处于非活动状态,并提示玩家单击Play按钮来开始游戏

game_stats.py

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

于Pygame没有内置创建按钮的方法,我们将编写一个Button类,用于创建带标签的实心矩形
创建方法draw_button() ,用于将这个按钮显示到屏幕

import pygame.font
class Button:
    def __init__(self, ai_game, 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)
        # 创建按钮的rect对象,并使其居中。
        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.center = self.screen_rect.center
        # 按钮的标签只需创建一次。
        self._prep_msg(msg)

    def _prep_msg(self, msg):
        """将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

    def draw_button(self):
        # 绘制一个用颜色填充的按钮,再绘制文本。
        self.screen.fill(self.button_color, self.rect)
        self.screen.blit(self.msg_image, self.msg_image_rect)

在AlienInvasion 中使用Button 类来创建一个Play按钮

def __init__(self):
	--snip--
	self._create_fleet()
	# 创建Play按钮。
	self.play_button = Button(self, "Play")

在_update_screen() 对其调用方法draw_button()

    def _update_screen(self):
        """更新屏幕上的图像,并切换到新屏幕。"""
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.draw(self.screen)
        # 如果游戏处于非活动状态,就绘制Play按钮。
        if not self.stats.game_active:
            self.play_button.draw_button()
        pygame.display.flip()

玩家单击Play按钮时开始新游戏,在_check_events() 末尾添加如下elif 代码块,以监视与该按钮相关的鼠标事件

     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()
                self._check_play_button(mouse_pos)

方法_check_play_button() 的代码如下,将它放在_check_events() 后面

   def _check_play_button(self, mouse_pos):
        """在玩家单击Play按钮时开始新游戏。"""
        if self.play_button.rect.collidepoint(mouse_pos):
            self.stats.game_active = True

这里使用了rect 的方法collidepoint() 检查鼠标单击位置是否在Play按钮的rect 内

重置游戏

为在玩家每次单击Play按钮时都重置游戏,需要重置统计信息、删除现有的外星人和子弹、创建一群新的外星人并让飞船居中

  def _check_play_button(self, mouse_pos):
        """在玩家单击Play按钮时开始新游戏。"""
        if self.play_button.rect.collidepoint(mouse_pos):
            # 重置游戏统计信息。
            self.stats.reset_stats()
            self.stats.game_active = True
            # 清空余下的外星人和子弹。
            self.aliens.empty()
            self.bullets.empty()
            # 创建一群新的外星人并让飞船居中。
            self._create_fleet()
            self.ship.center_ship()

当前存在一个问题:即便Play按钮不可见,玩家单击其所在的区域时,游戏依然会做出响应。游戏开始后,如果玩家不小心单击了Play按钮所处的区域,游戏将重新开始!

   def _check_play_button(self, mouse_pos):
        """在玩家单击Play按钮时开始新游戏。"""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            # 重置游戏统计信息。
            self.stats.reset_stats()
            self.stats.game_active = True
            # 清空余下的外星人和子弹。
            self.aliens.empty()
            self.bullets.empty()
            # 创建一群新的外星人并让飞船居中。
            self._create_fleet()
            self.ship.center_ship()

隐藏鼠标光标

   def _check_play_button(self, mouse_pos):
        """在玩家单击Play按钮时开始新游戏。"""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
           ...
            # 隐藏鼠标光标。
            pygame.mouse.set_visible(False)

游戏结束后,将重新显示光标,让玩家能够单击Play按钮来开始新游戏。相关的代码如下:

def _ship_hit(self):
	"""响应飞船被外星人撞到。"""
	if self.stats.ships_left > 0:
		--snip--
	else:
		self.stats.game_active = False
		pygame.mouse.set_visible(True)

提高等级

将整群外星人消灭干净后,玩家将提高一个等级,但游戏的难度没变。下面来增加一点趣味性:每当玩家将屏幕上的外星人消灭干净后,都加快游戏的节奏,让游戏玩起来更难。

class Settings:
    """存储游戏《外星人入侵》中所有设置的类"""
    def __init__(self):
        """初始化游戏的设置。"""
        # 屏幕设置
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)
        #飞船移动速度
        self.ship_speed =5
        self.ship_limit = 3

        #子弹设置
        self.bullet_speed = 3.0
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (60, 60, 60)
        self.bullets_allowed = 50

        # 外星人设置
        self.alien_speed = 1.0
        self.fleet_drop_speed = 30
        # fleet_direction为1表示向右移,为-1表示向左移。
        self.fleet_direction = 1

        # 加快游戏节奏的速度。
        self.speedup_scale = 1.1
        self.initialize_dynamic_settings()

    def initialize_dynamic_settings(self):
        """初始化随游戏进行而变化的设置。"""
        self.ship_speed = 1.5
        self.bullet_speed = 3.0
        self.alien_speed = 1.0
        # fleet_direction为1表示向右,为-1表示向左。
        self.fleet_direction = 1


    #在玩家的等级提高时提高飞船、子弹和外星人的速度
    def increase_speed(self):
        """提高速度设置"""
        self.ship_speed *= self.speedup_scale
        self.bullet_speed *= self.speedup_scale
        self.alien_speed *= self.speedup_scale

在_check_bullet_alien_collisions() 中,在整群外星人都被消灭后调用increase_speed() 来加快游戏的节奏

def _update_bullets(self):
    """更新子弹的位置并删除消失的子弹。"""
    # 更新子弹的位置。
    self.bullets.update()
    # 删除消失的子弹。
    for bullet in self.bullets.copy():
        if bullet.rect.bottom <= 0:
            self.bullets.remove(bullet)
    # 检查是否有子弹击中了外星人。
    # 如果是,就删除相应的子弹和外星人。
    self._check_bullet_alien_collisions()

def _check_bullet_alien_collisions(self):
    """响应子弹和外星人碰撞。"""
    # 删除发生碰撞的子弹和外星人。
    collisions = pygame.sprite.groupcollide(
        self.bullets, self.aliens, True, True)
    if not self.aliens:
        # 删除现有的所有子弹,并创建一群新的外星人。
        self.bullets.empty()
        self._create_fleet()
        self.settings.increase_speed()

每当玩家开始新游戏时,都需要将发生了变化的设置重置为初始值

def _check_play_button(self, mouse_pos):
	"""在玩家单击Play按钮时开始新游戏。"""
	button_clicked = self.play_button.rect.collidepoint(mouse_pos)
	if button_clicked and not self.stats.game_active:
		# 重置游戏设置。
		self.settings.initialize_dynamic_settings()
		--snip--

游戏完成

到目前为止,这个小游戏 就可以不断的 玩了。可以根据需要调整各项参数。
源码下载地址:点击下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

catch that elf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值