pygame精灵运动力学

时间:2017-01-26 14:05:24

标签: pygame sprite

我有一个平台游戏的机制问题,我试图在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()

1 个答案:

答案 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.1rect.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模块)