python - 由于重力将他推入地面,玩家将无法正确移动
问题描述
我正在制作一个带有 pygame 广告的 tilemap 平台游戏,我定义了玩家的 X 和 Y 运动,以及一个代表重力的 Y 力,以使其正确跳跃。但是,当我的玩家掉到地上并开始游戏时,由于不断将他向下推的重力,它不能正确地向右或向左移动。除此之外,当玩家跳跃并且我将其向右移动时,就好像它无法识别与墙壁底部矩形的碰撞(请参阅下面的 gif 以获得对此的视觉解释)。
我尝试在玩家撞击地面时禁用重力,并在玩家跳跃时启用它,但它没有按预期工作,而且我在管理碰撞时遇到了问题(另外,禁用重力也没有意义,对吧? )
这是我的 Player 类:
class Player(pg.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.sprites
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.image = pg.Surface((TILESIZE, TILESIZE))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.move_left = self.move_right = False
self.pos = pg.math.Vector2(x, y)
self.acc = pg.math.Vector2(0, GRAVITY)
self.vel = pg.math.Vector2(0, 0)
def jump(self):
self.vel.y -= 3
def update(self):
self.vel.x = 0
if self.move_left:
self.vel.x = -PLAYER_SPEED
if self.move_right:
self.vel.x = PLAYER_SPEED
self.vel += self.acc
self.pos += self.vel
self.rect.x = self.pos.x * TILESIZE
self.rect.y = self.pos.y * TILESIZE
if self.vel.y > 0.5:
self.vel.y = 0.5
hits = pg.sprite.spritecollide(self, self.game.walls, False)
if hits:
if self.vel.x > 0:
self.pos -= self.vel
self.rect.right = hits[0].rect.left
self.vel.x = 0
if self.vel.x < 0:
self.pos -= self.vel
self.rect.left = hits[0].rect.right
self.vel.x = 0
hits = pg.sprite.spritecollide(self, self.game.walls, False)
if hits:
if self.vel.y > 0:
self.pos -= self.vel
self.rect.bottom = hits[0].rect.top
self.vel.y = 0
if self.vel.y < 0:
self.pos -= self.vel
self.rect.top = hits[0].rect.bottom
self.vel.y = 0
解决方案
问题是调用spritecollide
两次,并结合更新位置:
hits = pg.sprite.spritecollide(self, self.game.walls, False)
if hits:
# If one of these conditions are true, the position will be updated,
# continuing the previous velocity, i.e. going through the roof.
if self.vel.x > 0:
self.pos -= self.vel
# [...]
if self.vel.x < 0:
self.pos -= self.vel
# [...]
# After you go through the roof, there's no more collision...
hits = pg.sprite.spritecollide(self, self.game.walls, False)
if hits:
if self.vel.y > 0:
self.pos -= self.vel
# [...]
self.vel.y = 0
两种情况,使用当前代码:
- 如果您在没有 x 速度的情况下跳跃,则不会更新位置(也就是穿过屋顶)。所以第二次调用
spritecollide
确实返回一个非空的hits
,你会在屋顶上反弹。 - 如果 x-speed 不为空,则更新通过屋顶的位置,第二个
if hits:
为 False。
解决方法:只调用hits = pg.sprite.spritecollide(self, self.game.walls, False)
一次,在所有速度都更新之前不要改变位置。
推荐阅读
- discord - Discord.js 机器人回复所有命令
- r - 是否有将列中的值扩展到 NA 位置的函数?[R]
- html - 引导输入组无法正常工作
- power-automate - 私人频道中 Excel 文件的流程
- css - 在表格上设置宽度时如何在列之间平均分配额外的空间
- php - PHP:如何从非文件的数据中下载部分内容。EG 数据存储在从 AWS S3 存储桶中提取的变量中
- arrays - Excel:根据达到的阈值并匹配字符串来更改单元格的颜色
- reactjs - API 路由中的无效挂钩调用
- c++ - 用于计算数组中元素频率的代码不起作用
- javascript - 多个范围输入(滑块)的值不会改变