我正在制作一个简单的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
所以这真让我感到困惑,特别是因为块落入的数量不一致。如果有人能给我一个如何解决这个问题的想法,我会非常感激。
最诚挚的问候,
德里克
答案 0 :(得分:0)
如果没有任何调试跟踪,很难诊断,但我有一两个想法。
首先,转储调试轨迹:在每个时间步骤打印显着值:播放器块的位置,碰撞块的位置和适用的速度。这应该会在所涉及对象的每个时间步骤为您提供类似于表的快照。
现在,查看碰撞前最后一个时间步的值。我怀疑你可能会有一个类似于-20的玩家速度,但是在平台上只有10个像素。您的更新逻辑需要处理两个时间步之间的着陆,并将玩家停在平台高度。在我看来,好像玩家可以在整个时间段内摔倒,这会将他的下肢10个像素嵌入平台。
其次,检查您是否正在比较较近的边缘:在这种情况下,玩家的下边缘与平台的上边缘相对应。稍后您将需要处理玩家的右下角接触一个区块的左上角的情况,并且您必须确定玩家是否首先击中该区块的顶部(着陆)或侧(改变水平速度和下降)。
我不会改变计算出的速度;我认为调整最终位置会更容易。您发布的最后一段代码是您已经处理碰撞的特殊情况。检测到碰撞时,获取对象的顶部曲面(y值)。如果它高于播放器底部的当前位置,请将顶部曲面指定为正确的位置。这将使您的玩家坐在碰撞列表中最高对象的顶部。
请注意,只有当您的整个碰撞清单来自下降时,此功能才有效;对于横向碰撞,您需要将列表分开并根据需要调整每个边界。如果在同一时间步骤中有来自多个方面的冲突,这可能会变得复杂 - 例如,当玩家同时击中墙壁和平台时,goombah从左侧猛烈撞击玩家。