在pygame中创建一个平台游戏,并使用向量进行重力和移动。现在我停留在与平台的冲突上,因为平台会撞到平台并几乎完全沉入平台,如下所示:
Player sunk into platform block
(编辑)人们想要更多的代码信息......
主类:
import pygame as pg
import sys
from sprites import *
class Game:
def __init__(self):
pg.init()
pg.mixer.init()
pg.display.set_caption(TITLE)
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
self.clock = pg.time.Clock()
self.running = True
self.load_data()
self.new_game()
def load_data(self):
# Eventually will load data
pass
def new_game(self):
# Creates new instances of all of the sprites
# groups and re-renders sprites at starting locations
self.all_sprites = pg.sprite.Group()
self.platform_sprites = pg.sprite.Group()
self.player = Player(self, 60, 60)
# Creates some test platforms
for x in range(10):
Platform(self, x, 6)
def run(self):
# Basic game loop
while self.running:
self.dt = self.clock.tick(FPS) # Get time passed since last update / Set FPS
self.events()
self.render()
self.update()
def events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
self.running = False
# Check for quit event and close window
def render(self):
self.screen.fill(WHITE)
self.all_sprites.draw(self.screen) # Draws all sprites to screen
pg.display.flip() # updates screen
def update(self):
self.all_sprites.update() # calls the update function of all of the sprites
if __name__ == '__main__':
g = Game()
while g.running:
g.run()
pg.quit()
sys.exit()
....播放器和平台精灵代码:
import pygame as pg
from constants import *
vec = pg.math.Vector2
class Player(pg.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites
self.game = game
super().__init__(self.groups)
self.image = pg.Surface((40, 70))
self.image.fill(BLUE)
self.rect = self.image.get_rect()
pg.draw.rect(self.image, BLACK, (0, 0, self.rect.width, self.rect.height), 3)
self.pos = vec(x, y)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
def move(self):
self.acc = vec(0, 0)
keypress = pg.key.get_pressed()
if keypress[pg.K_a]:
self.acc.x += -PLAYER_MOVE_SPEED
if keypress[pg.K_d]:
self.acc.x += PLAYER_MOVE_SPEED
self.acc += self.vel * PLAYER_FRICTION
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
self.rect.midbottom = self.pos
def collisions(self, axis):
if axis == 'y':
for plat in self.game.platform_sprites:
if self.acc.y > 0:
if pg.Rect.colliderect(self.rect, plat.rect):
self.acc.y = 0
self.pos.y = plat.rect.top
def update(self):
self.move()
self.collisions('y')
class Platform(pg.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites, game.platform_sprites
self.game = game
super().__init__(self.groups)
self.image = pg.Surface((TILESIZE, TILESIZE))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.x = x * TILESIZE
self.y = y * TILESIZE
def update(self):
self.rect.x = self.x
self.rect.y = self.y
“常量”文件仅包含定义的屏幕大小,颜色和播放器速度等内容。如果有任何需要,我会加上它。
答案 0 :(得分:0)
在Player.collisions
中:
if self.acc.y > 0:
if pg.Rect.colliderect(self.rect, plat.rect):
self.acc.y = 0
self.pos.y = plat.rect.top
您遇到问题的主要原因是玩家的速度:
您正在重置垂直加速度(acc.y
)和位置(pos.y
),但似乎您忘记了垂直速度(vel.y
)。 玩家下沉是因为它仍然具有向下的速度,您可以使用self.vel.y = 0
对此进行补救。
另一个更小的问题可能是@LarryMcMuffin正确猜测的,在您的移动/绘图之间存在订购问题:
您可能正确地更新了Player.pos.y
,因此玩家可以完美地站在平台上,但是如果您想绘制角色,还需要更新self.rect.midbottom
处于新位置-您可以执行此操作,但是位于Player.move
中,该位置称为之前。您可以重新排列移动/碰撞功能的顺序,但是我的建议是将self.rect.midbottom = self.pos
从Player.move
移动到Player.update
的最后。
最终结果:
def collisions(self, axis):
if axis == 'y':
for plat in self.game.platform_sprites:
if self.acc.y > 0:
if pg.Rect.colliderect(self.rect, plat.rect):
self.acc.y = 0
self.vel.y = 0
self.pos.y = plat.rect.top
def update(self):
self.move()
self.collisions('y')
self.rect.midbottom = self.pos
我想指出的另一件事,即使它可能与您所描述的问题无关: 使用时间增量。
看,您有两个影响角色位置的值:
vel
):表示位置随时间变化 acc
):表示速度随时间变化 这里的超时是关键-由于两次move
调用之间经过的时间是可变的,因此很重要:随着时间的流逝,速度应该更多/更少的位置。幸运的是,您将在 Game.dt
中保存两个帧/更新之间的时间。将其传递给您的播放器并大致使用它,就像这样:
self.acc += self.vel * PLAYER_FRICTION
self.vel += self.acc * dt
self.pos += (self.vel + 0.5 * self.acc) * dt
它无法完全解决问题,因此两次 dt = 0.5 的调用会产生与一次一次 dt = 1 的调用相同的效果,但是它将“填充”差距”。我认为,如果不以固定间隔更新物理原理,或者诉诸昂贵且复杂的计算(使用 power 函数),就无法实现这一目标。