【问题标题】:pygame sprite movement mechanicspygame sprite 运动机制
【发布时间】:2017-01-26 14:05:24
【问题描述】:

我尝试在 pygame 中创建的平台游戏机制存在问题。我是一个尝试学习 python 的初学者,所以这基本上是我从在线教程和在这里找到的信息的 sn-ps 中使用的代码。 有人可以帮忙吗?

问题是当玩家精灵向左移动时(通过按左箭头键),它不会像向右移动时那样稳定停止。 我找不到导致错误的原因。

代码:

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()

【问题讨论】:

  • 欢迎来到 StackOverflow。我已经编辑了您的帖子以使代码块看起来更具可读性。每行前面都有一个> 字符,因此请在发布问题之前查看代码格式。也就是说,到目前为止,您尝试过什么?这是本网站上的任何人都必须阅读以试图找出您的问题的大量代码,因此如果您可以将其缩小到代码中您认为可能发生问题的特定位置,您将获得更好的响应。
  • 顺便说一句:为了使代码更具可读性,请将所有常量和类放在 pygame.init() 之前。不要在类之间创建showStats = True。我们仅将UPPER_CASE 名称用于常量值 - 即。 self.PLAYER_VELOCITY_X 不是常数。
  • 使用print() 来查看变量中的内容以及执行的代码部分——这有助于发现问题。或者学习如何使用调试器;)
  • 你有self.screen,所以你不需要GAME_WINDOW
  • 非常感谢。也很抱歉电枢帖子!也感谢您的提示和指示。好的,所以问题出在 def calc_x_movement(self): 函数中。我确定这可能与 PLAYER_SPEED 值有关。

标签: pygame sprite


【解决方案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

self.rect.x += round(self.PLAYER_VELOCITY_X + 0.5 * self.PLAYER_ACCELERATION_X)

但是使用self.x 保留float 值可以得到更好的结果。

float 不能保留所有真实值,但这应该不是问题。或者您可以使用decimal 模块)

【讨论】:

  • 非常感谢!
猜你喜欢
  • 1970-01-01
  • 2020-05-03
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-30
  • 2015-06-16
相关资源
最近更新 更多