【问题标题】:Pygame spritecollide hitboxesPygame spritecollide 碰撞箱
【发布时间】:2016-07-14 23:37:12
【问题描述】:

我正在开发一个简单的 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

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

The player block is stuck inside the platform block

所以这真的让我很困惑,特别是因为块落入的数量是不一致的。如果有人能告诉我如何解决这个问题,我将不胜感激。

致以最诚挚的问候,

德里克

【问题讨论】:

    标签: python pygame collision-detection platform


    【解决方案1】:

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

    首先,转储调试跟踪:打印每个时间步的显着值:玩家块的位置、碰撞块的位置和适用的速度。这应该会在所涉及对象的每个时间步为您提供一个类似表格的快照。

    现在,查看碰撞前最后一个时间步的值。我怀疑您的玩家速度可能为 -20,但降落在仅低于 10 像素的平台上。您的更新逻辑需要处理两个时间步之间的着陆,并将玩家停在平台高度。在我看来,玩家似乎可以在整个时间步内跌倒,这会将他柔软的下肢嵌入平台 10 像素。

    其次,检查您是否在比较较近的边缘:在本例中,是玩家的下边缘与平台的上边缘。稍后您将需要处理玩家的右下角接触块的左上角的情况,并且您必须确定玩家是首先击中块的顶部(着陆)还是侧面(改变水平速度和下降) .


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

    请注意,这仅在您的整个碰撞列表未掉落时才有效;对于横向碰撞,您需要分开列表并根据需要调整每个边界。如果在同一时间步内有多个侧面的碰撞,这可能会变得复杂 - 例如,当玩家同时撞到墙壁和平台时,goombah 从左侧猛击玩家。

    【讨论】:

    • 所以我转储了一个调试跟踪,似乎正在发生的事情是你所说的关于播放器的速度。它距离块仅 4 个像素,但它的速度为 9,因此它向块中传输 5 个像素。我不确定如何处理代码,以便它在撞击块的那一刻将速度更改为 0,或者调整速度以以 0 的速度降落在块上。有什么想法吗?提前致谢
    • 好的,所以我这样做是为了当玩家与平台碰撞时,我将玩家 rect.bottom 设置为平台的 rect.top。然后发生的事情是两个精灵显然没有碰撞。为了解决这个问题,我将玩家 rect.bottom 设置为平台的 rect.top 加上 1 个额外像素,以确保两个精灵发生碰撞。感谢您的想法!对此,我真的非常感激。 :D
    • 很高兴能提供帮助。请记住“接受”答案,以便 SO 可以正确存档问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多