python - PYGAME:碰撞无法正常工作。播放器和平台表现不佳。帮助,这里是python的新手

标签 python oop pygame sprite game-physics

这是我在 stackoverflow 中的第一个问题。我 3 个月前开始学习 python,我正在使用 sprites 构建平台游戏。我必须隔离问题,所以我只发布问题所在的部分。

每当方 block 落在任何平台上时,都会检测到碰撞,但方 block 实际上会向下穿过平台大约 10 个像素(在碰撞期间),然后它会返回并稳定在平台顶部。

如果将 FPS 调整为 2,您可以看到更好的效果。 我怎样才能解决这个问题?我记得构建以前的游戏但没有在“x”轴(摩擦)和“y”轴(重力)上使用加速度,只是快速停止正方形的移动(左/右/上/下)检测碰撞并且正方形从未通过平台...

这是孤立的问题:

import pygame as pg
import random

WIDTH = 900
HEIGHT = 600
NAME = "square"
FPS = 60

green = (0, 150, 0)
white = (255, 255, 255)
black = (0, 0, 0)

class Platform(pg.sprite.Sprite):
    def __init__(self, x, y, width, height, color):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((width, height))
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

class Player(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((40, 40))
        self.image.fill(black)
        self.rect = self.image.get_rect()
        self.rect.center = (WIDTH / 2, HEIGHT / 2)
        self.posx = WIDTH / 2
        self.posy = HEIGHT * 0.10
        self.velx = 0
        self.vely = 0
        self.accx = 0
        self.accy = 0
        self.jumping = False
        self.jump_go = False

    def jump(self):
        if self.jumping == False:
            self.jumping = True
            self.vely = -25

    def update(self):

        self.accx = 0    #FRICTION
        self.accy = 1    #GRAVITY

        keys = pg.key.get_pressed()

        if keys[pg.K_RIGHT]:
            self.accx = 1
        if keys[pg.K_LEFT]:
            self.accx = -1

        if self.vely != 0:
            self.jump_go = False

        #MOVEMENT IN X:

        self.accx = self.accx + (self.velx * (-0.10))
        self.velx = self.velx + self.accx
        self.posx = self.posx + self.velx
        self.rect.x = self.posx

        if abs(self.velx) < 0.5:
            self.velx = 0

        #MOVEMENT IN Y:

        self.accy = self.accy + (self.vely * (-0.05))
        self.vely = self.vely + self.accy
        self.posy = self.posy + self.vely
        self.rect.y = self.posy

        #IF PLAYER FALLS TO EDGE OF SCREEN:

        if self.posy > HEIGHT:
            self.posy = 0
        if self.posx < 0:
            self.posx = WIDTH
        if self.posx > WIDTH:
            self.posx = 0


class Game:
    def __init__(self):
        pg.init()
        pg.mixer.init()
        pg.font.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        self.clock = pg.time.Clock()
        self.running = True

    def new(self):
        self.all_sprites = pg.sprite.Group()
        self.all_platforms = pg.sprite.Group()

        for i in range(3):
            self.platform = Platform(random.randint(0, WIDTH), random.randint(HEIGHT * .15,
                                     HEIGHT - 25), random.randint(100, 300), 50, green)
            self.all_platforms.add(self.platform)
            self.all_sprites.add(self.platform)

        self.player = Player()
        self.all_sprites.add(self.player)
        self.run()

    def run(self):
        self.playing = True
        while self.playing:
            self.clock.tick(FPS)
            self.eventos()
            self.update()
            self.draw()

    def eventos(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                if self.playing:
                    self.playing = False
                self.running = False
            if event.type == pg.KEYDOWN:
                if self.player.jump_go:
                    if event.key == pg.K_a:
                        self.player.jump()

    def update(self):
        self.all_sprites.update()

        # Check if player hit platfom:
        if self.player.vely > 0:
            hits = pg.sprite.spritecollide(self.player, self.all_platforms, False)
            if hits:
                for hit in hits:
                    if self.player.rect.top < hit.rect.top:
                        self.player.posy = hit.rect.top - self.player.rect.height
                        self.player.vely = 0
                        self.player.jumping = False
                        self.player.jump_go = True

    def draw(self):
        self.screen.fill(white)
        self.all_sprites.draw(self.screen)
        pg.display.flip()

g = Game()
while g.running:
    g.new()

pg.quit()

最佳答案

在你的碰撞检查中你得到所有hits ,然后检查每个 hit

if self.player.rect.top < hit.rect.top:

太晚了

如果您的播放器移动的距离小于其每帧的高度,则其底部 将穿透 hit.rect.top , 然后进行检查,但它的顶部 仍在其上方,因此什么也没有发生。

下一帧它走得更远,(仍然没有完全填满 if self.player.rect.top < hit.rect.top: )并通过你的 hit 走得更远一点.

最终填满后的一些帧 if self.player.rect.top < hit.rect.top:其位置由

                if self.player.rect.top < hit.rect.top:
                    self.player.posy = hit.rect.top - self.player.rect.height
                    self.player.vely = 0
                    self.player.jumping = False
                    self.player.jump_go = True

导致您看到的所描述的“通过并跳起”效果。

您可以通过更改来减轻影响

if self.player.rect.top < hit.rect.top:

self.player.rect.bottom时通过 hit.rect.top - 如果 bottom不存在,使用

    if (self.player.rect.top - self.player.rect.height) < hit.rect.top:

减轻“通过”效应。

关于python - PYGAME:碰撞无法正常工作。播放器和平台表现不佳。帮助,这里是python的新手,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62690050/

相关文章:

javascript - 对象内部的 JSON 调用失败。未捕获引用 : data is not defined

python - 让 Pygame 播放一次声音

pygame - 使用 psychopy 时如何在不更改窗口类型的情况下克服 "RuntimeError: Gamma ramp size is reported as 0."?

python - 将 DataFrame 变量名称作为字符串传递

python - Pandas Dataframe 对 ms 值重新采样

java - 在Java中,当一个接口(interface) "extends"另一个接口(interface)时到底会发生什么?

python - 如何安排音频文件在第一首歌曲结束后在 pygame 中自动播放?

python - numpy.unique 无法识别轴参数

python - 在 pandas 中按组替换列/系列

具有具体方法的Python抽象类