I'm making a small game with PyGame where the camera is focused on a sprite that represents a character and the map moves around it when the arrow keys are pressed. The problem is the map does not move. I've had this problem multiple times before and I think I've narrowed it down to what it might be, but I have no idea how actually to solve the problem.
Here's the code:
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()
Based on my past PyGame programs, I've always had problems moving sets of sprites that have been drawn to the screen with for
loops, such as what I have done here. Even banal and simple examples fail. What I want to know is why is this, and how can I draw large maps concisely and still have them move? range()
makes a list and as far as I know, list elements are mutable, so why isn't the map's position changing?