Python应用实例(一)外星人入侵(四)

您所在的位置:网站首页 python外星人入侵游戏用鼠标控制吗 Python应用实例(一)外星人入侵(四)

Python应用实例(一)外星人入侵(四)

2024-06-14 12:00| 来源: 网络整理| 查看: 265

外星人入侵(四) 1.前文总结回顾1.1 alien_invasion.py1.2 settings.py1.3 ship.py 2.射击2.1 添加子弹设置2.2 创建Bullet类2.3 将子弹存储到编组中2.4 开火2.5 删除消失的子弹2.6 限制子弹数量2.7 创建方法_update_bullets()

1.前文总结回顾 1.1 alien_invasion.py

主文件alien_invasion.py包含AlienInvasion类。这个类创建一系列贯穿整个游戏都要用到的属性:赋给self.settings的设置,赋给screen中的主显示surface,以及一个飞船实例。这个模块还包含游戏的主循环,即一个调用_check_events()、ship.update()和_update_screen()的while循环。

方法_check_events()检测相关的事件(如按下和松开键盘),并通过调用方法_check_keydown_events()和_check_keyup_events()处理这些事件。当前,这些方法负责管理飞船的移动。AlienInvasion类还包含方法_update_screen(),该方法在每次主循环中重绘屏幕。

要玩游戏《外星人入侵》,只需运行文件alien_invasion.py,其他文件(settings.py和ship.py)包含的代码会被导入这个文件中。

1.2 settings.py

文件settings.py包含Settings类,这个类只包含方法__init__(),用于初始化控制游戏外观和飞船速度的属性。

1.3 ship.py

文件ship.py包含Ship类,这个类包含方法__init__()、管理飞船位置的方法update()和在屏幕上绘制飞船的方法blitme()。表示飞船的图像存储在文件夹images下的文件ship.bmp中。

2.射击

下面来添加射击功能。我们将编写在玩家按空格键时发射子弹(用小矩形表示)的代码。子弹将在屏幕中向上飞行,抵达屏幕上边缘后消失。

2.1 添加子弹设置

首先,更新settings.py,在方法__init__()末尾存储新类Bullet所需的值:

def __init__(self): --snip-- # 子弹设置 self.bullet_speed = 1.0 self.bullet_width = 3 self.bullet_height = 15 self.bullet_color = (60, 60, 60)

这些设置创建宽3像素、高15像素的深灰色子弹。子弹的速度比飞船稍低。

2.2 创建Bullet类

下面来创建存储Bullet类的文件bullet.py,其前半部分如下:

bullet.py

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) ❷ self.rect.midtop = ai_game.ship.rect.midtop # 存储用小数表示的子弹位置。 ❸ self.y = float(self.rect.y)

Bullet类继承了从模块pygame.sprite导入的Sprite类。通过使用精灵(sprite),可将游戏中相关的元素编组,进而同时操作编组中的所有元素。为创建子弹实例,init()需要当前的AlienInvasion实例,我们还调用了super()来继承Sprite。另外,我们还定义了用于存储屏幕以及设置对象和子弹颜色的属性。

在❶处,创建子弹的属性rect。子弹并非基于图像,因此必须使用pygame.Rect()类从头开始创建一个矩形。创建这个类的实例时,必须提供矩形左上角的[插图]坐标和[插图]坐标,以及矩形的宽度和高度。我们在(0, 0)处创建这个矩形,但下一行代码将其移到了正确的位置,因为子弹的初始位置取决于飞船当前的位置。子弹的宽度和高度是从self.settings中获取的。

在❷处,将子弹的rect.midtop设置为飞船的rect.midtop。这样子弹将从飞船顶部出发,看起来像是从飞船中射出的。我们将子弹的[插图]坐标存储为小数值,以便能够微调子弹的速度(见❸)。

下面是bullet.py的第二部分,包括方法update()和draw_bullet():

def update(self): """向上移动子弹。""" #更新表示子弹位置的小数值。 ❶ self.y -= self.settings.bullet_speed # 更新表示子弹的rect的位置。 ❷ self.rect.y = self.y def draw_bullet(self): """在屏幕上绘制子弹。""" ❸ pygame.draw.rect(self.screen, self.color, self.rect)

方法update()管理子弹的位置。发射出去后,子弹向上移动,意味着其[插图]坐标将不断减小。为更新子弹的位置,从self.y中减去settings .bullet_speed的值(见❶)。接下来,将self.rect.y设置为self.y的值(见❷)。

属性bullet_speed让我们能够随着游戏的进行或根据需要提高子弹的速度,以调整游戏的行为。子弹发射后,其[插图]坐标始终不变,因此子弹将沿直线垂直向上飞行。

需要绘制子弹时,我们调用draw_bullet()。draw.rect()函数使用存储在self.color中的颜色填充表示子弹的rect占据的屏幕部分(见❸)。

2.3 将子弹存储到编组中

定义Bullet类和必要的设置后,便可编写代码在玩家每次按空格键时都射出一发子弹了。我们将在AlienInvasion中创建一个编组(group),用于存储所有有效的子弹,以便管理发射出去的所有子弹。这个编组是pygame.sprite.Group类的一个实例。pygame.sprite.Group类似于列表,但提供了有助于开发游戏的额外功能。在主循环中,将使用这个编组在屏幕上绘制子弹以及更新每颗子弹的位置。

首先,在__init__()中创建用于存储子弹的编组:

alien_invasion.py

def __init__(self): --snip-- self.ship = Ship(self) self.bullets = pygame.sprite.Group()

然后在while循环中更新子弹的位置:

def run_game(self): """开始游戏主循环。""" while True: self._check_events() self.ship.update() ❶ self.bullets.update() self._update_screen()

对编组调用update()时(见❶),编组自动对其中的每个精灵调用update()。因此代码行bullets.update()将为编组bullets中的每颗子弹调用bullet.update()。

2.4 开火

在AlienInvasion中,需要修改_check_keydown_events(),以便在玩家按空格键时发射一颗子弹。无须修改_check_keyup_events(),因为玩家松开空格键时什么都不会发生。还需要修改_update_screen(),确保在调用flip()前在屏幕上重绘每颗子弹。

为发射子弹,需要做的工作不少,因此编写一个新方法_fire_bullet()来完成这项任务:

alien_invasion.py

--snip-- from ship import Ship ❶ from bullet import Bullet class AlienInvasion: --snip-- def _check_keydown_events(self, event): --snip-- elif event.key == pygame.K_q: sys.exit() ❷ elif event.key == pygame.K_SPACE: self._fire_bullet() def _check_keyup_events(self, event): --snip-- def _fire_bullet(self): """创建一颗子弹,并将其加入编组bullets中。""" ❸ new_bullet = Bullet(self) ❹ self.bullets.add(new_bullet) def _update_screen(self): """更新屏幕上的图像,并切换到新屏幕。""" self.screen.fill(self.settings.bg_color) self.ship.blitme() ❺ for bullet in self.bullets.sprites(): bullet.draw_bullet() pygame.display.flip() --snip--

首先导入Bullet类(见❶),再在玩家按空格键时调用_fire_bullet()(见❷)。在_fire_bullet()中,创建一个Bullet实例并将其赋给new_bullet(见❸),再使用方法add()将其加入编组bullets中(见❹)。方法add()类似于append(),不过是专门为Pygame编组编写的。

方法bullets.sprites()返回一个列表,其中包含编组bullets中的所有精灵。为在屏幕上绘制发射的所有子弹,遍历编组bullets中的精灵,并对每个精灵调用draw_bullet()(见❺)。

如果此时运行alien_invasion.py,将能够左右移动飞船,并发射任意数量的子弹。子弹在屏幕上向上飞行,抵达屏幕顶部后消失得无影无踪,如图12-3所示。你可在settings.py中修改子弹的尺寸、颜色和速度。

在这里插入图片描述

2.5 删除消失的子弹

当前,子弹在抵达屏幕顶端后消失,但这仅仅是因为Pygame无法在屏幕外面绘制它们。这些子弹实际上依然存在,其[插图]坐标为负数且越来越小。这是个问题,因为它们将继续消耗内存和处理能力。

需要将这些消失的子弹删除,否则游戏所做的无谓工作将越来越多,进而变得越来越慢。为此,需要检测表示子弹的rect的bottom属性是否为零。如果是,则表明子弹已飞过屏幕顶端:

alien_invasion.py

def run_game(self): """开始游戏主循环。""" while True: self._check_events() self.ship.update() self.bullets.update() # 删除消失的子弹。 ❶ for bullet in self.bullets.copy(): ❷ if bullet.rect.bottom


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3