简体   繁体   English

Pygame中的平台碰撞

[英]Platformer Collision in Pygame

I was trying to write a platformer in Pygame, but for the past few weeks I've been stuck on the collision detection between the hero and the platform. 我试图在Pygame中编写平台游戏,但是在过去的几周里,我一直被困在英雄与平台之间的碰撞检测上。 Here are my classes: 这是我的课程:

class Platform(object):
    def __init__(self, colour, rect):
        self.colour = colour
        self.rect = rect

    def draw(self, screen):
        pygame.draw.rect(screen, self.colour, self.rect)


class Character(Block):
    def __init__(self, colour, rect, speed):
        super().__init__(colour, rect)
        (self.dx, self.dy) = speed
        self.is_falling = True

    def update(self, platforms):
        self.is_falling = True
        for platform in platforms:
            if self.is_on(platform):
                self.rect.bottom = platform.rect.top
                self.dy = 0
                self.is_falling = False

        if self.is_falling:
            self.gravity()
        self.rect.x += self.dx
        self.rect.y += self.dy

    def is_on(self, platform):
        return (pygame.Rect(self.rect.x, self.rect.y + self.dy,
                            self.rect.width, self.rect.height)
                .colliderect(platform.rect) and self.dy > 0)

    def left(self):
        self.dx = -5

    def right(self):
        self.dx = 5

    def stop_x(self):
        self.dx = 0

    def jump(self):
        if self.dy == 0:
            self.dy = -25

    def gravity(self):
        self.dy += 5

and here are my functions: 这是我的功能:

def key_down(event, character):
    if event.key == pygame.K_LEFT:
        character.left()
    elif event.key == pygame.K_RIGHT:
        character.right()
    elif event.key == pygame.K_UP:
        character.jump()

def key_up(event, character):
    if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
        character.stop_x()

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    pygame.display.set_caption("PyPlatformer")
    hero = Character((255, 255, 0), pygame.Rect(100, 0, 20, 20), (0, 0))
    platform1 = Block((0, 255, 255), pygame.Rect(100, 100, 100, 10))
    platform2 = Block((0, 255, 255), pygame.Rect(150, 150, 100, 10))
    platforms = (platform1, platform2)
    clock = pygame.time.Clock()
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                key_down(event, hero)
            elif event.type == pygame.KEYUP:
                key_up(event, hero)

        screen.fill((0, 0, 0))
        hero.update(platforms)
        [platform.draw(screen) for platform in platforms]
        hero.draw(screen)
        pygame.display.update()

However, when a Character is sitting on a Block , the collision detection fails, and the character falls through the block. 但是,当Character坐在Block ,碰撞检测失败,并且角色掉落在方块上。 However, when it is moving and inside the block, the detection succeeds and the character goes back to sitting on the block. 但是,当它在块中移动时,检测成功,角色回到坐在块上。 This cycle then repeats and the character looks like it is bouncing on the block. 然后重复此循环,角色看起来像在块上弹跳。

What is causing this bug? 是什么导致此错误? How do I fix it? 我如何解决它?

This version works for me: 这个版本适合我:

def is_on(self, platform):
    return (pygame.Rect(self.rect.x, self.rect.y + self.dy+1, # +1
                        self.rect.width, self.rect.height)
            .colliderect(platform.rect)) 

I add +1 and remove dy > 0 我加+1并删除dy > 0


By The Way: I found other problem. 顺便说一句:我发现了其他问题。

If you put platforms too close (see 128 in platform2 ) 如果平台离得太近(请参阅platform2 128

platform1 = Block((0, 255, 255), pygame.Rect(100, 100, 100, 10))
platform2 = Block((0, 255, 255), pygame.Rect(150, 128, 100, 10)) # 128

player standing on platform2 can touch platform1 and he is moved on platform1 站在platform2上的玩家可以触摸platform1并且他在platform1上移动

It can move me realy high :) 它可以使我真正感动:)

platforms = []
platforms.append(Block((0, 255, 255), pygame.Rect(100, 400, 100, 10)))
platforms.append(Block((0, 255, 255), pygame.Rect(150, 428, 100, 10)))
platforms.append(Block((0, 255, 255), pygame.Rect(250, 28, 10, 400)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM