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 ответ

  1. У вас есть входное состояние внутри ввода опроса событий. Это вызывает проблемы.
  2. вы скрываете имя map
  3. is_traversable всегда ложно
  4. рендеринг спрайтов 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()
Другие вопросы по тегам