PyGame: спрайты не будут двигаться
Я делаю небольшую игру с PyGame, где камера сфокусирована на спрайте, представляющем персонажа, и карта перемещается вокруг него, когда нажимаются клавиши со стрелками. Проблема в том, что карта не двигается. У меня была эта проблема несколько раз прежде, и я думаю, что сузил ее до того, что это может быть, но я не знаю, как на самом деле решить эту проблему.
Вот код:
import sys, pygame
from pygame.locals import *
pygame.init()
size = screen_width, screen_height = 800, 600
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
game_is_running = True
class Character(object):
""" Defines player's metadata """
def __init__(self):
self.x = 350
self.y = 250 # at about the center of the screen
self.dx = 0
self.dy = 0
self.width = 50
self.height = 50
self.sprite = pygame.image.load("./../Images/main-char-sprite.png") #the pic representing the character
self.dead_sprite = None #the pic representing the character when dead (doesn't exist yet)
player = Character()
class Map():
"""
Defines environment.
Will be drawn around static arrays for now.
"""
def __init__(self):
self.wall = pygame.image.load("./../Images/dungeon/wall.jpg")
self.floor = pygame.image.load("./../Images/dungeon/floor.jpg")
self.door = pygame.image.load("./../Images/dungeon/door.jpg")
self.null_tile = pygame.image.load("./../Images/blank.png")
self.x = 0
self.y = 0
self.tile_height = 50
self.tile_width = 50
self.center_x = 400
self.center_y = 300
#self.center_of_room = (self.center_x, self.center_y)
self.town = [
[0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
def draw_floor(self): #will use arrays
for j in range(24): #self.town is 24x24 elements
for k in range(24):
if self.town[j][k]==0:
screen.blit(self.null_tile, (j*player.height, k*player.width))
elif self.town[j][k]==1:
screen.blit(self.wall, (j*player.height, k*player.width))
elif self.town[j][k]==2:
screen.blit(self.floor, (j*player.height, k*player.width))
elif self.town[j][k]==3:
screen.blit(self.door, (j*player.height, k*player.width))
else:
screen.blit(self.null_tile, (j*player.height, k*player.width))
def is_traversable(self):
# if where the player is about to walk is not a floor,
# the land is not traversable and character will not move
if self.town[(player.x + player.dx)//50][(player.y + player.dy)//50]==2:
return True
return False
map = Map()
while game_is_running:
clock.tick(60)
key = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT or key[K_ESCAPE] or key[K_RETURN]:
game_is_running = False
if key[K_UP]:
player.dy = player.height-(2*player.height) #turns player.height negative
if map.is_traversable():
map.y -= player.height
elif key[K_DOWN]:
player.dy = player.height
if map.is_traversable():
map.y += player.height
elif key[K_LEFT]:
player.dx = player.width-(2*player.width)
if map.is_traversable():
map.x -= player.width
elif key[K_RIGHT] and map.is_traversable():
player.dx = player.width
if map.is_traversable():
map.x += player.width
else: pass
""" Drawing routines: """
screen.fill((0, 0, 0))
map.draw_floor()
screen.blit(player.sprite, (player.x, player.y))
""" Graphics cleanup: """
pygame.display.update()
pygame.display.flip()
pygame.quit()
sys.exit()
Основываясь на моих предыдущих программах PyGame, у меня всегда были проблемы с перемещением наборов спрайтов, которые были выведены на экран с for
петли, такие как то, что я сделал здесь. Даже банальные и простые примеры терпят неудачу. Что я хочу знать, так это почему, и как я могу рисовать большие карты кратко и при этом заставлять их двигаться? range()
создает список, и, насколько я знаю, элементы списка являются изменяемыми, так почему же положение карты не меняется?
1 ответ
- У вас есть входное состояние внутри ввода опроса событий. Это вызывает проблемы.
- вы скрываете имя
map
is_traversable
всегда ложно- рендеринг спрайтов
x = world_x + camera_x
а такжеy = world_y + camera_y
, Изменение camera_x/y (или думать о нем как о смещении) приводит к прокрутке карты. Тем не менее, объекты хранят свои позиции в виде глобальных координат. (Будь то пиксели или на основе плитки)
Модифицированный код ниже. Вы можете видеть, как он опрашивает стрелку вверх, но он никогда не печатает "правда!".
import pygame
from pygame.locals import *
pygame.init()
size = screen_width, screen_height = 800, 600
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
game_is_running = True
def temp_sprite(color, size=50):
# gen Surface, since I don't have your sprites
surf = pygame.Surface([size, size])
surf.fill(Color(color))
return surf
class Character(object):
""" Defines player's metadata """
def __init__(self):
self.x = 350
self.y = 250 # at about the center of the screen
self.dx = 0
self.dy = 0
self.width = 50
self.height = 50
#self.sprite = pygame.image.load("./../Images/main-char-sprite.png") #the pic representing the character
self.sprite = temp_sprite("red")
self.dead_sprite = None #the pic representing the character when dead (doesn't exist yet)
player = Character()
class Map():
"""
Defines environment.
Will be drawn around static arrays for now.
"""
def __init__(self):
self.wall = temp_sprite("blue") #pygame.image.load("./../Images/dungeon/wall.jpg")
self.floor = temp_sprite("green") #pygame.image.load("./../Images/dungeon/floor.jpg")
self.door = temp_sprite("brown") #pygame.image.load("./../Images/dungeon/door.jpg")
self.null_tile = temp_sprite("magenta") # pygame.image.load("./../Images/blank.png")
self.x = 0
self.y = 0
self.tile_height = 50
self.tile_width = 50
self.center_x = 400
self.center_y = 300
#self.center_of_room = (self.center_x, self.center_y)
self.town = [
[0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0],
[0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
def draw_floor(self): #will use arrays
for j in range(24): #self.town is 24x24 elements
for k in range(24):
if self.town[j][k]==0:
screen.blit(self.null_tile, (gamemap.y + j*player.height, gamemap.x + k*player.width))
elif self.town[j][k]==1:
screen.blit(self.wall, (gamemap.y + j*player.height, gamemap.x + k*player.width))
elif self.town[j][k]==2:
screen.blit(self.floor, (gamemap.y + j*player.height, gamemap.x + k*player.width))
elif self.town[j][k]==3:
screen.blit(self.door, (gamemap.y + j*player.height, gamemap.x + k*player.width))
else:
screen.blit(self.null_tile, (gamemap.y + j*player.height, gamemap.x + k*player.width))
def is_traversable(self):
# if where the player is about to walk is not a floor,
# the land is not traversable and character will not move
if self.town[(player.x + player.dx)//50][(player.y + player.dy)//50]!=2:
print "true!"
return True
return False
gamemap = Map()
while game_is_running:
clock.tick(60)
key = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT or key[K_ESCAPE] or key[K_RETURN]:
game_is_running = False
if key[K_UP]:
print '.'
player.dy = player.height-(2*player.height) #turns player.height negative
if gamemap.is_traversable():
gamemap.y -= player.height
elif key[K_DOWN]:
player.dy = player.height
if gamemap.is_traversable():
gamemap.y += player.height
elif key[K_LEFT]:
player.dx = player.width-(2*player.width)
if gamemap.is_traversable():
gamemap.x -= player.width
elif key[K_RIGHT] and gamemap.is_traversable():
player.dx = player.width
if gamemap.is_traversable():
gamemap.x += player.width
else: pass
""" Drawing routines: """
screen.fill((0, 0, 0))
gamemap.draw_floor()
screen.blit(player.sprite, (player.x, player.y))
""" Graphics cleanup: """
pygame.display.update()
pygame.display.flip()
pygame.quit()
sys.exit()