我有一个平台游戏的机制问题,我试图在pygame中创建。我是一个初学者,正在尝试学习python,所以这基本上是我从在线教程中使用的代码和在这里找到的信息片段。 有人可以帮忙吗?
问题是当玩家精灵向左移动时(通过按向左箭头键),它不会像向右方向移动那样稳定停止。 我找不到导致错误的原因。
代码:
import pygame as pg
GAME_TITLE = "Plat Game"
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 400
FPS = 60
GAME_WINDOW = pg.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
GAME_TIMER = 0
RUNNING_GAME = True
PLAYER_SIZE_X = 20
PLAYER_SIZE_Y = 20
PLAYER_FRICTION = -0.1
PLAYER_GRAVITY = 0.8
PLAYER_SPEED = 0.5
PLAYER_VELOCITY_X = 0.0
PLAYER_VELOCITY_Y = PLAYER_GRAVITY
PLAT_SIZE_X = 4
PLAT_SIZE_Y = 4
player_move_left_key = pg.K_LEFT
player_move_right_key = pg.K_RIGHT
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
BACK_GROUND_COLOUR = BLACK
PLAYER_COLOUR = RED
class Player(pg.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pg.Surface([PLAYER_SIZE_X, PLAYER_SIZE_Y])
self.image.fill(RED)
self.rect = self.image.get_rect()
self.PLAYER_VELOCITY_X = 0
self.PLAYER_VELOCITY_Y = 0
self.PLAYER_ACCELERATION_X = 0
self.PLAYER_ACCELERATION_Y = 0
def calc_x_movement(self):
self.PLAYER_ACCELERATION_X += self.PLAYER_VELOCITY_X * PLAYER_FRICTION
self.PLAYER_VELOCITY_X += self.PLAYER_ACCELERATION_X
self.rect.x += self.PLAYER_VELOCITY_X + 0.5 * self.PLAYER_ACCELERATION_X
def calc_gravity(self):
self.PLAYER_ACCELERATION_Y += PLAYER_GRAVITY
self.PLAYER_VELOCITY_Y += self.PLAYER_ACCELERATION_Y
self.rect.y += self.PLAYER_VELOCITY_Y + 0.5 * self.PLAYER_ACCELERATION_Y
def check_for_V_collisions(self):
block_hit_list = pg.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
if self.PLAYER_VELOCITY_Y > 0:
self.rect.bottom = block.rect.top
self.PLAYER_Y = self.rect.bottom
self.PLAYER_VELOCITY_Y = 0
def controls(self):
keys = pg.key.get_pressed()
if keys[player_move_left_key]:
self.PLAYER_ACCELERATION_X = -PLAYER_SPEED
if keys[player_move_right_key]:
self.PLAYER_ACCELERATION_X = PLAYER_SPEED
for event in pg.event.get():
if event.type == pg.QUIT:
quitGame()
if event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
pg.quit()
sys.exit()
if event.type == pg.QUIT:
quitGame()
def movement(self):
self.PLAYER_ACCELERATION_X = 0
self.PLAYER_ACCELERATION_Y = 0
self.PLAYER_GRAVITY = PLAYER_GRAVITY
self.controls()
self.calc_x_movement()
self.calc_gravity()
self.check_for_V_collisions()
class Platform(pg.sprite.Sprite):
def __init__(self, width, height):
super().__init__()
self.image = pg.Surface([width, height])
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
class Level():
def __init__(self, player):
self.platform_list = pg.sprite.Group()
self.enemy_list = pg.sprite.Group()
self.player = player
self.level = []
def update(self):
self.platform_list.update()
def draw(self, screen):
screen.fill(BACK_GROUND_COLOUR)
self.platform_list.draw(screen)
class Level_01(Level):
def __init__(self, player):
Level.__init__(self, player)
level = [[1000, 10, 0, 300]]
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
showStats = True
class Game:
def __init__(self):
pg.init()
pg.font.init()
pg.mixer.init()
pg.display.set_caption(GAME_TITLE)
self.clock = pg.time.Clock()
self.screen = pg.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
self.fontTypeA = pg.font.SysFont("Comic Sans MS", 10)
self.GAME_TIMER = 0
self.running = True
def new(self):
self.player = Player()
level_list = []
level_list.append(Level_01(self.player))
self.current_level_no = 0
self.current_level = level_list[self.current_level_no]
self.active_sprite_list = pg.sprite.Group()
self.player.level = self.current_level
self.player.rect.x = 200
self.player.rect.y = 0
self.active_sprite_list.add(self.player)
self.run()
def run(self):
self.playing = True
while self.playing:
self.update()
self.draw()
def update(self):
self.active_sprite_list.update()
self.current_level.update()
self.player.movement()
self.GAME_TIMER += (1 / FPS)
self.clock.tick(FPS)
def draw(self):
self.current_level.draw(GAME_WINDOW)
self.active_sprite_list.draw(GAME_WINDOW)
if showStats is True:
self.display_player_stats()
pg.display.flip()
def draw_text(self, font_name, text, size, colour, x, y):
font = pg.font.SysFont(font_name, size)
text_surface = font.render(text, True, colour)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
GAME_WINDOW.blit(text_surface, text_rect)
def display_player_stats(self):
text1 = "Vel.Y = " + ("%.2f" % self.player.PLAYER_VELOCITY_Y)
text2 = "Acc.Y = " + ("%.2f" % self.player.PLAYER_ACCELERATION_Y)
text3 = "Pos.Y = " + ("%.2f" % self.player.rect.y)
text4 = "Vel.X = " + ("%.2f" % self.player.PLAYER_VELOCITY_X)
text5 = "Acc.X = " + ("%.2f" % self.player.PLAYER_ACCELERATION_X)
text6 = "Pos.X = " + ("%.2f" % self.player.rect.x)
text7 = "Timer = " + ("%.2f" % self.GAME_TIMER)
self.draw_text("Comic Sans MS", text1, 10, GREEN, 40, 5)
self.draw_text("Comic Sans MS", text2, 10, GREEN, 40, 15)
self.draw_text("Comic Sans MS", text3, 10, GREEN, 40, 25)
self.draw_text("Comic Sans MS", text4, 10, YELLOW, 40, 40)
self.draw_text("Comic Sans MS", text5, 10, YELLOW, 40, 50)
self.draw_text("Comic Sans MS", text6, 10, YELLOW, 40, 60)
self.draw_text("Comic Sans MS", text7, 10, WHITE, SCREEN_WIDTH - 50, 5)
g = Game() while g.running:
g.new()
pg.quit()
答案 0 :(得分:1)
问题是float
值。
您对float
值进行了计算,但rect.x
仅保留integer
值,因此它会将所有float
计算舍入到integer
- 但它会错误地执行方式,它给出了错误的结果。
您可以将所有计算保持为float
- 即。在变量self.x
self.x += self.PLAYER_VELOCITY_X + 0.5 * self.PLAYER_ACCELERATION_X
并在所有计算设置self.rect.x
self.rect.x = self.x
修改强>
可能会rect.x
轮次向floor
添加值,因此会将-0.1
转换为-1
而不是0
,然后rect.x += -0.1
会rect.x += -1
而不是rect.x += 0
您还可以在添加round()
之前使用float
来手动转换<{1}}
self.rect.x += round(self.PLAYER_VELOCITY_X + 0.5 * self.PLAYER_ACCELERATION_X)
但使用self.x
保留float
值可以提供更好的结果。
(float
无法保留所有实际值,但它不应该是一个问题。或者您可以使用decimal模块)