当前位置: 首页 > 面试题库 >

pygame platformer-如何使底部稳定?

荀正谊
2023-03-14
问题内容

所以我当时在做一个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

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


问题答案:

这是一个简短的平台游戏示例。机芯尤其重要。您必须首先沿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 collishtml" target="_blank">ions:  # 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



 类似资料:
  • 本文向大家介绍Android如何实现底部菜单固定到底部,包括了Android如何实现底部菜单固定到底部的使用技巧和注意事项,需要的朋友参考一下 今天搞了很久的一个问题,导航菜单没有固定到底部,因为上面是ListView,可是没内容,于是就浮动上去了。 效果如下: 这里采用的是一个碎片,代码是: 出问题了,百度了很多,试了很多的办法,没用。 主页面代码: 最后发现是这段代码惹的麻烦:android:

  • 问题内容: 我有一个简单的2列布局,带有页脚,可清除标记中的右和左div。我的问题是我无法在所有浏览器中都将页脚停留在页面底部。如果内容将页脚放下,它会起作用,但并非总是如此。 问题答案: 要获得页脚的粘性: 有一个与您的内容。 右 前 收盘的的地方 。 权 后 收盘的的地方 。

  • 问题内容: 我需要使用才能使用keyboard_actions,以便可以在iOS的键盘上方放置一个“完成”按钮(此刻使用数字键盘) 在将有一列作为一个孩子,然后一个按钮被放置在底部。我尝试过使用来将高度提高到。 我尝试将with与该属性一起使用,但是最终当键盘出现时,该小部件不会消失。 旁注:脚手架同时具有和设置为(默认值) 问题答案: 问题在于它是孩子。因此,要在两者之间使用自动尺寸小部件- 我

  • 我创建了一个带有“底部导航活动”的新项目: 这是生成的代码: 如何使用底部栏更改为新片段?例如,我有3个片段:Fragment1 Fragment2和Fragment3,我想用底部栏中的3个按钮更改为它们。我还想通过左右滑动手指来切换片段,我该怎么做?

  • 我有一个JPanel,在我点击一个按钮后,我希望图标垂直显示,一个在顶部,另一个在底部点击第二个图标,依此类推。 因此,每次点击时,图标位置会在顶部和底部之间交替变化。 我尝试了许多布局经理,但似乎无法让它像我希望的那样工作。 编辑:举例, 第一次点击后; 二次点击, 第三次点击,顶部的另一个图标,依此类推。这样做的目的是添加到我正在创建的国际象棋游戏中。所以我希望死棋子出现在适当的玩家端(黑色或

  • 问题内容: 我希望一个html图像与div标签的底部齐平。我似乎找不到解决此问题的方法。 这是我的HTML: 问题是div嵌套在具有填充或边距的其他div中。 问题答案: 在包装的div标签上添加相对位置,然后将图像绝对定位在其中,如下所示: CSS: HTML: 现在,图像位于div的底部。