代码之家  ›  专栏  ›  技术社区  ›  Derek Zhang

Pygame spritecollide系列产品

  •  0
  • Derek Zhang  · 技术社区  · 8 年前

    我正在制作一个简单的2D平台编辑器,但我的精灵的接线盒有些问题。我使用pygame.sprite。spritecollide函数生成触摸我的播放器sprite的块(平台)列表。

    这是我的玩家等级:

    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

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

    谨致问候,

    德里克

    1 回复  |  直到 8 年前
        1
  •  0
  •   Prune    8 年前

    没有它很难诊断 任何 调试跟踪,但我有一两个主意。

    首先,转储调试跟踪:打印每个时间步的显著值:播放器块的位置、碰撞块的位置和适用的速度。这将在所涉及对象的每个时间步为您提供一个类似于表的快照。

    现在,查看碰撞前最后一个时间步中的值。我怀疑你的速度大概是-20,但在低于10像素的平台上着陆。您的更新逻辑需要处理两个时间点之间的着陆,并将播放器停在平台高度。在我看来,球员似乎被允许在整个时间步长内跌倒,这将把他柔嫩的下肢嵌入平台10像素。

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


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

    请注意,只有当您的整个碰撞列表不会掉落时,此操作才有效;对于横向碰撞,还需要分隔列表并根据需要调整每个边界。如果在同一时间步长上有来自多个侧面的碰撞,这可能会变得复杂。例如,当玩家撞到墙和平台时,一个恶棍从左侧猛击玩家。