这是我在 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/