当前位置: 首页 > news >正文

免费网站赚钱门户网站建设收费

免费网站赚钱,门户网站建设收费,大型网上商城,wordpress 做英汉翻译一、规划 在游戏《外星人入侵》中#xff0c;玩家控制着一艘最初出现在屏幕底部中央的飞船。玩家可以使用箭头键左右移动飞船#xff0c;还可使用空格键进行射击。游戏开始时#xff0c;一群外星人出现在天空中#xff0c;他们在屏 幕中向下移动。玩家的任务是射杀这些外星…一、规划 在游戏《外星人入侵》中玩家控制着一艘最初出现在屏幕底部中央的飞船。玩家可以使用箭头键左右移动飞船还可使用空格键进行射击。游戏开始时一群外星人出现在天空中他们在屏 幕中向下移动。玩家的任务是射杀这些外星人。玩家将所有外星人都消灭干净后将出现一群新的外星人他们移动的速度更快。只要有外星人撞到了玩家的飞船或到达了屏幕底部玩家就损失一艘飞船。玩家损失三艘飞船后游戏结束。 二、依赖库 Pygame 三、创建飞船 1.创建Pygame窗口以及响应用户输入 import sys import pygamedef run_game():# 初始化游戏并创建一个屏幕对象pygame.init()screenpygame.display.set_mode((1200,800))pygame.display.set_caption(Alien Invasion)#游戏开始的主循环while True:#监视键盘和鼠标for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()#让最近绘制的屏幕可见pygame.display.flip()run_game() pygame.init()初始化背景设置让Pygame能够正确地工作。调用pygame.display.set_mode()来创建一个名为screen的显示窗口这个游戏的所有图形元素都将在其中绘制。实参(1200, 800)是一个元组指定了游戏窗口的尺寸。 对象screen是一个surface。在Pygame中surface是屏幕的一部分用于显示游戏元素。在这个游戏中每个元素都是一个surface。display.set_mode()返回的surface表示整个游戏窗口。我们激活游戏的动画循环后每经过一次循环都将自动重绘这个surface。 这个游戏由一个while循环控制其中包含一个事件循环以及管理屏幕更新的代码。事件是用户玩游戏时执行的操作如按键或移动鼠标。为让程序响应事件我们编写一个事件循环以侦听事件并根据发生的事件执行相应的任务。 为访问Pygame检测到的事件我们使用方法pygame.event.get()。所有键盘和鼠标事件都将促使for循环运行。在这个循环中我们将编写一系列的if语句来检测并响应特定的事件。玩家单击游戏窗口的关闭按钮时将检测到pygame.QUIT事件而我们调用sys.exit()来退出游戏。 调用了pygame.display.flip()命令Pygame让最近绘制的屏幕可见。在这里它在每次执行while循环时都绘制一个空屏幕并擦去旧屏幕使得只有新屏幕可见。在我们移动游戏元素时pygame.display.flip()将不断更新屏幕以显示元素的新位置并在原来的位置隐藏元素从而营造平滑移动的效果。 2.设置背景色 import sys import pygamedef run_game():# 初始化游戏并创建一个屏幕对象pygame.init()screenpygame.display.set_mode((1200,600))pygame.display.set_caption(Alien Invasion)# 设置背景色bg_color (230, 230, 230)#游戏开始的主循环while True:#监视键盘和鼠标for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()# 每次循环时都重绘屏幕screen.fill(bg_color)#让最近绘制的屏幕可见pygame.display.flip()run_game() 在Pygame中颜色是以RGB值指定的。这种颜色由红色、绿色和蓝色值组成其中每个值的可能取值范围都为0~255。我们调用方法screen.fill()用背景色填充屏幕这个方法只接受一个实参一种颜色。 3.创建设置类 class Settings():存储《外星人入侵》的所有设置的类def __init__(self):初始化游戏的设置# 屏幕设置self.screen_width 1200self.screen_height 600self.bg_color (230, 230, 230) import sys import pygame from settings import Settingsdef run_game():# 初始化游戏并创建一个屏幕对象pygame.init()ai_settings Settings()screenpygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))pygame.display.set_caption(Alien Invasion)# 设置背景色bg_color (230, 230, 230)#游戏开始的主循环while True:#监视键盘和鼠标for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()# 每次循环时都重绘屏幕screen.fill(ai_settings.bg_color)#让最近绘制的屏幕可见pygame.display.flip()run_game() 编写一个名为settings的模块其中包含一个名为Settings的类用于将所有设置存储在一个地方以免在代码中到处添加设置。这样我们就能传递一个设置对象而不是众多不同的设置。 4.添加飞船图像 在游戏中几乎可以使用任何类型的图像文件但使用位图.bmp文件最为简单因为Pygame默认加载位图。虽然可配置Pygame以使用其他文件类型但有些文件类型要求你在计算机上安装相应的图像库。图灵社区 5.创建Ship类 import pygameclass Ship():def __init__(self,screen):初始化飞船并设置其初始位置self.screen screen# 加载飞船图像并获取其外接矩形self.image pygame.image.load(images/ship.bmp)self.rect self.image.get_rect()self.screen_rect screen.get_rect()# 将每艘新飞船放在屏幕底部中央self.rect.centerxself.screen_rect.centerxself.rect.bottomself.screen_rect.bottomdef blitme(self):在指定位置绘制飞船self.screen.blit(self.image, self.rect)Ship的方法__init__()接受两个参数引用self和screen其中后者指定了要将飞船绘制到什么地 方。为加载图像我们调用了pygame.image.load()。这个函数返回一个表示飞船的surface而我们将这个surface存储到了self.image中。 加载图像后我们使用get_rect()获取相应surface的属性rect。Pygame的效率之所以如此高一个原因是它让你能够像处理矩形一样处理游戏元素即便它们的形状并非矩形。 处理rect对象时可使用矩形四角和中心的 x 和 y 坐标。可通过设置这些值来指定矩形的位置。要将游戏元素居中可设置相应rect对象的属性center、centerx或centery。要让游戏元素与屏幕边缘对齐可使用属性top、bottom、left或right要调整游戏元素的水平或垂直位置可使用属性x和y它们分别是相应矩形左上角的 x 和 y 坐标。 6.在屏幕上绘制飞船 import sys import pygame from settings import Settings from ship import Ship def run_game():# 初始化游戏并创建一个屏幕对象pygame.init()ai_settings Settings()screenpygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))pygame.display.set_caption(Alien Invasion)ship Ship(screen)#游戏开始的主循环while True:#监视键盘和鼠标for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()# 每次循环时都重绘屏幕screen.fill(ai_settings.bg_color)ship.blitme()#让最近绘制的屏幕可见pygame.display.flip()run_game() 7.重构模块game_functions 在大型项目中经常需要在添加新代码前重构既有代码。重构旨在简化既有代码的结构使其更容易扩展。 1函数check_events() import pygame import sysdef check_events():响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:sys.exit() 2函数update_screen() import pygame import sysdef check_events():响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()def update_screen(ai_settings,screen,ship):更新屏幕上的图像并切换到新屏幕# 每次循环时都重绘屏幕screen.fill(ai_settings.bg_color)ship.blitme()# 让最近绘制的屏幕可见pygame.display.flip() 8.驾驶飞船 1响应按键 每当用户按键时都将在Pygame中注册一个事件。事件都是通过方法pygame.event.get()获取的因此在函数check_events()中我们需要指定要检查哪些类型的事件。每次按键都被注册为一个KEYDOWN事件。 def check_events(ship):响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()elif event.type pygame.KEYDOWN:if event.key pygame.K_RIGHT:ship.rect.center_x 1 2允许不断移动 玩家按住右箭头键不放时我们希望飞船不断地向右移动直到玩家松开为止。我们将让游戏检测pygame.KEYUP事件以便玩家松开右箭头键时我们能够知道这一点然后我们将结合使用KEYDOWN和KEYUP事件以及一个名为moving_right的标志来实现持续移动。 飞船不动时标志moving_right将为False。玩家按下右箭头键时我们将这个标志设置为True而玩家松开时我们将这个标志重新设置为False。 飞船的属性都由Ship类控制因此我们将给这个类添加一个名为moving_right的属性和一个名为update()的方法。方法update()检查标志moving_right的状态如果这个标志为True就调整飞船的位置。每当需要调整飞船的位置时我们都调用这个方法。 import pygameclass Ship():def __init__(self,screen):初始化飞船并设置其初始位置self.screen screen# 加载飞船图像并获取其外接矩形self.image pygame.image.load(images/ship.bmp)self.rect self.image.get_rect()self.screen_rect screen.get_rect()# 将每艘新飞船放在屏幕底部中央self.rect.centerxself.screen_rect.centerxself.rect.bottomself.screen_rect.bottom# 移动标志self.moving_right Falsedef update(self):根据移动标志调整飞船的位置if self.moving_right:self.rect.centerx1def blitme(self):在指定位置绘制飞船self.screen.blit(self.image, self.rect)def check_events(ship):响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()elif event.type pygame.KEYDOWN:if event.key pygame.K_RIGHT:ship.moving_right Trueelif event.type pygame.KEYUP:if event.key pygame.K_RIGHT:ship.moving_right False 修改alien_invasion.py中的while循环  while True:#监视键盘和鼠标gf.check_events(ship)ship.update()gf.update_screen(ai_settings, screen, ship) 3左右移动 ship.py更新 import pygameclass Ship():def __init__(self,screen):初始化飞船并设置其初始位置self.screen screen# 加载飞船图像并获取其外接矩形self.image pygame.image.load(images/ship.bmp)self.rect self.image.get_rect()self.screen_rect screen.get_rect()# 将每艘新飞船放在屏幕底部中央self.rect.centerxself.screen_rect.centerxself.rect.bottomself.screen_rect.bottom# 移动标志self.moving_right Falseself.moving_left Falsedef update(self):根据移动标志调整飞船的位置if self.moving_right:self.rect.centerx1if self.moving_left:self.rect.centerx-1def blitme(self):在指定位置绘制飞船self.screen.blit(self.image, self.rect)game_functions.py更新 def check_events(ship):响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()elif event.type pygame.KEYDOWN:if event.key pygame.K_RIGHT:ship.moving_right Trueelif event.key pygame.K_LEFT:ship.moving_left Trueelif event.type pygame.KEYUP:if event.key pygame.K_RIGHT:ship.moving_right Falseelif event.key pygame.K_LEFT:ship.moving_left False4调整飞船的速度 在Settings类中添加属性ship_speed_factor用于控制飞船的速度。 class Settings():存储《外星人入侵》的所有设置的类def __init__(self):初始化游戏的设置# 屏幕设置self.screen_width 1200self.screen_height 600self.bg_color (230, 230, 230)self.ship_speed_factor 1.5 通过将速度设置指定为小数值可在后面加快游戏的节奏时更细致地控制飞船的速度。然而rect的centerx等属性只能存储整数值因此我们需要对Ship类做些修改。 import pygameclass Ship():def __init__(self,ai_settings,screen):初始化飞船并设置其初始位置self.screen screenself.ai_settings ai_settings# 加载飞船图像并获取其外接矩形self.image pygame.image.load(images/ship.bmp)self.rect self.image.get_rect()self.screen_rect screen.get_rect()# 将每艘新飞船放在屏幕底部中央self.rect.centerxself.screen_rect.centerxself.rect.bottomself.screen_rect.bottom# 在飞船的属性center中存储小数值self.center float(self.rect.centerx)# 移动标志self.moving_right Falseself.moving_left Falsedef update(self):根据移动标志调整飞船的位置# 更新飞船的center值而不是rectif self.moving_right:self.center self.ai_settings.ship_speed_factorif self.moving_left:self.center -self.ai_settings.ship_speed_factor# 根据self.center更新rect对象self.rect.centerxself.centerdef blitme(self):在指定位置绘制飞船self.screen.blit(self.image, self.rect)5限制飞船的活动范围 将修改Ship类的方法update() def update(self):根据移动标志调整飞船的位置# 更新飞船的center值而不是rectif self.moving_right and self.rect.right self.screen_rect.right:self.center self.ai_settings.ship_speed_factorif self.moving_left and self.rect.left 0:self.center -self.ai_settings.ship_speed_factor# 根据self.center更新rect对象self.rect.centerxself.center 6重构check_events() 我们将其部分代码放在两个函数中一个处理KEYDOWN事件另一个处理KEYUP事件 def check_keydown_events(event,ship):if event.key pygame.K_RIGHT:ship.moving_right Trueelif event.key pygame.K_LEFT:ship.moving_left Truedef check_keyup_events(event, ship):if event.key pygame.K_RIGHT:ship.moving_right Falseelif event.key pygame.K_LEFT:ship.moving_left False def check_events(ship):响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()elif event.type pygame.KEYDOWN:check_keydown_events(event,ship)elif event.type pygame.KEYUP:check_keyup_events(event, ship)9.射击 1添加子弹设置 class Settings():存储《外星人入侵》的所有设置的类def __init__(self):初始化游戏的设置# 屏幕设置self.screen_width 1200self.screen_height 600self.bg_color (230, 230, 230)self.ship_speed_factor 1.5# 子弹设置self.bullet_speed_factor 1self.bullet_width 3self.bullet_height 15self.bullet_color 60, 60, 60 2创建Bullet类 import pygame from pygame.sprite import Spriteclass Bullet(Sprite):一个对飞船发射的子弹进行管理的类def __init__(self, ai_settings, screen, ship):在飞船所处的位置创建一个子弹对象super().__init__()self.screen screen# 在(0,0)处创建一个表示子弹的矩形再设置正确的位置self.rectpygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_height)self.rect.centerxship.rect.centerxself.rect.topship.rect.top# 存储用小数表示的子弹位置self.yfloat(self.rect.y)self.color ai_settings.bullet_colorself.speed_factor ai_settings.bullet_speed_factordef update(self):向上移动子弹# 更新表示子弹位置的小数值self.y-self.ship_speed_factor# 更新表示子弹的rect的位置self.rect.yself.ydef draw_bullet(self):在屏幕上绘制子弹pygame.draw.rect(self.screen, self.color, self.rect) Bullet类继承了我们从模块pygame.sprite中导入的Sprite类。通过使用Sprite可将游戏中相关的元素编组进而同时操作编组中的所有元素。 需要绘制子弹时我们调用draw_bullet()。函数draw.rect()使用存储在self.color中的颜色填充表示子弹的rect占据的屏幕部分。 3将子弹存储到编组中 import pygamefrom settings import Settings from ship import Ship import game_functions as gf from pygame.sprite import Group def run_game():# 初始化游戏并创建一个屏幕对象pygame.init()ai_settings Settings()screenpygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))pygame.display.set_caption(Alien Invasion)ship Ship(ai_settings,screen)# 创建一个用于存储子弹的编组bullets Group()#游戏开始的主循环while True:#监视键盘和鼠标gf.check_events(ai_settings, screen, ship, bullets)ship.update()bullets.update()gf.update_screen(ai_settings, screen, ship, bullets)run_game() 我们将在alien_invasion.py中创建一个编组group用于存储所有有效的子弹以便能够管理发射出去的所有子弹。这个编组将是pygame.sprite.Group类的一个实例pygame.sprite.Group类类似于列表但提供了有助于开发游戏的额外功能。 我们将bullets传递给了check_events()和update_screen()。在check_events()中需要在玩家按空格键时处理bullets而在update_screen()中需要更新要绘制到屏幕上的bullets。当你对编组调用update()时编组将自动对其中的每个精灵调用update()因此代码行bullets.update()将为编组bullets中的每颗子弹调用bullet.update()。 4开火 在game_functions.py中我们需要修改check_keydown_events()以便在玩家按空格键时发射一颗子弹。我们无需修改check_keyup_events()因为玩家松开空格键时什么都不会发生。我们还需修改update_screen()确保在调用flip()前在屏幕上重绘每颗子弹。 import pygame import sys from bullet import Bulletdef check_keydown_events(event,ai_settings, screen, ship, bullets):if event.key pygame.K_RIGHT:ship.moving_right Trueelif event.key pygame.K_LEFT:ship.moving_left Trueelif event.key pygame.K_SPACE:# 创建一颗子弹并将其加入到编组bullets中new_bullet Bullet(ai_settings, screen, ship)bullets.add(new_bullet)def check_keyup_events(event, ship):if event.key pygame.K_RIGHT:ship.moving_right Falseelif event.key pygame.K_LEFT:ship.moving_left False def check_events(ai_settings, screen, ship, bullets):响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:sys.exit()elif event.type pygame.KEYDOWN:check_keydown_events(event, ai_settings, screen, ship,bullets)elif event.type pygame.KEYUP:check_keyup_events(event, ship)def update_screen(ai_settings, screen, ship, bullets):更新屏幕上的图像并切换到新屏幕# 每次循环时都重绘屏幕screen.fill(ai_settings.bg_color)# 在飞船和外星人后面重绘所有子弹for bullet in bullets.sprites():bullet.draw_bullet()ship.blitme()# 让最近绘制的屏幕可见pygame.display.flip()编组bulltes传递给了check_keydown_events()。玩家按空格键时创建一颗新子弹并使用方法add()将其加入到编组bullets中。 我们给在屏幕上绘制子弹的update_screen()添加了形参bullets。方法bullets.sprites()返回一个列表其中包含编组bullets中的所有sprite。为在屏幕上绘制发射的所有子弹我们遍历编组bullets中的sprite并对每个sprite都调用draw_bullet() 5删除已消失的子弹 我们检查每颗子弹看看它是否已从屏幕顶端消失。如果是这样就将其从bullets中删除。我们使用了一条print语句以显示当前还有多少颗子弹从而核实已消失的子弹确实删除了。 #游戏开始的主循环while True:#监视键盘和鼠标gf.check_events(ai_settings, screen, ship, bullets)ship.update()bullets.update()# 删除已消失的子弹for bullet in bullets.copy():if bullet.rect.bottom 0: bullets.remove(bullet)print(len(bullets))gf.update_screen(ai_settings, screen, ship, bullets) 6限制子弹数量 在settings.py中存储所允许的最大子弹数 # 子弹设置self.bullet_speed_factor 1self.bullet_width 3self.bullet_height 15self.bullet_color 60, 60, 60self.bullets_allowed 3 在game_functions.py的check_keydown_events()中我们在创建新子弹前检查未消失的子弹数是否小于该设置 elif event.key pygame.K_SPACE:# 创建一颗子弹并将其加入到编组bullets中if len(bullets) ai_settings.bullets_allowed:new_bullet Bullet(ai_settings, screen, ship)bullets.add(new_bullet) 7创建函数update_bullets() 我们创建一个名为update_bullets()的新函数并将其添加到game_functions.py的末尾 def update_bullets(bullets):更新子弹的位置并删除已消失的子弹# 更新子弹的位置bullets.update()# 删除已消失的子弹for bullet in bullets.copy():if bullet.rect.bottom 0:bullets.remove(bullet) alien_invasion.py中的while循环又变得很简单 #游戏开始的主循环while True:#监视键盘和鼠标gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(bullets)gf.update_screen(ai_settings, screen, ship, bullets) 8创建函数fire_bullet() 下面将发射子弹的代码移到一个独立的函数中这样在check_keydown_events()中只需使用一行代码来发射子弹让elif代码块变得非常简单. def check_keydown_events(event,ai_settings, screen, ship, bullets):if event.key pygame.K_RIGHT:ship.moving_right Trueelif event.key pygame.K_LEFT:ship.moving_left Trueelif event.key pygame.K_SPACE:fire_bullet(ai_settings, screen, ship, bullets)def fire_bullet(ai_settings, screen, ship, bullets):如果还没有到达限制就发射一颗子弹# 创建新子弹并将其加入到编组bullets中if len(bullets) ai_settings.bullets_allowed:new_bullet Bullet(ai_settings, screen, ship)bullets.add(new_bullet) 9添加一个结束游戏的快捷键Q def check_keydown_events(event,ai_settings, screen, ship, bullets):if event.key pygame.K_RIGHT:ship.moving_right Trueelif event.key pygame.K_LEFT:ship.moving_left Trueelif event.key pygame.K_SPACE:fire_bullet(ai_settings, screen, ship, bullets)elif event.key pygame.K_q:sys.exit() 四、创建外星人 1.创建Alien类 import pygame from pygame.sprite import Spriteclass Alien(Sprite):表示单个外星人的类def __init__(self, ai_settings, screen):初始化外星人并设置其起始位置super().__init__()self.screen screenself.ai_settings ai_settings# 加载外星人图像并设置其rect属性self.image pygame.image.load(images/alien.bmp)self.rect self.image.get_rect()# 每个外星人最初都在屏幕左上角附近self.rect.x self.rect.widthself.rect.y self.rect.height# 存储外星人的准确位置self.x float(self.rect.x)def blitme(self):在指定位置绘制外星人self.screen.blit(self.image, self.rect) 2.创建Alien实例 import pygamefrom settings import Settings from ship import Ship import game_functions as gf from alien import Alien from pygame.sprite import Group def run_game():# 初始化游戏并创建一个屏幕对象pygame.init()ai_settings Settings()screenpygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))pygame.display.set_caption(Alien Invasion)ship Ship(ai_settings,screen)# 创建一个用于存储子弹的编组bullets Group()# 创建一个外星人alien Alien(ai_settings, screen)#游戏开始的主循环while True:#监视键盘和鼠标gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(bullets)gf.update_screen(ai_settings, screen, ship, alien,bullets)run_game() 3.让外星人出现在屏幕上 def update_screen(ai_settings, screen, ship, alien,bullets):更新屏幕上的图像并切换到新屏幕# 每次循环时都重绘屏幕screen.fill(ai_settings.bg_color)# 在飞船和外星人后面重绘所有子弹for bullet in bullets:bullet.draw_bullet()ship.blitme()alien.blitme()# 让最近绘制的屏幕可见pygame.display.flip() 4.创建一群外星人 为创建一行外星人首先在alien_invasion.py中创建一个名为aliens的空编组用于存储全部外星人再调用game_functions.py中创建外星人群的函数 import pygamefrom settings import Settings from ship import Ship import game_functions as gf from pygame.sprite import Group def run_game():# 初始化游戏并创建一个屏幕对象pygame.init()ai_settings Settings()screenpygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))pygame.display.set_caption(Alien Invasion)# 创建一艘飞船、一个子弹编组和一个外星人编组ship Ship(ai_settings, screen)bullets Group()aliens Group()# 创建外星人群gf.create_fleet(ai_settings, screen, aliens)#游戏开始的主循环while True:#监视键盘和鼠标gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(bullets)gf.update_screen(ai_settings, screen, ship, aliens,bullets)run_game() 我们还需要修改update_screen() def update_screen(ai_settings, screen, ship, aliens ,bullets):更新屏幕上的图像并切换到新屏幕# 每次循环时都重绘屏幕screen.fill(ai_settings.bg_color)# 在飞船和外星人后面重绘所有子弹for bullet in bullets:bullet.draw_bullet()ship.blitme()aliens.draw(screen)# 让最近绘制的屏幕可见pygame.display.flip() 5.创建外星人群 下面是新函数create_fleet() def create_fleet(ai_settings, screen, aliens):创建外星人群# 创建一个外星人并计算一行可容纳多少个外星人# 外星人间距为外星人宽度alien Alien(ai_settings, screen)alien_width alien.rect.widthavailable_space_x ai_settings.screen_width - 2 * alien_widthnumber_aliens_x int(available_space_x / (2 * alien_width))# 创建第一行外星人for alien_number in range(number_aliens_x):# 创建一个外星人并将其加入当前行alien Alien(ai_settings, screen)alien.x alien_width 2 * alien_width * alien_numberalien.rect.x alien.xaliens.add(alien) 1重构create_fleet() 下面是create_fleet()和两个新函数get_number_aliens_x()和create_alien()。 def get_number_aliens_x(ai_settings, alien_width):计算每行可容纳多少个外星人available_space_x ai_settings.screen_width - 2 * alien_widthnumber_aliens_x int(available_space_x / (2 * alien_width))return number_aliens_x def create_alien(ai_settings, screen, aliens, alien_number):创建一个外星人并将其放在当前行alien Alien(ai_settings, screen)alien_width alien.rect.widthalien.x alien_width 2 * alien_width * alien_numberalien.rect.x alien.xaliens.add(alien) def create_fleet(ai_settings, screen, aliens):创建外星人群# 创建一个外星人并计算每行可容纳多少个外星人alien Alien(ai_settings, screen)number_aliens_x get_number_aliens_x(ai_settings,alien.rect.width)# 创建第一行外星人for alien_number in range(number_aliens_x):create_alien(ai_settings, screen, aliens, alien_number) 2添加行 def create_fleet(ai_settings, screen, ship,aliens):创建外星人群# 创建一个外星人并计算每行可容纳多少个外星人alien Alien(ai_settings, screen)number_aliens_x get_number_aliens_x(ai_settings,alien.rect.width)number_rows get_number_rows(ai_settings, ship.rect.height,alien.rect.height)# 创建外星人群for row_number in range(number_rows):for alien_number in range(number_aliens_x):create_alien(ai_settings, screen, aliens,alien_number,row_number)def get_number_rows(ai_settings, ship_height, alien_height):计算屏幕可容纳多少行外星人available_space_y (ai_settings.screen_height -(3 * alien_height) - ship_height)number_rows int(available_space_y / (2 * alien_height))return number_rows def create_alien(ai_settings, screen, aliens, alien_number,row_number):创建一个外星人并将其放在当前行alien Alien(ai_settings, screen)alien_width alien.rect.widthalien.x alien_width 2 * alien_width * alien_numberalien.rect.x alien.xalien.rect.y alien.rect.height 2 * alien.rect.height * row_numberaliens.add(alien) 6.让外星人群移动 1向右移动外星人 我们将使用alien.py中的方法update()且对外星人群中的每个外星人都调用它。 def __init__(self):--snip--# 外星人设置self.alien_speed_factor 1 def update(self):向右移动外星人self.x self.ai_settings.alien_speed_factor self.rect.x self.x 在主while循环中已调用了更新飞船和子弹的方法但现在还需更新每个外星人的位置 #游戏开始的主循环while True:#监视键盘和鼠标gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(bullets)gf.update_aliens(aliens)gf.update_screen(ai_settings, screen, ship, aliens,bullets) 最后在文件game_functions.py末尾添加新函数update_aliens() def update_aliens(aliens):更新外星人群中所有外星人的位置aliens.update() 我们对编组aliens调用方法update()这将自动对每个外星人调用方法update()。 2创建表示外星人移动方向的设置 下面来创建让外星人撞到屏幕右边缘后向下移动、再向左移动的设置。 # 外星人设置 self.alien_speed_factor 1 self.fleet_drop_speed 10 # fleet_direction为1表示向右移为-1表示向左移 self.fleet_direction 1 设置fleet_drop_speed指定了有外星人撞到屏幕边缘时外星人群向下移动的速度。 3检查外星人是否撞到了屏幕边缘 需要编写一个方法来检查是否有外星人撞到了屏幕边缘还需修改update()以让每个外星人都沿正确的方向移动。 def update(self):向左或向右移动外星人self.x (self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction)self.rect.x self.xdef check_edges(self):如果外星人位于屏幕边缘就返回Truescreen_rect self.screen.get_rect()if self.rect.right screen_rect.right:return Trueelif self.rect.left 0:return True 4向下移动外星人群并改变移动方向 需要对game_functions.py做重大修改我们编写函数check_fleet_edges()和change_fleet_direction()并对update_aliens()进行修改。 def check_fleet_edges(ai_settings, aliens):有外星人到达边缘时采取相应的措施for alien in aliens.sprites():if alien.check_edges():change_fleet_direction(ai_settings, aliens)break def change_fleet_direction(ai_settings, aliens):将整群外星人下移并改变它们的方向for alien in aliens.sprites():alien.rect.y ai_settings.fleet_drop_speedai_settings.fleet_direction * -1 def update_aliens(ai_settings, aliens):检查是否有外星人位于屏幕边缘并更新整群外星人的位置check_fleet_edges(ai_settings, aliens)aliens.update() alien_invasion.py也需要进行相应修改 # 开始游戏主循环while True:gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(bullets)gf.update_aliens(ai_settings, aliens)gf.update_screen(ai_settings, screen, ship, aliens,bullets) 五、射杀外星人 我们将使用sprite.groupcollide()检测两个编组的成员之间的碰撞。 1.检测子弹与外星人的碰撞 方法sprite.groupcollide()将每颗子弹的rect同每个外星人的rect进行比较并返回一个字典其中包含发生了碰撞的子弹和外星人。 在函数update_bullets()中使用下面的代码来检查碰撞。 def update_bullets(aliens, bullets):更新子弹的位置并删除已消失的子弹# 更新子弹的位置bullets.update()# 删除已消失的子弹for bullet in bullets.copy():if bullet.rect.bottom 0:bullets.remove(bullet)# 检查是否有子弹击中了外星人# 如果是这样就删除相应的子弹和外星人collisions pygame.sprite.groupcollide(bullets, aliens, True,True) 每当有子弹和外星人的rect重叠时groupcollide()就在它返回的字典中添加一个键-值对。两个实参True告诉Pygame删除发生碰撞的子弹和外星人。  我们调用update_bullets()时传递了实参aliens while True:gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(aliens, bullets)gf.update_aliens(ai_settings, aliens)gf.update_screen(ai_settings, screen, ship, aliens,bullets) 2.生成新的外星人群 首先需要检查编组aliens是否为空。如果为空就调用create_fleet()。我们将在update_bullets()中执行这种检查因为外星人都是在这里被消灭的。 def update_bullets(ai_settings, screen, ship, aliens, bullets):--snip--# 检查是否有子弹击中了外星人# 如果是就删除相应的子弹和外星人collisions pygame.sprite.groupcollide(bullets, aliens, True,True)if len(aliens) 0: # 删除现有的子弹并新建一群外星人bullets.empty() create_fleet(ai_settings, screen, ship, aliens) 我们需要更新alien_invasion.py中对update_bullets()的调用 # 开始游戏主循环 while True:gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(ai_settings, screen, ship, aliens,bullets)gf.update_aliens(ai_settings, aliens)gf.update_screen(ai_settings, screen, ship, aliens,bullets) 3.重构update_bullets() def update_bullets(ai_settings, screen, ship, aliens, bullets):--snip--# 删除已消失的子弹for bullet in bullets.copy():if bullet.rect.bottom 0:bullets.remove(bullet)check_bullet_alien_collisions(ai_settings, screen, ship,aliens, bullets) def check_bullet_alien_collisions(ai_settings, screen, ship,aliens, bullets):响应子弹和外星人的碰撞# 删除发生碰撞的子弹和外星人collisions pygame.sprite.groupcollide(bullets, aliens, True,True)if len(aliens) 0:# 删除现有的所有子弹并创建一个新的外星人群bullets.empty()create_fleet(ai_settings, screen, ship, aliens) 我们创建了一个新函数——check_bullet_alien_collisions()以检测子弹和外星人之间的碰撞以及在整群外星人都被消灭干净时采取相应的措施。这避免了update_bullets()太长。 六、结束游戏 1.检测外星人和飞船碰撞 我们在更新每个外星人的位置后立即检测外星人和飞船之间的碰撞。 def update_aliens(ai_settings, ship, aliens):检查是否有外星人到达屏幕边缘然后更新所有外星人的位置check_fleet_edges(ai_settings, aliens)aliens.update()# 检测外星人和飞船之间的碰撞if pygame.sprite.spritecollideany(ship, aliens): print(Ship hit!!!) 方法spritecollideany()接受两个实参一个sprite和一个编组。它检查编组是否有成员与sprite发生了碰撞并在找到与sprite发生了碰撞的成员后就停止遍历编组。 如果没有发生碰撞spritecollideany()将返回None因此if代码块不会执行。如果找到了与飞船发生碰撞的外星人它就返回这个外星人。 现在我们需要将ship传递给update_aliens() # 开始游戏主循环 while True:gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(ai_settings, screen, ship, aliens,bullets)gf.update_aliens(ai_settings, ship, aliens)gf.update_screen(ai_settings, screen, ship, aliens,bullets) 2.响应外星人和飞船碰撞 编写一个用于跟踪游戏统计信息的新类——GameStats并将其保存为文件game_stats.py class GameStats():跟踪游戏的统计信息def __init__(self, ai_settings):初始化统计信息self.ai_settings ai_settingsself.reset_stats() def reset_stats(self):初始化在游戏运行期间可能变化的统计信息self.ships_left self.ai_settings.ship_limit 在这个游戏运行期间我们只创建一个GameStats实例但每当玩家开始新游戏时需要重置一些统计信息。为此我们在方法reset_stats()中初始化大部分统计信息而不是在__init__()中直接初始化它们。 一开始玩家拥有的飞船数存储在settings.py的ship_limit中 # 飞船设置 self.ship_speed_factor 1.5 self.ship_limit 3 我们还需对alien_invasion.py做些修改以创建一个GameStats实例 --snip-- from settings import Settings from game_stats import GameStats --snip-- def run_game():--snip--pygame.display.set_caption(Alien Invasion)# 创建一个用于存储游戏统计信息的实例stats GameStats(ai_settings) --snip--# 开始游戏主循环while True:--snip--gf.update_bullets(ai_settings, screen, ship, aliens,bullets)gf.update_aliens(ai_settings, stats, screen, ship, aliens,bullets) --snip-- 实现响应功能的大部分代码放到函数ship_hit()中 import sys from time import sleep import pygame --snip-- def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):响应被外星人撞到的飞船# 将ships_left减1stats.ships_left - 1 # 清空外星人列表和子弹列表aliens.empty() bullets.empty()# 创建一群新的外星人并将飞船放到屏幕底端中央create_fleet(ai_settings, screen, ship, aliens) ship.center_ship()# 暂停sleep(0.5) def update_aliens(ai_settings, stats, screen, ship, aliens,bullets): --snip--# 检测外星人和飞船碰撞if pygame.sprite.spritecollideany(ship, aliens):ship_hit(ai_settings, stats, screen, ship, aliens,bullets) def center_ship(self):让飞船在屏幕上居中self.center self.screen_rect.centerx 3.有外星人到达屏幕底端 def check_aliens_bottom(ai_settings, stats, screen, ship, aliens,bullets):检查是否有外星人到达了屏幕底端screen_rect screen.get_rect()for alien in aliens.sprites():if alien.rect.bottom screen_rect.bottom: # 像飞船被撞到一样进行处理ship_hit(ai_settings, stats, screen, ship, aliens,bullets)break def update_aliens(ai_settings, stats, screen, ship, aliens,bullets):--snip--# 检查是否有外星人到达屏幕底端check_aliens_bottom(ai_settings, stats, screen, ship, aliens,bullets) 4.游戏结束 下面在GameStats中添加一个作为标志的属性game_active以便在玩家的飞船用完后结束游戏 def __init__(self, settings):--snip--# 游戏刚启动时处于活动状态self.game_active True 现在在ship_hit()中添加代码在玩家的飞船都用完后将game_active设置为False def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):响应飞船被外星人撞到if stats.ships_left 0: # 将ships_left减1stats.ships_left - 1--snip--#暂停一会儿sleep(0.5)else:stats.game_active False 七、确定应运行游戏的哪些部分 在alien_invasion.py中我们需要确定游戏的哪些部分在任何情况下都应运行哪些部分仅在游戏处于活动状态时才运行 # 开始游戏主循环 while True:gf.check_events(ai_settings, screen, ship, bullets)if stats.game_active:ship.update()gf.update_bullets(ai_settings, screen, ship, aliens,bullets)gf.update_aliens(ai_settings, stats, screen, ship,aliens, bullets)gf.update_screen(ai_settings, screen, ship, aliens,bullets) 八、记分 1.添加Play按钮 当前这个游戏在玩家运行alien_invasion.py时就开始了。下面让游戏一开始处于非活动状态并提示玩家单击Play按钮来开始游戏。为此在game_stats.py中输入如下代码 def __init__(self, ai_settings):初始化统计信息self.ai_settings ai_settingsself.reset_stats()# 让游戏一开始处于非活动状态self.game_active False def reset_stats(self):--snip-- 1创建Button类 我们创建一个Button类用于创建带标签的实心矩形。将这个类保存为文件button.py import pygame.fontclass Button():def __init__(self, ai_settings, screen, msg): 初始化按钮的属性self.screen screenself.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.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.font它让Pygame能够将文本渲染到屏幕上。Pygame通过将你要显示的字符串渲染为图像来处理文本。我们调用prep_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 方法prep_msg()接受实参self以及要渲染为图像的文本。调用font.render()将存储在msg中的文本转换为图像然后将该图像存储在msg_image中。方法font.render()还接受一个布尔实参该实参指定开启还是关闭反锯齿功能。余下的两个实参分别是文本颜色和背景色。我们启用了反锯齿功能并将文本的背景色设置为按钮的颜色。 我们让文本图像在按钮上居中根据文本图像创建一个rect并将其center属性设置为按钮的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) 我们调用screen.fill()来绘制表示按钮的矩形再调用screen.blit()并向它传递一幅图像以及与该图像相关联的rect对象从而在屏幕上绘制文本图像。 2在屏幕上绘制按钮 --snip-- from game_stats import GameStats from button import Button --snip-- def run_game():--snip--pygame.display.set_caption(Alien Invasion)# 创建Play按钮play_button Button(ai_settings, screen, Play) --snip--# 开始游戏主循环while True:--snip--gf.update_screen(ai_settings, screen, stats, ship, aliens,bullets, play_button)run_game() 接下来修改update_screen()以便在游戏处于非活动状态时显示Play按钮. def update_screen(ai_settings, screen, stats, ship, aliens,bullets,play_button):更新屏幕上的图像并切换到新屏幕--snip--# 如果游戏处于非活动状态就绘制Play按钮if not stats.game_active:play_button.draw_button()# 让最近绘制的屏幕可见pygame.display.flip() 3开始游戏 为在玩家单击Play按钮时开始新游戏需在game_functions.py中添加如下代码以监视与这个按钮相关的鼠标事件 def check_events(ai_settings, screen, stats, play_button, ship,bullets):响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:--snip--elif event.type pygame.MOUSEBUTTONDOWN: mouse_x, mouse_y pygame.mouse.get_pos() check_play_button(stats, play_button, mouse_x,mouse_y)def check_play_button(stats, play_button, mouse_x, mouse_y):在玩家单击Play按钮时开始新游戏if play_button.rect.collidepoint(mouse_x, mouse_y): stats.game_active True 在alien_invasion.py中调用check_events()需要传递另外两个实参——stats和play_button # 开始游戏主循环 while True:gf.check_events(ai_settings, screen, stats, play_button,ship,bullets)--snip-- 4重置游戏 为在玩家每次单击Play按钮时都重置游戏需要重置统计信息、删除现有的外星人和子弹、创建一群新的外星人并让飞船居中如下所示 def check_play_button(ai_settings, screen, stats, play_button,ship, aliens,bullets, mouse_x, mouse_y):在玩家单击Play按钮时开始新游戏if play_button.rect.collidepoint(mouse_x, mouse_y):# 重置游戏统计信息stats.reset_stats() stats.game_active True# 清空外星人列表和子弹列表aliens.empty() bullets.empty()# 创建一群新的外星人并让飞船居中create_fleet(ai_settings, screen, ship, aliens) ship.center_ship() check_events()的定义需要修改调用check_play_button()的代码亦如此 def check_events(ai_settings, screen, stats, play_button, ship,aliens,bullets):响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:--snip--elif event.type pygame.MOUSEBUTTONDOWN:mouse_x, mouse_y pygame.mouse.get_pos()check_play_button(ai_settings, screen, stats,play_button, ship, aliens, bullets, mouse_x, mouse_y) 下面来修改alien_invasion.py中调用check_events()的代码以将实参aliens传递给它 # 开始游戏主循环 while True:gf.check_events(ai_settings, screen, stats, play_button,ship,aliens, bullets)--snip-- 5将Play按钮切换到非活动状态 当前Play按钮存在一个问题那就是即便Play按钮不可见玩家单击其原来所在的区域时游戏依然会作出响应。为修复这个问题可让游戏仅在game_active为False时才开始. def check_play_button(ai_settings, screen, stats, play_button,ship, aliens,bullets,mouse_x, mouse_y):玩家单击Play按钮时开始新游戏button_clicked play_button.rect.collidepoint(mouse_x,mouse_y) if button_clicked and not stats.game_active: #重置游戏统计信息--snip-- 标志button_clicked的值为True或False仅当玩家单击了Play按钮且游戏当前处于非活动状态时游戏才重新开始。 6隐藏光标 我们在游戏处于活动状态时让光标不可见 def check_play_button(ai_settings, screen, stats, play_button,ship, aliens,bullets, mouse_x, mouse_y):在玩家单击Play按钮时开始新游戏button_clicked play_button.rect.collidepoint(mouse_x,mouse_y)if button_clicked and not stats.game_active:# 隐藏光标pygame.mouse.set_visible(False)--snip-- 通过向set_visible()传递False让Pygame在光标位于游戏窗口内时将其隐藏起来。游戏结束后我们将重新显示光标让玩家能够单击Play按钮来开始新游戏。 def ship_hit(ai_settings, screen, stats, ship, aliens, bullets):响应飞船被外星人撞到if stats.ships_left 0:--snip--else:stats.game_active Falsepygame.mouse.set_visible(True) 2.提高等级 1修改速度设置 我们首先重新组织Settings类将游戏设置划分成静态的和动态的两组。对于随着游戏进行而变化的设置我们还确保它们在开始新游戏时被重置。 def __init__(self):初始化游戏的静态设置# 屏幕设置self.screen_width 1200self.screen_height 800self.bg_color (230, 230, 230)# 飞船设置self.ship_limit 3# 子弹设置self.bullet_width 3self.bullet_height 15self.bullet_color 60, 60, 60self.bullets_allowed 3# 外星人设置self.fleet_drop_speed 10# 以什么样的速度加快游戏节奏self.speedup_scale 1.1 self.initialize_dynamic_settings() initialize_dynamic_settings()的代码如下 def initialize_dynamic_settings(self):初始化随游戏进行而变化的设置self.ship_speed_factor 1.5self.bullet_speed_factor 3self.alien_speed_factor 1# fleet_direction为1表示向右为-1表示向左self.fleet_direction 1 每当玩家提高一个等级时我们都使用increase_speed()来提高飞船、子弹和外星人的速度 def increase_speed(self):提高速度设置self.ship_speed_factor * self.speedup_scaleself.bullet_speed_factor * self.speedup_scaleself.alien_speed_factor * self.speedup_scale 在check_bullet_alien_collisions()中我们在整群外星人都被消灭后调用increase_speed()来加快游戏的节奏再创建一群新的外星人 def check_bullet_alien_collisions(ai_settings, screen, ship,aliens, bullets):--snip--if len(aliens) 0:# 删除现有的子弹加快游戏节奏并创建一群新的外星人bullets.empty()ai_settings.increase_speed()create_fleet(ai_settings, screen, ship, aliens) 2重置速度 def check_play_button(ai_settings, screen, stats, play_button,ship, aliens,bullets, mouse_x, mouse_y):在玩家单击Play按钮时开始新游戏button_clicked play_button.rect.collidepoint(mouse_x,mouse_y)if button_clicked and not stats.game_active:# 重置游戏设置ai_settings.initialize_dynamic_settings()# 隐藏光标pygame.mouse.set_visible(False)--snip-- 3.记分 下面来实现一个记分系统以实时地跟踪玩家的得分并显示最高得分、当前等级和余下的飞船数。得分是游戏的一项统计信息因此我们在GameStats中添加一个score属性。 class GameStats():--snip--def reset_stats(self):初始化随游戏进行可能变化的统计信息self.ships_left self.ai_settings.ship_limitself.score 0 为在每次开始游戏时都重置得分我们在reset_stats()而不是__init__()中初始化score。 1显示得分 为在屏幕上显示得分我们首先创建一个新类Scoreboard。就当前而言这个类只显示当前得分但后面我们也将使用它来显示最高得分、等级和余下的飞船数。下面是这个类的前半部分它被保存为文件scoreboard.py import pygame.fontclass Scoreboard():显示得分信息的类def __init__(self, ai_settings, screen, stats): 初始化显示得分涉及的属性self.screen screenself.screen_rect screen.get_rect()self.ai_settings ai_settingsself.stats stats# 显示得分信息时使用的字体设置self.text_color (30, 30, 30) self.font pygame.font.SysFont(None, 48) # 准备初始得分图像self.prep_score() 为将要显示的文本转换为图像我们调用了prep_score() def prep_score(self):将得分转换为一幅渲染的图像score_str str(self.stats.score) self.score_image self.font.render(score_str, True,self.text_color,self.ai_settings.bg_color)# 将得分放在屏幕右上角self.score_rect self.score_image.get_rect() self.score_rect.right self.screen_rect.right - 20 self.score_rect.top 20 最后我们创建方法show_score()用于显示渲染好的得分图像 def show_score(self):在屏幕上显示得分self.screen.blit(self.score_image, self.score_rect) 2创建记分牌 为显示得分我们在alien_invasion.py中创建一个Scoreboard实例 --snip-- from game_stats import GameStats from scoreboard import Scoreboard --snip-- def run_game():--snip--# 创建存储游戏统计信息的实例并创建记分牌stats GameStats(ai_settings)sb Scoreboard(ai_settings, screen, stats) --snip--# 开始游戏主循环while True:--snip--gf.update_screen(ai_settings, screen, stats, sb, ship,aliens, bullets, play_button)run_game() 为显示得分将update_screen()修改成下面这样 def update_screen(ai_settings, screen, stats, sb, ship, aliens,bullets,play_button):--snip--# 显示得分sb.show_score()# 如果游戏处于非活动状态就显示Play按钮if not stats.game_active:play_button.draw_button()# 让最近绘制的屏幕可见pygame.display.flip() 3在外星人被消灭时更新得分 def initialize_dynamic_settings(self):--snip--# 记分self.alien_points 50 在check_bullet_alien_collisions()中每当有外星人被击落时都更新得分 def check_bullet_alien_collisions(ai_settings, screen, stats, sb,ship,aliens, bullets):响应子弹和外星人发生碰撞# 删除发生碰撞的子弹和外星人collisions pygame.sprite.groupcollide(bullets, aliens, True,True)if collisions:stats.score ai_settings.alien_points sb.prep_score()--snip-- 我们需要修改update_bullets()确保在函数之间传递合适的实参 def update_bullets(ai_settings, screen, stats, sb, ship, aliens,bullets):更新子弹的位置并删除已消失的子弹--snip--check_bullet_alien_collisions(ai_settings, screen, stats, sb,ship, aliens, bullets) 我们还需要修改主while循环中调用update_bullets()的代码 # 开始游戏主循环 while True:gf.check_events(ai_settings, screen, stats, play_button,ship,aliens, bullets)if stats.game_active:ship.update()gf.update_bullets(ai_settings, screen, stats, sb,ship, aliens,bullets)--snip-- 4将消灭的每个外星人的点数都计入得分 我们的代码可能遗漏了一些被消灭的外星人。例如如果在一次循环中有两颗子弹射中了外星人或者因子弹更宽而同时击中了多个外星人玩家将只能得到一个被消灭的外星人的点数。 在check_bullet_alien_collisions()中与外星人碰撞的子弹都是字典collisions中的一个键而与每颗子弹相关的值都是一个列表其中包含该子弹撞到的外星人。我们遍历字典collisions确保将消灭的每个外星人的点数都记入得分 def check_bullet_alien_collisions(ai_settings, screen, stats, sb,ship,aliens, bullets):--snip--if collisions:for aliens in collisions.values(): stats.score ai_settings.alien_points * len(aliens)sb.prep_score()--snip-- 5提高点数 玩家每提高一个等级游戏都变得更难因此处于较高的等级时外星人的点数应更高。 class Settings():存储游戏《外星人入侵》的所有设置的类def __init__(self):--snip--# 加快游戏节奏的速度self.speedup_scale 1.1# 外星人点数的提高速度self.score_scale 1.5 self.initialize_dynamic_settings()def increase_speed(self):提高速度设置和外星人点数self.ship_speed_factor * self.speedup_scaleself.bullet_speed_factor * self.speedup_scaleself.alien_speed_factor * self.speedup_scaleself.alien_points int(self.alien_points *self.score_scale) 6将得分圆整 将得分显示为10的整数倍还将设置得分的格式在大数字中添加用逗号表示的千位分隔符。我们在Scoreboard中执行这种修改 def prep_score(self):将得分转换为渲染的图像rounded_score int(round(self.stats.score, -1)) score_str {:,}.format(rounded_score) self.score_image self.font.render(score_str, True,self.text_color, self.ai_settings.bg_color)--snip-- 函数round()通常让小数精确到小数点后多少位其中小数位数是由第二个实参指定的。然而如果将第二个实参指定为负数round()将圆整到最近的10、100、1000等整数倍。使用了一个字符串格式设置指令它让Python将数值转换为字符串时在其中插入逗号。 7最高得分 每个玩家都想超过游戏的最高得分记录。下面来跟踪并显示最高得分给玩家提供要超越的目标。我们将最高得分存储在GameStats中。 def __init__(self, ai_settings):--snip--# 在任何情况下都不应重置最高得分self.high_score 0 下面来修改Scoreboard以显示最高得分。先来修改方法__init__() def __init__(self, ai_settings, screen, stats):--snip--# 准备包含最高得分和当前得分的图像self.prep_score()self.prep_high_score() 方法prep_high_score()的代码如下 def prep_high_score(self):将最高得分转换为渲染的图像high_score int(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.ai_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 show_score(self):在屏幕上显示当前得分和最高得分self.screen.blit(self.score_image, self.score_rect)self.screen.blit(self.high_score_image,self.high_score_rect) 为检查是否诞生了新的最高得分我们在game_functions.py中添加一个新函数check_high_score() def check_high_score(stats, sb):检查是否诞生了新的最高得分if stats.score stats.high_score: stats.high_score stats.scoresb.prep_high_score() 在check_bullet_alien_collisions()中每当有外星人被消灭都需要在更新得分后调用check_high_score() def check_bullet_alien_collisions(ai_settings, screen, stats, sb,ship,aliens, bullets):--snip--if collisions:for aliens in collisions.values():stats.score ai_settings.alien_points * len(aliens)sb.prep_score()check_high_score(stats, sb)--snip-- 8显示等级 为在游戏中显示玩家的等级首先需要在GameStats中添加一个表示当前等级的属性。为确保每次开始新游戏时都重置等级在reset_stats()中初始化它 def reset_stats(self):初始化随游戏进行可能变化的统计信息self.ships_left self.ai_settings.ship_limitself.score 0self.level 1 为让Scoreboard能够在当前得分下方显示当前等级我们在__init__()中调用了一个新方法prep_level() def __init__(self, ai_settings, screen, stats):--snip--# 准备包含得分的初始图像self.prep_score()self.prep_high_score()self.prep_level() prep_level()的代码如下 def prep_level(self):将等级转换为渲染的图像self.level_image self.font.render(str(self.stats.level),True, self.text_color, self.ai_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 我们还需要更新show_score() 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) 我们在check_bullet_alien_collisions()中提高等级并更新等级图像 def check_bullet_alien_collisions(ai_settings, screen, stats, sb,ship,aliens, bullets):--snip--if len(aliens) 0:# 如果整群外星人都被消灭就提高一个等级bullets.empty()ai_settings.increase_speed()# 提高等级stats.level 1 sb.prep_level() create_fleet(ai_settings, screen, ship, aliens) 为确保开始新游戏时更新记分和等级图像在按钮Play被单击时触发重置 def check_play_button(ai_settings, screen, stats, sb, play_button,ship,aliens, bullets, mouse_x, mouse_y):在玩家单击Play按钮时开始新游戏button_clicked play_button.rect.collidepoint(mouse_x,mouse_y)if button_clicked and not stats.game_active:--snip--# 重置游戏统计信息stats.reset_stats()stats.game_active True# 重置记分牌图像sb.prep_score() sb.prep_high_score()sb.prep_level()# 清空外星人列表和子弹列表aliens.empty()bullets.empty()--snip-- 在check_events()中现在需要向check_play_button()传递sb让它能够访问记分牌对象 def check_events(ai_settings, screen, stats, sb, play_button,ship, aliens,bullets):响应按键和鼠标事件for event in pygame.event.get():if event.type pygame.QUIT:--snip--elif event.type pygame.MOUSEBUTTONDOWN:mouse_x, mouse_y pygame.mouse.get_pos()check_play_button(ai_settings, screen, stats, sb,play_button, ship, aliens, bullets, mouse_x, mouse_y) 最后更新alien_invasion.py中调用check_events()的代码也向它传递sb # 开始游戏主循环 while True:gf.check_events(ai_settings, screen, stats, sb,play_button, ship,aliens, bullets)--snip-- 9显示余下的飞船数 首先需要让Ship继承Sprite以便能够创建飞船编组 import pygame from pygame.sprite import Spriteclass Ship(Sprite): def __init__(self, ai_settings, screen):初始化飞船并设置其起始位置super(Ship, self).__init__() --snip-- 接下来需要修改Scoreboard在其中创建一个可供显示的飞船编组。下面是其中的import语句和方法__init__() import pygame.font from pygame.sprite import Group from ship import Shipclass Scoreboard():报告得分信息的类def __init__(self, ai_settings, screen, stats):--snip--self.prep_level()self.prep_ships()--snip-- prep_ships()的代码如下 def prep_ships(self):显示还余下多少艘飞船self.ships Group() for ship_number in range(self.stats.ships_left): ship Ship(self.ai_settings, self.screen)ship.rect.x 10 ship_number * ship.rect.width ship.rect.y 10 self.ships.add(ship) 现在需要在屏幕上绘制飞船了 def show_score(self):--snip--self.screen.blit(self.level_image, self.level_rect)# 绘制飞船self.ships.draw(self.screen) 为在游戏开始时让玩家知道他有多少艘飞船我们在开始新游戏时调用prep_ships()。这是在game_functions.py的check_play_button()中进行的 def check_play_button(ai_settings, screen, stats, sb, play_button,ship,aliens, bullets, mouse_x, mouse_y):在玩家单击Play按钮时开始新游戏button_clicked play_button.rect.collidepoint(mouse_x,mouse_y)if button_clicked and not stats.game_active:--snip--# 重置记分牌图像sb.prep_score()sb.prep_high_score()sb.prep_level()sb.prep_ships()--snip-- 我们还在飞船被外星人撞到时调用prep_ships()从而在玩家损失一艘飞船时更新飞船图像 def update_aliens(ai_settings, screen, stats, sb, ship, aliens,bullets): --snip--# 检测外星人和飞船之间的碰撞if pygame.sprite.spritecollideany(ship, aliens):ship_hit(ai_settings, screen, stats, sb, ship, aliens,bullets) # 检查是否有外星人抵达屏幕底端check_aliens_bottom(ai_settings, screen, stats, sb, ship,aliens, bullets) def ship_hit(ai_settings, screen, stats, sb, ship, aliens,bullets): 响应被外星人撞到的飞船if stats.ships_left 0:# 将ships_left减1stats.ships_left - 1# 更新记分牌sb.prep_ships() # 清空外星人列表和子弹列表--snip-- 在check_aliens_bottom()中需要调用ship_hit()因此对这个函数进行更新 def check_aliens_bottom(ai_settings, screen, stats, sb, ship,aliens,bullets):检查是否有外星人抵达屏幕底端screen_rect screen.get_rect()for alien in aliens.sprites():if alien.rect.bottom screen_rect.bottom:# 像飞船被外星人撞到一样处理ship_hit(ai_settings, screen, stats, sb, ship, aliens,bullets)break 最后在alien_invasion.py中修改调用update_aliens()的代码向它传递实参sb # 开始游戏主循环 while True:--snip--if stats.game_active:ship.update()gf.update_bullets(ai_settings, screen, stats, sb,ship, aliens,bullets)gf.update_aliens(ai_settings, screen, stats, sb, ship,aliens,bullets)--snip-- 九、源码来源 Python编程从入门到实践 (ituring.com.cn)或星途辛某人/pydemo1 - 码云 - 开源中国 (gitee.com)或GitHub - 11xy11/pydemo1
http://www.pierceye.com/news/75411/

相关文章:

  • 用dw做网站怎么给链接怎样做打赏网站
  • 无锡中小企业网站建设东莞网站建设优化东莞
  • 用wordpress建站的好处集团做网站
  • 重庆做模块网站南宁做网站 的
  • 有哪些网站开发公司平面电商设计是什么
  • 怎么在网站上做网页网站建设中期检查表怎么写
  • 网站建设论文题目网站建设与管理基础及实训电子版
  • 企业网站开发实训目的不改域名和空间 只改网站类型
  • 免费建站绑定域名v6厂高仿手表网站
  • 东莞大朗网站建设仗剑苗木推广做哪个网站好
  • 专门做衬衣网站信息网站方案
  • 龙岗 网站建设深圳信科专业做网站制作
  • 网站域名怎么查询dw做网站常用标签
  • 沧县网站制作grace8WordPress主题
  • mvc在网站开发中的应用做网站的宽度为多少钱
  • 萧山网站优化福州网站建设咨询
  • 宿迁城乡建设监督网站wordpress解决大型访问
  • 手机设计软件app推荐天津seo网络营销
  • 当当网网站系统建设的意义wordpress实现文章目录
  • 南昌成都网站建设方案工程建设官方网站
  • 在线网站开发wordpress无插件
  • 门户网站建设模式包括网站群和wordpress 安装插件慢
  • 高密做网站的公司精美的商城网站介绍
  • 企业微网站与手机微信淘宝网的网站设计方案
  • ae免费素材网站梅州做网站设计公司
  • 财务记账网站建设需要摊销吗app开发公司图片
  • 长沙做网站优化的公司h5case 网站
  • 成都网站建设 哪家比较好asp网站打开很慢的原因
  • 江苏扬州建设工程信息网站网站开发需要什么人员
  • wordpress高级设置百度seo系统