针对静态的成角度的矩形障碍物处理精灵碰撞

时间:2020-07-15 23:34:21

标签: python pygame

所以我有一个障碍要让我的精灵与之碰撞,并且它处于一个特定的角度,在这种情况下,我们从x轴的正方向到矩形的顶部进行测量,在这种情况下为333.02相对于x轴的正方向为0度,相对于y轴的方向为63.02度。所以我的问题是,如何设置pygame精灵以正确地与矩形矩形障碍物碰撞? Pygame精灵矩形没有旋转属性(据我所知),由于这种缺乏旋转,我不能只说“嘿,当我的精灵的右角与顶部碰撞时,等等”。我的碰撞对于水平甚至垂直表面都非常有效,但是我始终坚持如何与成角度的障碍物碰撞。

这是我的碰撞代码。它使用向量,并分别检查x和y以查看是否存在任何东西。下面是我要与之碰撞的对象的图片,该对象是在“平铺地图编辑器”中创建的。像我之前提到的,它的角度为333.02度。如果相关,我还提供了该轴的粗略草图。

    def update(self):
        self.animate()
        self.acc = vec(0, PLAYER_MASS * GRAVITY)
        self.move()

        # Equations of Motion
        self.acc.x += self.vel.x * PLAYER_FRICTION
        self.vel += self.acc

        # Collision check in all 4 directions
        self.pos.x += (
            self.vel.x + 0.5 * self.acc.x * self.game.dt
        )  # Update x component (Frame-independent motion)
        if abs(self.vel.x) < PLAYER_VELX_EPSILON:
            self.vel.x = 0

        self.rect.x = self.pos.x
        hits = pg.sprite.spritecollide(self, self.game.platforms, False)
        for hit in hits:  # Horizontal collision
            if self.vel.x > 0:  # Rightward motion
                self.rect.right = hit.rect.left
            elif self.vel.y < 0:  # Leftward motion
                self.rect.left = hit.rect.right
            self.pos.x = self.rect.x  # Update true postion

        self.pos.y += self.vel.y + 0.5 * self.acc.y * self.game.dt  # Update y component
        self.rect.y = self.pos.y + 5

        # This prevents double jumping
        if self.vel.y > 0:
            self.onGnd = False

        hits = pg.sprite.spritecollide(self, self.game.platforms, False)
        for hit in hits:  # Vertical Collision
            if self.vel.y > 0:  # Downward motion
                self.rect.bottom = hit.rect.top
                self.vel.y = 0
                self.onGnd = True
            elif self.vel.y < 0:  # Upward motion
                self.rect.top = hit.rect.bottom
                self.vel.y = 0
            self.pos.y = self.rect.y  # Update true postion

        # Limit Player's movement
        if self.rect.bottom > HEIGHT:
            self.vel.y = 0
            self.rect.bottom = HEIGHT
            self.pos.y = self.rect.y

This is the invisible object in the Tiled Map Editor that I want to collide with so I can go up this slope. The angle says 333.02 with respect to the positive x axis (to the right when facing the screen).

Rough Drawing of the axis and angles associated.

在此问题上的任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

答案是坐标平移。想象一下,旋转的对象有其自己的坐标系,其中x沿矩形的底部延伸,y沿左侧的侧面向上。然后,如果您可以找到该精灵在该坐标系中的位置,则可以按照通常与未旋转矩形的方式检查碰撞,即,如果x> = 0且x <= width且y> = 0且y <=高度,然后发生碰撞。

但是如何获得转换后的坐标?答案是矩阵。您可以使用2D变换矩阵来旋转,缩放和平移向量和坐标。不幸的是,我对这些类型的转换的经验是C#,而不是python,但是例如this page提供了使用numpy的python示例和解释。

请注意,这非常简单,就是2d(和3d)游戏的工作方式-矩阵变换无处不在,并且是旋转,缩放和平移对象进行碰撞检测的 方法。它们也是精灵移动,旋转等的方式:pygame转换模块是矩阵转换模块。因此,如果乍一看代码和说明看起来很吓人,那么值得花时间来理解它,因为如果没有超过一定的点就很难编写游戏。

我知道这不是您所提问题的完整答案,因为我没有给您代码,但是评论太久了,希望可以为您指明正确的方向。 SO上还有this answer,它提供了一些简单的代码。

编辑:仅添加一些进一步的信息,完整的碰撞检测例程将对照对象检查每个可碰撞像素的位置。这可能是您游戏中的必需方法,具体取决于您需要碰撞检测的准确性。这就是我在游戏Magnetar(https://www.youtube.com/watch?v=mbgr2XiIR7w)中所做的事情,该游戏会在任意位置,比例和旋转位置碰撞多个不规则形状的精灵。

但是我注意到,在您的游戏中,如果您所需要的只是带有某些倾斜角度的碰撞检测,那么您可能会“作弊”。那就是说,您可能有一个数据结构,该数据结构记录了地面的“角”(点改变了角度),然后使用简单的几何来确定x,y点是在地面之下还是在地面之上。也就是说,您将获取一个点的x值并检查其在地面的哪一部分上。如果在倾斜地面上,计算出倾斜地面沿x轴的距离,然后使用角度的正弦乘以该值,计算出该位置处的倾斜度y值,如果是大于要检查点的y值,则发生碰撞。

答案 1 :(得分:0)

seesharper的答案可能是正确的方法。我没有经验,但是看起来很有趣,我将必须阅读链接并学习一些有关此方法的知识。不过,在看到他的答案之前,我仍然会立即对这个问题做出回应。

您可以使用pygames mask并屏蔽碰撞检测例程。创建一个具有一定角度的矩形/平台形状的蒙版,并使用这些方法来检测与之碰撞的情况。

如果您向Sprite子类添加self.mask属性,则这些Sprite会在碰撞检测中自动使用该蒙版。