当我的玩家精灵从侧面撞到墙精灵时,它会将玩家传送到墙顶

When my player sprite runs into a wall sprite from the side, it teleports the player to the top of the wall

我正在构建一个游戏,并且我有一个玩家 class,但是当它接触到块精灵的 left/right 侧时,它会传送到块的顶部。我不确定如何解决这个问题。我所见过的问题都没有帮助我解决这个问题。

我可以通过

检测碰撞
for entity in blocks:
If self.rect.collidepoint(entity.midleft):
Collide = true

然而,出于某种原因,无论我尝试实现什么代码,它仍然会向上传送玩家。

我很确定这与玩家的速度有关,因为当它撞到墙上时,这些值似乎表现得很奇怪。

玩家class:

class Player(pygame.sprite.Sprite):
  def __init__(self):
    super(Player, self).__init__()
    self.surf = pygame.Surface((40,40))
    self.surf.fill((255,0,0))
    self.rect = self.surf.get_rect()
    self.pos = vec(0,144)
    self.vel = vec(0,0)
    self.acc = vec(0,0)
    
  def move(self, pressed_keys):
    self.acc = vec(0,0.5)
    if pressed_keys[K_LEFT]:
      self.acc.x = -ACC
      
    if pressed_keys[K_RIGHT]:
      self.acc.x = ACC

    
    self.acc.x += self.vel.x * FRIC
    self.vel += self.acc
    self.pos += self.vel + 0.5 * self.acc
    
      

    #if self.pos.x > W:
    #  self.pos.x = W
    #if self.pos.x < 0:
    #  self.pos.x = 0

    self.rect.midbottom = self.pos
  
    
  def checkCollision(self):
    for entity in blocks:
      if self.rect.collidepoint(entity.rect.midleft) or self.rect.collidepoint(entity.rect.midright):
        return True
    return False
  def update(self):
    hits = pygame.sprite.spritecollide(self, blocks, False)

    
    if self.vel.y > 0:
      if hits:
        self.pos.y = hits[0].rect.top + 1
        self.vel.y = 0
    
  def jump(self):
    hits = pygame.sprite.spritecollide(self, blocks, False)
    if hits:
      self.vel.y = -15

块class:


class textureblock(pygame.sprite.Sprite):
  def __init__(self, imagefile, x, y):
    super(textureblock, self).__init__()
    self.imagefile = imagefile
    self.original_image = pygame.image.load(imagefile).convert_alpha()
    self.original_image = pygame.transform.scale(self.original_image, (48,48))
    self.hover_image = self.original_image.copy()
    pygame.draw.rect(self.hover_image, (255, 255, 0), self.hover_image.get_rect(), 6)
    self.image = self.original_image 
    self.rect = self.image.get_rect(center = (x, y))
    self.hover = False
    self.mouse_pos = None
    self.count = 0

  def update(self):
    mouse_pos = pygame.mouse.get_pos()
    self.hover = self.rect.collidepoint(mouse_pos)
    self.image = self.hover_image if self.hover else self.original_image
    if self.hover and mouse_pos == self.mouse_pos:
      self.count += 1
      if self.count > 10:
        self.image = pygame.Surface((48,48))
        self.image.fill((0,191,255))

        item = Item(self.imagefile, self.rect.x, self.rect.y)
        
        items.add(item)
        self.remove(blocks)
        
        
    else:
      self.count = 0
    self.mouse_pos = mouse_pos

主循环:


while running:
  for event in pygame.event.get():
    if event.type == pygame.KEYDOWN:
      if event.key == pygame.K_SPACE:
        player.jump()
      if event.key == pygame.K_ESCAPE:
        running = False
        pygame.quit()

    if event.type == pygame.QUIT:
      running = False
      pygame.quit()


  
  blocks.update()
  blocks.draw(screen)
  
  
  pressed_keys = pygame.key.get_pressed()

  items.update()
  
  player.update()
  player.move(pressed_keys)
  
  update()

  
  pygame.display.update()
  clock.tick(60)
You 

我只需要一些东西来指引我正确的方向!

你必须分别做x轴和y轴的碰撞测试。

首先运行 x 轴的碰撞测试。如果玩家移动到方块中,请将玩家与方块对齐。如果玩家从侧面撞到方块,则必须停止(设置 self.vel.x = 0self.acc.x = 0)。

hit_side = False
for entity in blocks:
    if self.rect.colliderect(entity.rect):

        # move left and hit the block on the right
        if self.vel.x < 0 and self.rect.right > entity.rect.right:
            self.rect.left = entity.rect.right
            hit_side = True

        # move right and hit the block on the left
        if self.vel.x > 0 and self.rect.left < entity.rect.left:
            self.rect.right = entity.rect.left
            hit_side = True

if hit_side:
    self.vel.x = 0
    self.acc.x = 0

之后你可以运行 y轴的碰撞测试:

for entity in blocks:
    if self.rect.colliderect(entity.rect):
        
        # player is falling
        if self.vel.y > 0:
            self.rect.bottom = entity.rect.top

首先沿x轴移动玩家,并沿x轴进行碰撞检测。然后沿 y 轴移动玩家并沿 y 轴破解碰撞。如果玩家与方块发生碰撞,则需要更新 self.rect self.pos.

Class Player

class Player(pygame.sprite.Sprite):
  def __init__(self):
    super(Player, self).__init__()
    # [...]
    
  def move(self, pressed_keys):
    self.acc = vec(0,0.5)
    if pressed_keys[K_LEFT]:
      self.acc.x = -ACC
      
    if pressed_keys[K_RIGHT]:
      self.acc.x = ACC
    
    self.acc.x += self.vel.x * FRIC
    self.vel += self.acc
    self.pos.x += self.vel.x + 0.5 * self.acc.x
    self.rect.midbottom = self.pos

    hit_side = False
    for entity in blocks:
        if self.rect.colliderect(entity.rect):

            # move left and hit the block on the right
            if self.vel.x < 0 and self.rect.right > entity.rect.right:
                self.rect.left = entity.rect.right
                self.pos.x = self.rect.centerx
                hit_side = True

            # move right and hit the block on the left
            if self.vel.x > 0 and self.rect.left < entity.rect.left:
                self.rect.right = entity.rect.left
                self.pos.x = self.rect.centerx
                hit_side = True

    if hit_side:
        self.vel.x = 0
        self.acc.x = 0

  def update(self):

    self.pos.y += self.vel.y + 0.5 * self.acc.y
    self.rect.midbottom = self.pos

    for entity in blocks:
        if self.rect.colliderect(entity.rect):
            if self.vel.y > 0:
                self.rect.bottom = entity.rect.top
                self.pos.y = self.rect.bottom
                self.vel.y = 0

  # [...]

不要忘记调用 player.update():

while running:
  # [...]

  player.move(pressed_keys)
  player.update()
  update()