0

好的,所以我正在用 pygame 制作一个小游戏,并通过将图块生成到多维数组来构建地图。为了做到这一点,我使用了两个 for 循环。

def create(this, t):

    if t == "grasslands":
        for j in range(0, this.numRows):
            for i in range(0, this.numColumns):
                this.column.append(this.Tile("grass", j * this.tileWidth, i * this.tileHeight))
            this.row.append(this.column)

j * this.tileWidth的值被正确地传递到 Tile 初始化中。尽管column[whatever].x值仍然为0。y值设置得很好,如果我使用i或任何其他值而不是j ,事情就很好了。这是我做错了什么还是 Python 有问题?

地图生成文件

import pygame
from sprite import *
from assets import *

class mapG:

def __init__(this, resw, resh):
    this.numRows = 3
    this.numcolumns = 3
    this.tileWidth = 128
    this.tileHeight = 128

    this.row = []
    this.column = []
    this.width = this.numRows * this.tileWidth
    this.height = this.numcolumns * this.tileHeight


def create(this, t):

    if t == "grasslands":
        for j in range(0, this.numRows):
            for i in range(0, this.numcolumns):
                this.column.append(this.Tile("grass", j * this.tileWidth, i * this.tileHeight))
            this.row.append(this.column)


def tileAt(this, x, y):
    pass

def moveRight(this):
    for j in range(0,this.numRows):
        for i in range(0, this.numcolumns):
            this.row[j][i].incX(1)

def Update(this, src):
    for j in range(0,this.numRows):
        for i in range(0, this.numcolumns):
            this.row[j][i].Update(src)
            print(this.row[j][i].y, this.row[j][i].x)

class Tile:

    def __init__(this, name, xpos, ypos):
        this.y = ypos
        this.x = xpos
        this.image = assets.tile[name + ".png"]
        this.sprite = sprite(this.image, this.x, this.y, 100, 100)

    def incX(this, amount):
        this.sprite.IncX(amount)

    def decX(this, amount):
        this.sprite.DecX(amount)

    def incY(this, amount):
        this.sprite.IncY(amount)

    def decY(this, amount):
        this.sprite.DecY(amount)

    def Update(this, src = None):
        if src != None:
            this.sprite.Update(src)

精灵.py

import pygame
import assets

class sprite:

def __init__(this, image, xpos, ypos, width = None, height = None):

    this.image = image
    this.x = xpos
    this.y = ypos
    this.width = width
    this.height = height

    if this.width != None and this.height != None:
        this.image = pygame.transform.scale(image, (this.width,this.height))

def GetPos(this):
    return (this.x, this.y)

def IncX(this, amount):
    this.x += amount

def IncY(this, amount):
    this.y += amount

def DecX(this, amount):
    this.x -= amount

def DecY(this, amount):
    this.y -= amount

def Update(this, src = None):
    if src != None:
        src.blit(this.image, this.GetPos())
4

2 回答 2

5

我相信您遇到的问题来自您this.column在方法中使用变量create

您只需创建一个列列表(在 中__init__),然后将其重新用于地图的所有列。这行不通。

您的this.row列表最终对同一列列表有多个引用,该列表最终包含Tile您创建的所有对象。您稍后只会看到其中的一些,因为您的迭代代码使用预定义的维度,而不是实际迭代整个列表。

为了理解这一点,试着想象一下 2x2 网格的迭代是如何进行的(忽略图块尺寸)。我将每个ij值放在它自己的行上以显示它是如何进展的,并给出每个步骤侧的值row和之后的值:columns

j=0:
   i=0:
      column.append(Tile(i, j))
      # column is [Tile(0, 0)]
      # row is []

   i=1:
      column.append(Tile(i, j))
      # column is [Tile(0, 0), Tile(0, 1)]
      # row is []

   row.append(column)
   # column is [Tile(0, 0), Tile(0, 1)]
   # row is [[Tile(0, 0), Tile(0, 1)]]

j=1: # column is not reset!
   i=0:
      column.append(Tile(i, j))
      # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0)]
      # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0)]]

   i=1:
      column.append(Tile(i, j))
      # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]
      # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]]

   row.append(column)
   # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]
   # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)],
   #          [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]]

row列表包含对同一column四个图块列表的两个引用。您的代码打算将前两个添加Tile(0, 0)Tile(0,1)第一列,然后将最后两个图块添加Tile(1, 0)Tile(1, 1)第二列。但是因为两次都使用了同一个列表,所以你最终将所有值放在一起,然后整个一堆重复。迭代时,您只会看到上图左侧的重复值。

以下是解决方法:

def create(this, t):
    if t == "grasslands":
        for j in range(0, this.numRows):

            column = [] # Create a new list! This is the key!

            for i in range(0, this.numColumns):
                column.append(this.Tile("grass",
                              j * this.tileWidth,
                              i * this.tileHeight))
            this.row.append(column)

您也可以删除构造函数中初始化的行self.column。它只是暂时需要,所以不需要使用实例变量。

于 2013-04-29T08:41:38.250 回答
0

您最终不会创建宽度为 3 ( numColumns) 的行。您最终会得到宽度为 9 (rows*cols) 的行,因为您不会在每次循环中都创建一个新行。

您的循环应如下所示:

for j in range(0, this.numRows):
    row=[]
    for i in range(0, this.numColumns):
        row.append(this.Tile("grass", j * this.tileWidth, i * this.tileHeight))
    this.rows.append(row)

然后,您在调试时可能最终查看了错误的数据,而没有意识到该行比您预期的要长。(而且名称有点混乱,所以我稍微改变了它们。)

于 2013-04-29T08:40:33.403 回答