4.游戏对象类

加载模块并编写资源处理函数后,您将需要开始编写一些游戏对象。实现这一点的方法相当简单,尽管乍看起来可能很复杂。您为游戏中的每种对象编写一个类,然后为这些对象创建这些类的实例。然后,您可以使用这些类的方法来操作对象,从而为对象提供一些运动和交互功能。因此,在伪代码中,您的游戏将如下所示::

#!/usr/bin/python

# [load modules here]

# [resource handling functions here]

class Ball:
    # [ball functions (methods) here]
    # [e.g. a function to calculate new position]
    # [and a function to check if it hits the side]

def main:
    # [initiate game environment here]

    # [create new object as instance of ball class]
    ball = Ball()

    while True:
        # [check for user input]

        # [call ball's update function]
        ball.update()

当然,这是一个非常简单的示例,您需要放入所有代码,而不是那些带括号的小注释。但你应该了解基本的想法。您创建了一个类,在其中放入了球的所有函数,包括 __init__ ,这将创建球的所有属性,以及 update ,它会将球移动到它的新位置,然后在这个位置上将它抛到屏幕上。

然后,您可以为所有其他游戏对象创建更多类,然后创建它们的实例,以便可以在 main 函数和主程序循环。与此形成对比的是在 main 函数,然后有许多无类函数来操作Set Ball对象,您将有希望看到为什么使用类是一个优势:它允许您将每个对象的所有代码放在一个位置;它使对象的使用更容易;它使添加新对象和操作它们更灵活。无需为每个新的Ball对象添加更多代码,只需创建 Ball 为每个新的球对象初始化。魔术!

4.1.简单的球类课程

下面是一个简单的类,其中包含创建一个Ball对象所需的函数,如果 update 函数在主循环中调用,在屏幕上移动::

class Ball(pygame.sprite.Sprite):
    """A ball that will move across the screen
    Returns: ball object
    Functions: update, calcnewpos
    Attributes: area, vector"""

    def __init__(self, vector):
        pygame.sprite.Sprite.__init__(self)
        self.image, self.rect = load_png('ball.png')
        screen = pygame.display.get_surface()
        self.area = screen.get_rect()
        self.vector = vector

    def update(self):
        newpos = self.calcnewpos(self.rect,self.vector)
        self.rect = newpos

    def calcnewpos(self,rect,vector):
        (angle,z) = vector
        (dx,dy) = (z*math.cos(angle),z*math.sin(angle))
        return rect.move(dx,dy)

在这里,我们有 Ball 类,并使用 __init__ 设置球的函数,一个 update 函数将球的矩形更改为新位置,并使用 calcnewpos 函数根据球的当前位置和它移动的矢量计算球的新位置。稍后我会解释物理原理。另一件需要注意的事情是文档字符串,这一次它稍微长了一点,它解释了类的基本知识。这些字符串不仅对您自己和其他查看代码的程序员很方便,而且对于分析代码和记录代码的工具也很方便。它们不会在小程序中产生太大影响,但对于大型程序来说,它们是无价的,所以养成这个习惯是一个好习惯。

4.1.1.改道1:精灵

为每个对象创建类的另一个原因是精灵。您在游戏中呈现的每个图像都将是一个精灵对象,因此,首先,每个对象的类都应该继承 Sprite 班级。这是Python类继承的一个非常好的特性。现在 Ball 类具有与 Sprite 类的所有对象实例以及 Ball 类将被PYGAME注册为精灵。在文本和背景不移动的情况下,可以将对象放到背景上,而PyGame以不同的方式处理Sprite对象,当我们查看整个程序的代码时,您将看到这一点。

基本上,您既创建了一个球对象,又为该球创建了一个精灵对象,然后在精灵对象上调用球的更新函数,从而更新精灵。精灵还为您提供了确定两个对象是否发生碰撞的复杂方法。通常,您可能只是签入主循环以查看它们的矩形是否重叠,但这将涉及大量代码,这将是一种浪费,因为 Sprite 类提供两个函数 (spritecollidegroupcollide )为您做这件事。

4.1.2。转移话题2:矢量物理学

而不是 Ball 类,关于这段代码值得注意的是向量物理,用于计算球的运动。对于任何涉及角度移动的游戏,除非您熟悉三角学,否则您不会走得很远,所以我只介绍您需要了解的基本知识,以理解 calcnewpos 功能。

首先,您会注意到球有一个属性 vector ,它由以下部分组成 anglez 。角度是以弧度为单位测量的,它将给出球移动的方向。Z是球移动的速度。因此,通过使用这个矢量,我们可以确定球的方向和速度,从而确定它在x轴和y轴上的移动量:

../_images/tom_radians.png

上图说明了矢量背后的基本数学运算。在左手图中,您可以看到球的投影运动由蓝线表示。这条线的长度(Z)代表它的速度,角度是它将移动的方向。球的移动角度将始终从右侧的x轴开始测量,并从该线顺时针测量,如图所示。

从球的角度和速度,我们就可以算出它沿x轴和y轴移动了多少。我们需要这样做,因为PyGame本身不支持向量,我们只能通过沿两个轴移动球的矩形来移动球。所以我们需要 resolve 在x轴(Dx)和y轴(Dy)上运动的角度和速度。这是一个简单的三角学问题,可以用图中所示的公式来完成。

如果你以前学过初等三角学,这些对你来说都不是什么新鲜事。但是,如果你健忘,这里有一些有用的公式需要记住,它们将帮助你可视化角度(我发现以度为单位的角度比以弧度为单位更容易可视化!)

../_images/tom_formulae.png



Edit on GitHub