【问题标题】:PyGame: Sprites won't movePyGame:精灵不会移动
【发布时间】:2013-10-12 05:11:23
【问题描述】:

我正在使用 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() 做了一个列表,据我所知,列表元素是可变的,那为什么地图的位置没有改变呢?

【问题讨论】:

  • player.dx 始终为 0,map.x 不会在任何地方使用。
  • map.x 用于游戏逻辑。当我按下一个键时,地图的位置应该按 player.height/width 移动。我没有注意到 player.dx。我将更改代码,看看会发生什么。
  • @Armin Rigo 我将游戏逻辑更改为使用 player.dx/dy。它仍然不动。我已编辑问题以反映更改。
  • 更准确地说,map.x 仅用于map.x += ... 行。这意味着您可以更改此属性的值,但不要对它做任何其他事情。

标签: python pygame roguelike


【解决方案1】:
  1. 您有输入状态 inside 事件轮询输入。这会导致问题。
  2. 您正在隐藏名称map
  3. is_traversable 总是假的
  4. 渲染精灵是 x = world_x + camera_xy = world_y + camera_y 。更改 camera_x/y (或将其视为 offset )会导致地图滚动。然而,对象将它们的位置存储为全局坐标。 (无论是基于像素还是图块)

修改后的代码如下。您可以看到它轮询 up arrow ,但它从不打印“true!”。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多