Pygame 碰撞检测后停止移动

5

我想使用pygame创建一个“实体”物体。目标是当玩家与物体接触时,将其推开。目前我正在使用以下代码(但无法正常工作):

keys_pressed = pygame.key.get_pressed()
if 1 in keys_pressed:
    if keys_pressed[K_w]:
        self.player_l[1] += -2
        if self.player_r.colliderect(self.tower_r): self.player_l[1] -= -2
    if keys_pressed[K_a]:
        self.player_l[0] += -2
        if self.player_r.colliderect(self.tower_r): self.player_l[0] -= -2
    if keys_pressed[K_s]:
        self.player_l[1] += 2
        if self.player_r.colliderect(self.tower_r): self.player_l[1] -= 2
    if keys_pressed[K_d]:
        self.player_l[0] += 2
        if self.player_r.colliderect(self.tower_r): self.player_l[0] -= 2

这个问题在于,即使玩家回到了与碰撞发生前相同的位置,玩家矩形仍然会被"卡住"在塔状物的内部,导致碰撞不断触发。一旦玩家接触了塔状物,就无法在任何方向上移动。


你能展示一下该方法的完整代码吗?这可能是一个打字错误。 - Patashu
添加了整个移动代码 :) - Dan Doe
1
一个想法是,如果您使用浮点数进行定位,舍入误差可能意味着您不会完全被推出,就像您推入的那样。您是否尝试过使用调试器、打印语句或日志来跟踪位置随时间的变化? - Patashu
哦,太感谢了,我设法修复它,确保它四舍五入! - Dan Doe
1个回答

3
我在我的pygame游戏中也做过同样的事情。您需要创建一个所有对象都将使用的移动函数。这使得不可能穿过被称为everything的渲染更新组中的任何精灵。如果精灵不是everything的一部分,它将不会发生碰撞。以下是该函数。这将为碰撞创建一定数量的阻力。基本上,在推动物体时,它会推回一定量。任何没有调用移动函数的物体即使被推动也不会移动,因此只有能够移动的物体才能被推动,而像墙壁之类的东西在推动它们时不会在棋盘上滑动。
    def moveRelative(self,other,speed):                                   #This function is a function the one you need uses, which you may find useful. It is designed to move towards or a way from another sprite. Other is the other sprite, speed is an integer, where a negative value specifies moving away from the sprite, which is how many pixels it will move away from the target. This returns coordinates for the move_ip function to move to or away from the sprite, as a tuple
            dx = other.rect.x - self.rect.x
            dy = other.rect.y - self.rect.y
            if abs(dx) > abs(dy):
                    # other is farther away in x than in y
                    if dx > 0:
                            return (+speed,0)
                    else:
                            return (-speed,0)
            else:
                    if dy > 0:
                            return (0,+speed)
                    else:
                            return (0,-speed)

    def move(self,dx,dy):
            screen.fill((COLOR),self.rect)                                 #covers over the sprite's rectangle with the background color, a constant in the program
            collisions = pygame.sprite.spritecollide(self, everything, False)
            for other in collisions:
                    if other != self:
                            (awayDx,awayDy) = self.moveRelative(other,-1)  #moves away from the object it is colliding with
                            dx = dx + 9*(awayDx)                           #the number 9 here represents the object's resistance. When you push on an object, it will push with a force of nine back. If you make it too low, players can walk right through other objects. If you make it too high, players will bounce back from other objects violently upon contact. In this, if a player moves in a direction faster than a speed of nine, they will push through the other object (or simply push the other object back if they are also in motion)
                            dy = dy + 9*(awayDy)
            self.rect.move_ip(dx,dy)                                       #this finally implements the movement, with the new calculations being used

这是一些代码,你可能需要根据自己的需求进行修改,但这是一个相当不错的方法。如果你想消除反弹功能,你可以考虑将任何朝着这个对象的移动速度设置为零,只允许远离它的移动速度。然而,我发现反弹功能对于我的游戏更加有用和准确。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接