试图使用碰撞检测pygame防止玩家职业落入地面职业



到目前为止,我有一个播放器类,每次更新方法都有重力作用,现在我所有的重力方法所做的就是检查玩家是否与地面碰撞,如果没有碰撞,那么玩家 yVel += 1,但永远不会超过 13(每帧永远不会超过 13 像素),但问题是如果我的播放器正好在地面上方并掉落 (13)在地面上,他被困在地面中间,无法跳出来。有什么方法可以解决这个问题,还是需要完全重写播放器类中的所有内容?

    import pygame
import time  # lint:ok
from pygame.locals import *
char = 'ball.png'
char_jump = 'ball_jump.png'
ball = pygame.image.load(char)
ballJump = pygame.image.load(char_jump)

class Player(pygame.sprite.Sprite):
    def __init__(self, screen, image, xPos, yPos, xVel, yVel, checkGroup):
        pygame.sprite.Sprite.__init__(self)
        self.xPos = xPos
        self.yPos = yPos
        self.xVel = xVel
        self.yVel = yVel
        self.image = image
        self.screen = screen
        self.rect = self.image.get_rect()
        self.isInAir = True
        self.checkGroup = checkGroup
    def draw(self, screen):
        screen.blit(self.image, self.rect)
    def update(self):
        self.gravity()
        self.xPos += self.xVel  # updates x and y based on velocities
        self.yPos += self.yVel  # updates rect
        self.rect.topleft = (self.xPos, self.yPos)  # updates sprite rectangle
        if self.xPos > 440:  # keeps player from going to far right and left
            self.xPos = 440
        if self.xPos < -3:  # #########
            self.xPos = -3
    def gravity(self):
        if self.checkCollision(self.checkGroup) is True:
            self.yVel = 0
        elif self.checkCollision(self.checkGroup) is False:
            self.yVel = 50
    def jump(self):
        if self.isInAir is False:
            print('jump')
            self.yVel -= 20
            self.image = ballJump
    def moveRight(self):
        self.xVel = 3
    def moveLeft(self):
        self.xVel = -3
    def stopLeft(self):
        self.xVel = 0
        self.image = ball
    def stopRight(self):
        self.xVel = 0
        self.image = ball
    def stopJump(self):
        self.image = ball
        if self.yVel < 0:  # if player is still jumping up
            self.yVel = 1  # make y Velocity positive (fall down)
    def checkCollision(self, group):
        if pygame.sprite.spritecollideany(self, group):
            return True
        elif not pygame.sprite.spritecollideany(self, group):
            return False

首先,您的碰撞检查是多余的:

def checkCollision(self, group):
    if pygame.sprite.spritecollideany(self, group):
        return True
    elif not pygame.sprite.spritecollideany(self, group):
        return False

如果没有冲突,则调用spritecollideany两次。你可以只使用:

def checkCollision(self, group):
    return pygame.sprite.spritecollideany(self, group)

def gravity(self):
    if self.checkCollision(self.checkGroup) is True:
        self.yVel = 0
    elif self.checkCollision(self.checkGroup) is False:
        self.yVel = 50

它可以重写为

def gravity(self):
    self.yVel = 0 if self.checkCollision(self.checkGroup) else 50

现在谈谈你的问题:

你检查你的玩家是否与某物碰撞,如果是,你就停止移动。这导致了您描述的问题,因为您不会检查移动的每个像素的碰撞,而只会检查每个第 n 个像素的碰撞,其中 n 是您的行进速度。一种常见的方法是使用称为CCD(连续碰撞检测)的东西,但这超出了本答案的范围。

更简单的方法如下:

首先检查 x 轴的碰撞,然后检查 y 轴的碰撞。如果注册碰撞,请检测导致碰撞的对象。然后将玩家的位置更改为该对象顶部。您可以在此处找到完整的示例。

def collide(self, xvel, yvel, platforms):
        for p in platforms:
            if sprite.collide_rect(self, p):
                ...
                if xvel > 0: self.rect.right = p.rect.left
                if xvel < 0: self.rect.left = p.rect.right
                if yvel > 0:
                    self.rect.bottom = p.rect.top # <- relevant line
                    ...
                    self.yvel = 0
                if yvel < 0: self.rect.top = p.rect.bottom

如果你有一个简单的游戏,大多数时候这是一个足够好的方法。

最新更新