Pygame spritecollide hitboxes

时间:2016-07-14 23:37:12

标签: python pygame collision-detection platform

我正在制作一个简单的2D平台游戏,但是我的精灵的命中箱遇到了一些麻烦。我使用pygame.sprite.spritecollide函数生成一个触摸我的播放器精灵的块(平台)列表。

这是我的玩家类:

class Player( pygame.sprite.Sprite ):

     def __init__(self,x,y,image):

        super( Player, self ).__init__()

        self.vel_x = 0
        self.vel_y = 0
        self.moveSpeed = 3
        self.jumpPower = 7

        self.direction = idle
        self.grounded = False
        self.falling = True
        self.jumping = False
        self.climbing = False

        self.image = pygame.Surface((50,50))#pygame.transform.scale( image, (50,50))
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.width = 50
        self.height = 50
        self.rect.bottom = self.rect.y + self.height

    def set_position( self,x,y ):

        self.rect.x = x
        self.rect.y = y

    def experience_gravity(self, gravity = 0.3):

        if not self.grounded:
            self.vel_y += gravity
            self.falling = True
        else:
            self.vel_y = 0
            self.grounded = True
            self.falling = False

    def jump(self):

        self.grounded = False
        self.vel_y -= self.jumpPower

    def update(self, collidable = pygame.sprite.Group() ):

        global collision

        self.experience_gravity()

        self.rect.x += self.vel_x
        self.rect.y += self.vel_y

        collision_list = pygame.sprite.spritecollide( self, collidable, False )

        for p in collision_list:
            if ( self.vel_y > 0 ):
                self.vel_y = 0
                self.grounded = True

在我的更新方法中,我检查保存所有平台(参数可碰撞)的精灵组与播放器之间的冲突。

这是我的街区类:

class Block( pygame.sprite.Sprite ):

    def __init__( self, x, y, width, height):

        super( Block, self ).__init__()
        self.image = pygame.Surface( ( width, height ) )
        self.image.fill( black )

        self.rect = self.image.get_rect()

        self.type = platform

        self.rect.x = x
        self.rect.y = y
        self.width = width
        self.height = height

相当不言自明的块类。我的其余代码是更新并将所有内容blit到白色背景上。我遇到的问题是,当玩家登陆平台时,它只会在已经在平台上时停止下降(变为接地)。甚至更奇怪的是,该块沉入其平台的深度并不一致。有时它会落在10像素,其他的20像素。这是播放器卡住的屏幕截图:

The player block is stuck inside the platform block

所以这真让我感到困惑,特别是因为块落入的数量不一致。如果有人能给我一个如何解决这个问题的想法,我会非常感激。

最诚挚的问候,

德里克

1 个答案:

答案 0 :(得分:0)

如果没有任何调试跟踪,很难诊断,但我有一两个想法。

首先,转储调试轨迹:在每个时间步骤打印显着值:播放器块的位置,碰撞块的位置和适用的速度。这应该会在所涉及对象的每个时间步骤为您提供类似于表的快照。

现在,查看碰撞前最后一个时间步的值。我怀疑你可能会有一个类似于-20的玩家速度,但是在平台上只有10个像素。您的更新逻辑需要处理两个时间步之间的着陆,并将玩家停在平台高度。在我看来,好像玩家可以在整个时间段内摔倒,这会将他的下肢10个像素嵌入平台。

其次,检查您是否正在比较较近的边缘:在这种情况下,玩家的下边缘与平台的上边缘相对应。稍后您将需要处理玩家的右下角接触一个区块的左上角的情况,并且您必须确定玩家是否首先击中该区块的顶部(着陆)或侧(改变水平速度和下降)。

我不会改变计算出的速度;我认为调整最终位置会更容易。您发布的最后一段代码是您已经处理碰撞的特殊情况。检测到碰撞时,获取对象的顶部曲面(y值)。如果它高于播放器底部的当前位置,请将顶部曲面指定为正确的位置。这将使您的玩家坐在碰撞列表中最高对象的顶部。

请注意,只有当您的整个碰撞清单来自下降时,此功能才有效;对于横向碰撞,您需要将列表分开并根据需要调整每个边界。如果在同一时间步骤中有来自多个方面的冲突,这可能会变得复杂 - 例如,当玩家同时击中墙壁和平台时,goombah从左侧猛烈撞击玩家。