5.用户可控制的对象¶
到目前为止,您可以创建一个PyGame窗口,并渲染一个将在屏幕上飞行的球。下一步是制作一些用户可以控制的蝙蝠。这可能比球简单得多,因为它不需要物理(除非用户控制的对象以比上下移动更复杂的方式移动,例如像马里奥这样的平台角色,在这种情况下,您将需要更多物理知识)。用户可控的对象很容易创建,这要归功于PyGame的事件队列系统,正如您将看到的。
5.1.一个简单的蝙蝠类¶
蝙蝠类背后的原理类似于球类。您需要一个 __init__
函数来初始化球(这样您就可以为每个球棒创建对象实例),则 update
函数在将BAT显示到屏幕之前对BAT执行逐帧更改,以及将定义此类实际操作的函数。以下是一些示例代码::
class Bat(pygame.sprite.Sprite):
"""Movable tennis 'bat' with which one hits the ball
Returns: bat object
Functions: reinit, update, moveup, movedown
Attributes: which, speed"""
def __init__(self, side):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_png("bat.png")
screen = pygame.display.get_surface()
self.area = screen.get_rect()
self.side = side
self.speed = 10
self.state = "still"
self.reinit()
def reinit(self):
self.state = "still"
self.movepos = [0,0]
if self.side == "left":
self.rect.midleft = self.area.midleft
elif self.side == "right":
self.rect.midright = self.area.midright
def update(self):
newpos = self.rect.move(self.movepos)
if self.area.contains(newpos):
self.rect = newpos
pygame.event.pump()
def moveup(self):
self.movepos[1] = self.movepos[1] - (self.speed)
self.state = "moveup"
def movedown(self):
self.movepos[1] = self.movepos[1] + (self.speed)
self.state = "movedown"
如您所见,这个类在结构上与Ball类非常相似。但每种功能的作用都有所不同。首先,有一个RENIT函数,当一轮比赛结束时使用,需要将球棒放回开始位置,将所有属性设置回必要的值。接下来,球棒的移动方式比球的移动方式稍微复杂一些,因为在这里,它的移动很简单(向上/向下),但它依赖于用户告诉它移动,而不是球在每一帧中不停地移动。为了理解球是如何移动的,查看显示事件顺序的快速图表是很有帮助的:

这里发生的事情是,控制球棒的人按下了将球棒向上移动的键。对于主游戏循环的每次迭代(针对每一帧),如果仍按住该键,则 state
属性将设置为“Moving”,并且 moveup
函数,从而使球的y位置减去 speed
属性(在本例中为10)。换句话说,只要按住键,蝙蝠就会每帧在屏幕上向上移动10个像素。这个 state
属性,但如果您正在处理Spin,或者想要一些有用的调试输出,那么了解它是很有用的。
玩家一松开那个键,第二组盒子就会被调用, state
属性将被设置回“静止”,并且 movepos
属性将设置回 [0,0] ,这意味着当 update
函数被调用,它将不再移动球棒。因此,当球员松开钥匙时,球棒就会停止移动。很简单!
5.1.1.转移注意力3:PYGAME事件¶
那么,我们怎么知道玩家什么时候按下键,然后释放键呢?用PYGAME事件队列系统,笨蛋!这是一个非常容易使用和理解的系统,所以这应该不会花很长时间:)您已经在基本的PyGame程序中看到了事件队列的作用,它用于检查用户是否正在退出应用程序。移动蝙蝠的代码就像这样简单::
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN:
if event.key == K_UP:
player.moveup()
if event.key == K_DOWN:
player.movedown()
elif event.type == KEYUP:
if event.key == K_UP or event.key == K_DOWN:
player.movepos = [0,0]
player.state = "still"
这里假设您已经创建了一个BAT的实例,并将该对象命名为 player
。您可以看到熟悉的布局 for
结构,该结构循环访问在PyGame事件队列中找到的每个事件,该事件队列是使用 event.get()
功能。当用户敲击按键、按下鼠标键并移动操纵杆时,这些操作被注入到PyGame事件队列中,并留在那里直到被处理。因此,在主游戏循环的每次迭代中,您都要检查这些事件,检查它们是否是您想要处理的事件,然后适当地处理它们。这个 event.pump()
函数中的 Bat.update
然后,在每次迭代中调用函数以取出旧事件,并使队列保持最新。
首先,我们检查用户是否正在退出程序,如果是,则退出程序。然后我们检查是否有键被按下,如果是,我们检查它们是否是用于上下移动球棒的指定键。如果是,那么我们调用适当的移动函数,并适当地设置播放器状态(尽管状态MoveUp和MoveDown以及在 moveup()
和 movedown()
函数,这使得代码更整洁,并且不会中断 封装 ,这意味着您将属性分配给对象本身,而不引用该对象实例的名称)。请注意,这里有三种状态:静止、向上移动和向下移动。同样,如果您想要调试或计算旋转,这些代码会派上用场。我们还检查是否有任何键被“松开”(即不再被按住),如果它们是正确的键,我们将阻止蝙蝠移动。
Edit on GitHub