首页 > 解决方案 > Pygame 垂直碰撞

问题描述

我有一个代码可以让玩家在没有重力的情况下在二维中移动(比如艾萨克或世界最难游戏)。问题是与地图中的瓦片(celle)发生碰撞:

def collisions(self):
    player = self.player.sprite
    for cell in self.celle.sprites():
        if cell.rect.colliderect(player.rect):
            if player.direction.x < 0:
                player.rect.left = cell.rect.right
            elif player.direction.x > 0:
                player.rect.right = cell.rect.left
                
    for cell in self.celle.sprites():
        if cell.rect.colliderect(player.rect):
            if player.direction.y < 0:
                player.rect.top = cell.rect.bottom
            elif player.direction.y > 0:
                player.rect.bottom = cell.rect.top

如果玩家碰撞仅在 x 或 y 中移动,它就可以工作,但是当它垂直移动时,它会传送到另一侧。发生这种情况是因为当它在 ay 侧发生碰撞时,如果它也在 x 中移动,则会触发 x 碰撞算法。所以我尝试使用 bool 来检查 x 或 y 碰撞:

def collisions(self):
    global collx, colly
    player = self.player.sprite
    for cell in self.celle.sprites():
        if cell.rect.colliderect(player.rect):
            if player.direction.x < 0 and colly == False:
                player.rect.left = cell.rect.right
                collx=True
            elif player.direction.x > 0 and colly == False:
                player.rect.right = cell.rect.left
                collx=True
            else:
                collx=False
                
    for cell in self.celle.sprites():
        if cell.rect.colliderect(player.rect):
            if player.direction.y < 0:
                colly=True
                player.rect.top = cell.rect.bottom
            elif player.direction.y > 0:
                colly=True
                player.rect.bottom = cell.rect.top
            else:
                colly=False

它工作得更好,但 False 条件没有正确发生,我认为这是因为代码在 for 循环内,但我真的不知道该怎么做。代码太长而且包含图像,所以我没有发布它。

Player 类中的移动函数:

    def movement(self):
        key_input=pygame.key.get_pressed()
        if key_input[pygame.K_a] or key_input[pygame.K_d]:
            if key_input[pygame.K_a]:
                self.direction.x = -1
                if key_input[pygame.K_w] or key_input[pygame.K_s]:
                    self.rect.x += -self.velx_diag
                else:
                    self.rect.x += -self.velx
            if key_input[pygame.K_d]:
                self.direction.x = 1
                if key_input[pygame.K_w] or key_input[pygame.K_s]:
                    self.rect.x += self.velx_diag
                else:
                    self.rect.x += self.velx
        else:
            self.direction.x = 0

        if key_input[pygame.K_w] or key_input[pygame.K_s]:
            if key_input[pygame.K_w]:
                self.direction.y = -1
                if key_input[pygame.K_a] or key_input[pygame.K_d]:
                    self.rect.y += -self.vely_diag
                else:
                    self.rect.y += -self.vely
            if key_input[pygame.K_s]:
                self.direction.y = 1
                if key_input[pygame.K_a] or key_input[pygame.K_d]:
                    self.rect.y += self.vely_diag
                else:
                    self.rect.y += self.vely
        else:
            self.direction.y = 0

标签: pythonpygame

解决方案


我知道处理 2d 碰撞的最好方法是在一个轴上移动玩家,检查碰撞,然后在另一个轴上移动玩家:

def collision_x(self):
    player = self.player.sprite
    for cell in self.celle.sprites():
        if cell.rect.colliderect(player.rect):
            if player.direction.x < 0:
                player.rect.left = cell.rect.right
            elif player.direction.x > 0:
                player.rect.right = cell.rect.left

# make two different methods for x and y collision.
def collision_y(self):
    for cell in self.celle.sprites():
        if cell.rect.colliderect(player.rect):
            if player.direction.y < 0:
                player.rect.top = cell.rect.bottom
            elif player.direction.y > 0:
                player.rect.bottom = cell.rect.top

然后在移动方法中你需要单独调用它们:
你的移动函数对我来说看起来有点乱,所以我清理了一点(如果你不喜欢它,你也可以使用你的函数,它可以工作正好。)

    def movement(self):
        key_input=pygame.key.get_pressed()
        up = key_input[pygame.K_w]
        down = key_input[pygame.K_s]
        left = key_input[pygame.K_a]
        right = key_input[pygame.K_d]
        y_move = up or down
        x_move = left or right
        if left:
            self.direction.x = -1
            if up or down:
                self.rect.x += -self.velx_diag
            else:
                self.rect.x += -self.velx
        elif right:
                self.direction.x = 1
                if up or down:
                    self.rect.x += self.velx_diag
                else:
                    self.rect.x += self.velx
        else:
            self.direction.x = 0

        # this is the important part
        # check the x collision first
        self.collision_x()

        if up:
            self.direction.y = -1
            if left or right:
                self.rect.y += -self.vely_diag
            else:
                self.rect.y += -self.vely
        elif down:
            self.direction.y = 1
            if left or right:
                self.rect.y += self.vely_diag
            else:
                self.rect.y += self.vely
        else:
            self.direction.y = 0

        # now check for the y collision
        self.collision_y()

推荐阅读