【问题标题】:Player won't move correctly due to gravity force pushing him into the ground由于重力将他推入地面,玩家将无法正确移动
【发布时间】:2020-05-04 17:55:31
【问题描述】:

我正在使用 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

【问题讨论】:

  • 不应该有不同类型的碰撞,在屋顶上,在墙上(在地面上)?
  • 我应该吗?实际上,我正在关注一些关于 YT 的教程系列,似乎他们都使用组来检测碰撞。

标签: python pygame collision-detection


【解决方案1】:

问题是调用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 不为 null,则更新通过屋顶的位置,第二个 if hits: 为 False。

解决方法:只调用一次hits = pg.sprite.spritecollide(self, self.game.walls, False),在所有速度都更新之前不要改变位置。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多