首先,我们要创建一个新的精灵类,叫Enemy,它的格式和前面我们创建的Player差不多。
def update(self):
self.rect.move_ip(-self.speed, 0)
if self.rect.right < 0:
self.kill()
不过Enemy和Player相比有些不同。首先,当我们对surface调用get_rect()方法时,我们将横坐标x设为了820,纵坐标y设为了一个用random.randit()产生的随机数。
Random是python的一个库(library),要使用这个库,需要在文件的开头用import random的命令将其导入。为什么要使用随机数呢?答案很简单:我们想要敌人从屏幕的右边缘出现(横坐标820),但具体出现在哪里会是随机的(纵坐标0-600)。我们还要使用random来给敌人设置一个随机的速度,让敌人有不同的行进速度。
针对敌人使用的update()方法不带参数(因为我们不需要对敌人进行任何操作),这个方法的作用只是将敌人以一定速度移动到屏幕的左边。最后的if表达式用于检测敌人的右边是否超过了屏幕的左边界(这时它们会直接从屏幕中消失)。如果它们超过了屏幕的左边界,我们就调用精灵类的自带方法kill()来把它们从精灵组内删除,这样我们就不需要对这些已经消失的图形进行渲染。
pygame提供的另一个很有用的对象是精灵组。顾名思义,精灵组就是一组精灵。我们接下来要创建一个带有游戏中所有精灵的组,接着把Player加到这个组中(因为到目前为止我们所有的精灵就只有Player)。我们可以为敌人(enemies)创建另一个组。当我们调用精灵的kill()方法时,精灵就会从其所在的组中被移除。
enemies = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
现在我们有了这个叫做all_sprites的组,现在让我们改变一下渲染设置,使得这个组里所有的对象都能被渲染。
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
现在,我们放入all_sprites里的所有东西都会被渲染。
现在我们为敌人设置了一个精灵组,但实际上屏幕上还没有敌人。所以我们要如何让敌人出现在屏幕上呢?我们可以在游戏一开始就创建一堆敌人,但这样的话玩游戏的人就很难撑过前几秒。所以,我们要创建一个自定义事件,这个事件每过几秒钟就会创建一个心的敌人。我们将会对这个事件进行侦听(listen,检测是否发生),就好像我们先前侦听是否有按键(key press)或者退出(quit)的事件发生一样。创建一个自定义事件很简单,只需要使用下面这行代码:
ADDENEMY = pygame.USEREVENT 1
就是这么简单!现在我们有了一个ADDENEMY事件,我们在游戏的主循环中对这个事件进行侦听。唯一需要记住的是,我们的自定义事件有一个独特的值,这个值必须备USEREVENT要大,这就是为什么我们把我们的新时间设为USEREVENT 1。实际上,这些事件本质上就是一些整数常数。USEREVENT有一个数值,而所有我们自定义的事件都需要有一个比USEREVENT大的数值(这是因为所有比USEREVENT大的数值都已经被自带内容所占据了)。
现在,我们要把刚才定义的事件插入到事件队列中。要在游戏的过程中创建这些事件,我们需要一个计时器。PyGame的time()对象可以设置计时器:
pygame.time.set_timer(ADDENEMY, 250)
这行代码告诉PyGame:每250毫秒(0.25秒)激发一次ADDENEMY事件。这行代码在我们游戏的主循环之外,但它仍能在整个游戏的过程中不断被激发。现在,我们需要加入一些代码用于事件侦听:
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
elif(event.type == ADDENEMY):
new_enemy = Enemy()
enemies.add(new_enemy)
all_sprites.add(new_enemy)
小提示
set_timer()只能用于向PyGame的时间队列中插入新事件,没有别的作用。
上面这段代码用于侦听ADDENEMY事件,如果事件被激发,程序将会创建一个新的Enemy类,并把这个新的类加到enemies精灵组中(我们之后将会用精灵组来检测游戏主角与敌人是否碰撞(collision))以及all_sprites组中(这样它就能够和其他东西一起得到渲染)。
我们喜欢用PyGame来写游戏的其中一大原因是,PyGame有很多专门用于碰撞测试的方法,这让原本很难写的碰撞测试代码变得简单许多。在今天的教程中,我们要使用的是spritecollideany。Spritecollideany()方法将一个精灵对象和一个精灵组作为参数,并测验精灵对象是否与精灵组中的任何精灵相触碰。在这里,我们使用player精灵和enemies精灵组来测试游戏主角是否和任何敌人相碰撞,代码如下:
if pygame.sprite.spritecollideany(player, enemies):
player.kill()
上面的代码用于测试player精灵对象是否与enemies精灵组中的精灵相触碰,如果碰到了,我们就用kill()方法把player精灵移除。现在,所有的代码变成了这样:
# 导入pygame
import pygame
# 导入random,用于产生随机数
import random
# 导入pygame.locals
from pygame.locals import *
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.surf = pygame.Surface((75, 25))
self.surf.fill((255, 255, 255))
self.rect = self.surf.get_rect()
def update(self, pressed_keys):
if pressed_keys[K_UP]:
self.rect.move_ip(0, -5)
if pressed_keys[K_DOWN]:
self.rect.move_ip(0, 5)
if pressed_keys[K_LEFT]:
self.rect.move_ip(-5, 0)
if pressed_keys[K_RIGHT]:
self.rect.move_ip(5, 0)
#让player一直在屏幕上出现
if self.rect.left < 0:
self.rect.left = 0
elif self.rect.right > 800:
self.rect.right = 800
if self.rect.top <= 0:
self.rect.top = 0
elif self.rect.bottom >= 600:
self.rect.bottom = 600
def update(self):
self.rect.move_ip(-self.speed, 0)
if self.rect.right < 0:
self.kill()
# 初始化pygame
pygame.init()
# 创建screen对象
# 把它的尺寸定为800 x 600
screen = pygame.display.set_mode((800, 600))
# 创建一个自定义事件用于增加敌人
ADDENEMY = pygame.USEREVENT 1
pygame.time.set_timer(ADDENEMY, 250)
# 创建游戏主角,它现在只是一个矩形
player = Player()
background = pygame.Surface(screen.get_size())
background.fill((0, 0, 0))
enemies = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
elif(event.type == ADDENEMY):
new_enemy = Enemy()
enemies.add(new_enemy)
all_sprites.add(new_enemy)
screen.blit(background, (0, 0))
pressed_keys = pygame.key.get_pressed()
player.update(pressed_keys)
enemies.update()
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
让我们运行一下游戏试试!
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved