要求在14-2的代码基础上,让标靶的移动速度随着游戏进行而加快,并在单击Play按钮时重置会原来的速度。
我的思路是,在子弹击中外星人事件发生后,修改外星人运动速度,以此来让外星人每次被击中后都移动得更快。
在单击Play按钮时,初始化外星人类的相关属性,以此来重置回原来的速度。
代码如下:
import sys
import pygame
from pygame.sprite import Sprite
import pygame.font
class Play:
"""管理游戏行为和资源的类"""
def __init__(self):
"""初始化游戏并创建游戏资源"""
pygame.init()
self.screen = pygame.display.set_mode((900, 600))
self.screen_rect = self.screen.get_rect()
self.ship = Ship(self)
self.alien = Alien(self)
self.bullets = pygame.sprite.Group()
self.bg_color = (230, 230, 230)
self.play_button = Button(self, "Play")
#游戏初始活动状态
self.game_active = False
#子弹限制数量和剩余子弹数量
self.bullet_limit = 3
self.bullet_left = self.bullet_limit
def run_game(self):
"""开始游戏的主循环"""
while True:
self._check_events()
if self.game_active:
self.ship.update()
self.alien.update()
self._update_bullets()
self._update_screen()
def _check_events(self):
"""响应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
self.ship.moving_up = True
elif event.key == pygame.K_DOWN:
self.ship.moving_down = True
elif event.key == pygame.K_q:
sys.exit()
elif event.key == pygame.K_SPACE:
self._fire_bullet()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
self.ship.moving_up = False
elif event.key == pygame.K_DOWN:
self.ship.moving_down = False
elif event.type == pygame.MOUSEBUTTONDOWN:
self._check_play_button()
def _check_play_button(self):
"""点击play按钮开始游戏"""
mouse_pos = pygame.mouse.get_pos()
click_start_button = self.play_button.rect.collidepoint(mouse_pos)
if click_start_button and not self.game_active:
self.alien.__init__(self)
self.game_active = True
self.bullets.empty()
self.bullet_left = self.bullet_limit
def _fire_bullet(self):
"""创建一个子弹,并加入编组"""
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
def _update_bullets(self):
"""更新子弹"""
self.bullets.update()
#如果有子弹超过屏幕边缘,就删除它,并将子弹上限减去1
for bullet in self.bullets:
if bullet.rect.left >= self.screen_rect.width:
self.bullets.remove(bullet)
self.bullet_left -= 1
#检查子弹是否击中外星人,并做出相应的反应
if pygame.sprite.spritecollideany(self.alien, self.bullets):
self._shout_alien()
#如果子弹上限等于0,就将游戏状态调整为False
if self.bullet_left <= 0:
self.game_active = False
def _shout_alien(self):
"""
子弹击中外星人后,清空子弹的编组、重置外星人的位置、重置剩余子弹的数量。
"""
self.bullets.empty()
self.alien.reset_place()
self.alien.alien_speed *= 1.1
self.bullet_left = self.bullet_limit
def _update_screen(self):
#每次循环都重新绘制屏幕
self.screen.fill(self.bg_color)
#绘制飞船、外星人、和子弹编组
self.ship.blit()
self.alien.blit()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
#绘制Play按钮
if not self.game_active:
self.play_button.draw_button()
#让最近绘制的屏幕可见
pygame.display.flip()
class Ship:
"""管理飞船的类"""
def __init__(self, play_game):
self.screen = play_game.screen
self.screen_rect = play_game.screen.get_rect()
self.image = pygame.image.load('other_files/ship.bmp')
self.rect = self.image.get_rect()
self.rect.midleft = self.screen_rect.midleft
self.moving_up = False
self.moving_down = False
self.y = float(self.rect.y)
def update(self):
if self.moving_up and self.rect.top > 0:
self.y -= 0.5
if self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.y += 0.5
self.rect.y = self.y
def blit(self):
self.screen.blit(self.image, self.rect)
class Bullet(Sprite):
"""管理一个子弹的类"""
def __init__(self, play_game):
"""创建一个子弹"""
super().__init__()
self.screen = play_game.screen
self.color = (60, 60, 60)
#创建一个表示子弹的矩形,再把它放在飞船前方
self.rect = pygame.Rect(0, 0, 15, 3)
self.rect.midright = play_game.ship.rect.midright
#用小数表示子弹的位置
self.x = float(self.rect.x)
def update(self):
"""更新子弹位置"""
self.x += 1.5
self.rect.x = self.x
def draw_bullet(self):
"""屏幕上绘制子弹"""
pygame.draw.rect(self.screen, self.color, self.rect)
class Alien():
"""管理外星飞船的类"""
def __init__(self, play_game):
self.screen = play_game.screen
self.screen_rect = self.screen.get_rect()
self.image = pygame.image.load('other_files/alien.bmp')
self.rect = self.image.get_rect()
#外星人初始位置,屏幕右上角
self.rect.x = self.screen_rect.width - self.rect.width
self.rect.y = 0
#外星人的运动速度
self.alien_speed = 0.1
#表示外星人运动方向的数字,1为向下,-1 为向上
self.direction = 1
self.x = float(self.rect.x)
self.y = float(self.rect.y)
def blit(self):
"""屏幕上绘制外星人"""
self.screen.blit(self.image, self.rect)
def update(self):
"""更新屏幕上外星人的位置"""
self._check_edge()
self.y += self.alien_speed * self.direction
self.rect.y = self.y
def _check_edge(self):
"""检查外星人是否接触到屏幕边缘,是则调整运动方向"""
if self.rect.top < 0 or self.rect.bottom > self.screen_rect.bottom:
self.direction *= -1
def reset_place(self):
self.x = self.screen_rect.width - self.rect.width
self.y = 0
class Button:
def __init__(self, play_game, msg):
"""初始化按钮属性"""
self.screen = play_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)
if __name__ == '__main__':
play = Play()
play.run_game()