Python 玩家赢了';由于重力把他推到地上,他不能正确移动

Python 玩家赢了';由于重力把他推到地上,他不能正确移动,python,pygame,collision-detection,Python,Pygame,Collision Detection,我用pygame ad制作了一个tilemap平台,我为玩家定义了X和Y方向的运动,也定义了一个Y方向的力,代表重力,使其正确跳跃。然而,当我的玩家从地上摔下来,游戏开始时,由于重力不断地将他推到下方,它无法正确地向右或向左移动。除此之外,当玩家跳跃时,我将其移动到右侧,就好像它无法识别与墙的底部矩形的碰撞(请参见下面的gif以获得视觉解释) 我试着在玩家触地时禁用重力,在玩家跳跃时启用重力,但它没有按预期工作,而且我在管理碰撞时遇到了问题(同样,禁用重力也没有意义,对吧?) 这是我的玩家课程

我用pygame ad制作了一个tilemap平台,我为玩家定义了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
职业玩家(pg.sprite.sprite):
定义初始化(self,game,x,y):
self.groups=game.sprite
pg.sprite.sprite.\uuuu init\uuuu(self,self.groups)
self.game=游戏
self.image=pg.Surface((瓷砖大小,瓷砖大小))
self.image.fill(绿色)
self.rect=self.image.get_rect()
self.move\u left=self.move\u right=False
self.pos=pg.math.Vector2(x,y)
self.acc=pg.math.Vector2(0,重力)
self.vel=pg.math.Vector2(0,0)
def跳转(自):
自我水平y-=3
def更新(自我):
self.vel.x=0
如果self.move_向左移动:
self.vel.x=-玩家速度
如果self.move_向右移动:
self.vel.x=玩家速度
self.vel+=self.acc
self.pos+=self.vel
self.rect.x=self.pos.x*波浪大小
self.rect.y=self.pos.y*瓷砖大小
如果自身水平y>0.5:
自身水平y=0.5
hits=pg.sprite.spritecollide(self,self.game.walls,False)
如果点击:
如果self.vel.x>0:
self.pos-=self.vel
self.rect.right=点击[0]。rect.left
self.vel.x=0
如果自身水平x<0:
self.pos-=self.vel
self.rect.left=点击[0]。rect.right
self.vel.x=0
hits=pg.sprite.spritecollide(self,self.game.walls,False)
如果点击:
如果自身水平y>0:
self.pos-=self.vel
self.rect.bottom=点击[0]。rect.top
自我水平y=0
如果自身水平y<0:
self.pos-=self.vel
self.rect.top=点击[0]。rect.bottom
自我水平y=0

问题是调用
spritecollide
两次,同时更新位置:

hits=pg.sprite.spritecollide(self,self.game.walls,False)
如果点击:
#如果其中一个条件为真,则位置将更新,
#继续先前的速度,即穿过屋顶。
如果self.vel.x>0:
self.pos-=self.vel
# [...]
如果自身水平x<0:
self.pos-=self.vel
# [...]
#穿过屋顶后,就不会再有碰撞了。。。
hits=pg.sprite.spritecollide(self,self.game.walls,False)
如果点击:
如果自身水平y>0:
self.pos-=self.vel
# [...]
自我水平y=0
两种情况,当前代码为:

  • 如果您在没有x-speed的情况下跳跃,则不会更新位置(也称为穿过屋顶)。因此,第二次调用spritecollide会返回一个非空的
    hits
    ,您将在屋顶上弹跳
  • 如果x-speed为非空,则更新穿过车顶的位置,如果hits:第二个
    为假

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

问题是调用
spritecollide
两次,同时更新位置:

hits=pg.sprite.spritecollide(self,self.game.walls,False)
如果点击:
#如果其中一个条件为真,则位置将更新,
#继续先前的速度,即穿过屋顶。
如果self.vel.x>0:
self.pos-=self.vel
# [...]
如果自身水平x<0:
self.pos-=self.vel
# [...]
#穿过屋顶后,就不会再有碰撞了。。。
hits=pg.sprite.spritecollide(self,self.game.walls,False)
如果点击:
如果自身水平y>0:
self.pos-=self.vel
# [...]
自我水平y=0
两种情况,当前代码为:

  • 如果您在没有x-speed的情况下跳跃,则不会更新位置(也称为穿过屋顶)。因此,第二次调用spritecollide会返回一个非空的
    hits
    ,您将在屋顶上弹跳
  • 如果x-speed为非空,则更新穿过车顶的位置,如果hits:第二个
    为假

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

你不应该在屋顶、墙壁(地面)上有不同类型的碰撞吗?我应该吗?实际上,我正在关注一些关于YT的教程系列,它们似乎都使用组来检测碰撞。你不应该有不同类型的碰撞,在屋顶上,在墙上(,在地面上)?我应该吗?实际上,我正在关注一些关于YT的教程系列,它们似乎都使用组来检测冲突。正如您所看到的,我更改了代码,但现在似乎无法识别任何冲突。秘密解决方案