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函数,当一轮比赛结束时使用,需要将球棒放回开始位置,将所有属性设置回必要的值。接下来,球棒的移动方式比球的移动方式稍微复杂一些,因为在这里,它的移动很简单(向上/向下),但它依赖于用户告诉它移动,而不是球在每一帧中不停地移动。为了理解球是如何移动的,查看显示事件顺序的快速图表是很有帮助的:

../_images/tom_event-flowchart.png

这里发生的事情是,控制球棒的人按下了将球棒向上移动的键。对于主游戏循环的每次迭代(针对每一帧),如果仍按住该键,则 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