pygame platformer-如何使底部稳定?

发布于 2021-01-29 19:31:25

所以我当时在做一个pygame平台游戏,却陷入了一件事情。我找不到找到使平台基础坚实的方法。玩家可以降落在它的顶部,但是当它试图穿过底部时,它会弹跳回去。我试过了,但是没用:

hits = pg.sprite.spritecollide(player, platforms, False)
if hits:
    if player.pos.y == hits[0].rect.top:
        player.vel.y = 10
    else:
        player.pos.y = hits[0].rect.top + 1
        player.vel.y = 0

有人为我提供解决方案吗?这是完整的程序

关注者
0
被浏览
37
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这是一个简短的平台游戏示例。机芯尤其重要。您必须首先沿x轴移动,检查播放器是否与墙壁碰撞,然后在发生碰撞时将其移回墙壁。然后,对y轴执行相同的操作。如果您不将机芯分为这两个部分,那么如果您同时按下多个机芯键,则玩家将跳到墙的侧面,顶部或底部。

    import pygame as pg
    
    
    pg.init()
    WINDOW_WIDTH, WINDOW_HEIGHT = 800, 600
    screen = pg.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
    GRAY = pg.Color('gray24')
    GRAVITY = 800
    
    
    class Player(pg.sprite.Sprite):
    
        def __init__(self, pos, blocks):
            super().__init__()
            self.image = pg.Surface((30, 50))
            self.image.fill(pg.Color(0, 110, 170))
            self.rect = self.image.get_rect(topleft=pos)
            self.vel = pg.math.Vector2(0, 0)
            self.pos = pg.math.Vector2(pos)
            self.blocks = blocks
            self.on_ground = False
    
        def update(self, dt):
            # Move along x-axis.
            self.pos.x += self.vel.x * dt
            self.rect.x = self.pos.x
    
            collisions = pg.sprite.spritecollide(self, self.blocks, False)
            for block in collisions:  # Horizontal collision occurred.
                if self.vel.x > 0:  # Moving right.
                    self.rect.right = block.rect.left  # Reset the rect pos.
                elif self.vel.x < 0:  # Moving left.
                    self.rect.left = block.rect.right  # Reset the rect pos.
                self.pos.x = self.rect.x  # Update the actual x-position.
    
            # Move along y-axis.
            self.pos.y += self.vel.y * dt
            # +1 to check if we're on a platform each frame.
            self.rect.y = self.pos.y + 1
            # Prevent air jumping when falling.
            if self.vel.y > 0:
                self.on_ground = False
    
            collisions = pg.sprite.spritecollide(self, self.blocks, False)
            for block in collisions:  # Vertical collision occurred.
                if self.vel.y > 0:  # Moving down.
                    self.rect.bottom = block.rect.top  # Reset the rect pos.
                    self.vel.y = 0  # Stop falling.
                    self.on_ground = True
                elif self.vel.y < 0:  # Moving up.
                    self.rect.top = block.rect.bottom  # Reset the rect pos.
                    self.vel.y = 0  # Stop jumping.
                self.pos.y = self.rect.y  # Update the actual y-position.
    
            # Stop the player at screen bottom.
            if self.rect.bottom >= WINDOW_HEIGHT:
                self.vel.y = 0
                self.rect.bottom = WINDOW_HEIGHT
                self.pos.y = self.rect.y
                self.on_ground = True
            else:
                self.vel.y += GRAVITY * dt  # Gravity
    
    
    class Block(pg.sprite.Sprite):
    
        def __init__(self, rect):
            super().__init__()
            self.image = pg.Surface(rect.size)
            self.image.fill(pg.Color('paleturquoise2'))
            self.rect = rect
    
    
    def main():
        clock = pg.time.Clock()
        done = False
        dt = 0
    
        all_sprites = pg.sprite.Group()
        blocks = pg.sprite.Group()
        player = Player((300, 100), blocks)
        all_sprites.add(player)
        rects = ((300, 200, 30, 70), (100, 350, 270, 30),
                 (500, 450, 30, 170), (400, 570, 270, 30),
                 (500, 150, 70, 170), (535, 310, 270, 70))
        for rect in rects:  # Create the walls/platforms.
            block = Block(pg.Rect(rect))
            all_sprites.add(block)
            blocks.add(block)
    
        while not done:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    done = True
                elif event.type == pg.KEYDOWN:
                    if event.key == pg.K_a:
                        player.vel.x = -220
                    elif event.key == pg.K_d:
                        player.vel.x = 220
                    elif event.key == pg.K_w:  # Jump
                        if player.on_ground:
                            player.vel.y = -470
                            player.pos.y -= 20
                            player.on_ground = False
                elif event.type == pg.KEYUP:
                    if event.key == pg.K_a and player.vel.x < 0:
                        player.vel.x = 0
                    elif event.key == pg.K_d and player.vel.x > 0:
                        player.vel.x = 0
    
            all_sprites.update(dt)
    
            screen.fill(GRAY)
            all_sprites.draw(screen)
    
            pg.display.flip()
            dt = clock.tick(60) / 1000
    
    
    if __name__ == '__main__':
        main()
        pg.quit()
    

    这是您在注释中发布的代码的有效版本(仅对于垂直碰撞,还需要添加水平碰撞)。因此,当玩家跳跃并与平台碰撞时,您必须将设置player.rect.topplatform.rect.bottom并更改vel.y

    import pygame as pg
    from pygame.math import Vector2 as vec
    
    
    pg.init()
    WIDTH, HEIGHT = 800, 600
    YELLOW = pg.Color('yellow')
    GREEN = pg.Color('green')
    BLACK = pg.Color('gray11')
    screen = pg.display.set_mode((WIDTH,HEIGHT))
    clock = pg.time.Clock()
    FPS = 60
    PLAYER_FRICTION = .95
    PLAYER_ACC = .2
    
    
    class Player(pg.sprite.Sprite):
    
        def __init__(self):
            pg.sprite.Sprite.__init__(self)
            self.image = pg.Surface((30, 40))
            self.image.fill(YELLOW)
            self.rect = self.image.get_rect(center=(WIDTH/2, HEIGHT-30))
            self.pos = vec(WIDTH/2, HEIGHT/2)
            self.vel = vec(0,0)
            self.acc = vec(0,0)
    
        def jump(self):
            self.rect.y += 1
            hits = pg.sprite.spritecollide(self, platforms, False)
            self.rect.y -= 1
            if hits:
                self.vel.y = -13
    
        def update(self):
            self.acc = vec(0, 0.5)
            keys = pg.key.get_pressed()
            if keys[pg.K_a]:
                self.acc.x = -PLAYER_ACC
            if keys[pg.K_d]:
                self.acc.x = PLAYER_ACC
    
            # apply friction
            self.vel.x *= PLAYER_FRICTION
            self.vel += self.acc
            self.pos += self.vel
            # wrap around the sides of the screen
            if self.pos.x > WIDTH:
                self.pos.x = 0
            if self.pos.x < 0:
                self.pos.x = WIDTH
    
            self.rect.midbottom = self.pos
    
    
    class Platform(pg.sprite.Sprite):
        def __init__(self, x, y, w, h):
            pg.sprite.Sprite.__init__(self)
            self.image = pg.Surface((w, h))
            self.image.fill(GREEN)
            self.rect = self.image.get_rect(topleft=(x, y))
    
    
    all_sprites = pg.sprite.Group()
    platforms = pg.sprite.Group()
    
    player = Player()
    all_sprites.add(player)
    # spawns and adds platforms to group
    p1 = Platform(0, HEIGHT - 40, WIDTH, 40)
    p2 = Platform(WIDTH / 2 - 50, HEIGHT - 300, 100, 20)
    p3 = Platform(WIDTH / 2 - 100, HEIGHT - 150, 200, 20)
    all_sprites.add(p1, p2, p3)
    platforms.add(p1, p2, p3)
    
    running = True
    while running:
        clock.tick(FPS)
        for event in pg.event.get():
            if event.type == pg.QUIT:
                running = False
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_SPACE:
                    player.jump()
    
        all_sprites.update()
        # Check if we hit a wall/platform.
        hits = pg.sprite.spritecollide(player, platforms, False)
        for platform in hits:  # Iterate over the collided platforms.
            if player.vel.y > 0:  # We're falling.
                player.rect.bottom = platform.rect.top
                player.vel.y = 0
            elif player.vel.y < 0:  # We're jumping.
                player.rect.top = platform.rect.bottom
                player.vel.y = 3
    
            player.pos.y = player.rect.bottom
    
        #Draw / render
        screen.fill(BLACK)
        all_sprites.draw(screen)
        pg.display.flip()
    
    
    pg.quit()
    

    顺便说一句,在跳跃方法,你必须改变self.rect.yself.rect.x



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看