当前位置: 首页 > 知识库问答 >
问题:

由于重力将球员推入地面,球员无法正确移动

易成天
2023-03-14

我正在制作一个带有pygame广告的平铺地图平台游戏,我为玩家定义了X和Y运动,以及一个代表重力的Y力,以使其正确跳跃。然而,当我的玩家摔倒在地上并且游戏开始时,由于重力不断将他推向下方,它既不能向右移动也不能向左移动。除此之外,当玩家跳跃并且我将其向右移动时,就像它无法识别与墙壁底部的碰撞一样(请参阅下面的gif以获取视觉解释)。

我尝试在玩家落地时禁用重力,在玩家跳跃时启用重力,但它没有按预期工作,我在管理碰撞方面也遇到了问题(同样,禁用重力也没有意义,对吧?)

这是我的玩家类:

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

共有1个答案

严兴言
2023-03-14

问题是调用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会返回一个非空点击
  • 如果x速度为非空,则更新穿过屋顶的位置,如果命中,则第二个为False

解决方案:调用命中=pg.sprite.spritecollide(Self,self.game.walls, False)仅一次,并且在所有速度更新之前不要更改位置。

 类似资料:
  • 我的游戏循环中有以下代码: 它做它应该做的事情:当你按下A时,它逆时针转动。按D键时,它会顺时针转动。当你按W时,它向前,当你按S时,它向后。然而,如果我拿着W和D,一开始它会像应该的那样绕一个圈,但它会慢慢地开始向左上角的方向移动。我该怎么解决这个问题?

  • 是否可以在使用官方映像运行到泊坞站容器中的独立 Web Sphere Liberty 服务器上启用“部署”选项?当我登录到管理员中心时,我只能看到这个选项:

  • 嗨,我正在做一个游戏,我有一个问题。当球员落地时,他会稍微地下一点,例如: 我想要这样的东西: 这是我的重力代码: 谢谢

  • 三维地球支持的功能包括:新建三维地球、添加图层、绘制要素、执行分析、保存场景。 新建三维地球 您可以在应用中心中点击三维地球,在弹出页面中点击“立即体验”。您也可以依次点击“资源中心”,“场景”,“创建场景”打开三维地球。 在资源中心中,可以查看或编辑您保存的场景。 添加图层 点击左上角工具栏添加按钮即可添加图层。 您可以使用我们为您提供的公有数据服务,也可以在自定义服务中使用您在云存储中上传并发

  • 通常只有Y轴运动在这样的游戏中可用,但我决定让它在这样一种方式,X轴桨运动也被允许。 起初,我认为这与像素有关,但我也尝试了多种方式改变桨碰撞,但没有任何积极的结果。无论我试了多少次,球都不会从桨上弹下来。 代码非常简单,我每次只移动1px: 为了移动桨叶,我使用简单的标志,在按键时将移动方向设置为“开”,在按键释放时设置为“关”。我在不定式循环中运行它,所以它不断地被执行。 这就是“run()”

  • 我正在将现有应用程序从Akka Classic移植到Akka Typed。最初,您可以使用上下文获取对参与者的引用。actorSelection()。resolveOne() 我知道在Akka Type中不再支持这一点,我们应该使用来注册演员以供发现。 但是,我只想将消息发送到本地参与者,即存在于集群中每个节点上的本地单例。我有它的本地路径,但没有对它的直接引用。这是因为它是由Akka管理系统创建