我目前正在pygame中为一款游戏制作地图编辑器,使用tile地图。
关卡是由以下结构中的块构建而成的(尽管要大得多):
level1 = (
(1,1,1,1,1,1)
(1,0,0,0,0,1)
(1,0,0,0,0,1)
(1,0,0,0,0,1)
(1,0,0,0,0,1)
(1,1,1,1,1,1))
其中“1”是一堵墙,“0”是一个空的空气。
下面的代码基本上是处理块类型变化的代码:
clicked = pygame.mouse.get_pressed()
if clicked[0] == 1:
currLevel[((mousey+cameraY)/60)][((mousex+cameraX)/60)] = 1
但由于关卡存储在元组中,我无法更改不同块的值。我如何以简单的方式改变关卡中的不同值?
将元组转换为列表
(给定问题中元组之间缺少逗号,是为了防止错误消息而添加的)
方法1:
level1 = (
(1,1,1,1,1,1),
(1,0,0,0,0,1),
(1,0,0,0,0,1),
(1,0,0,0,0,1),
(1,0,0,0,0,1),
(1,1,1,1,1,1))
level1 = [list(row) for row in level1]
print(level1)
方法2:
level1 = map(list,level1)
print(list(level1))
方法1花费了——0.0019991397857666016秒——
方法2花费了——0.0010001659393310547秒——
为什么不试着将它的类型从元组转换为列表,反之亦然。
level1 = (
(1,1,1,1,1,1)
(1,0,0,0,0,1)
(1,0,0,0,0,1)
(1,0,0,0,0,1)
(1,0,0,0,0,1)
(1,1,1,1,1,1))
print(level1)
level1 = list(level1)
print(level1)
level1 = tuple(level1)
print(level1)
如果您只使用一个列表而不是列表的列表,您可以极大地加快您的工作速度。当然,这只有在所有内部列表都具有相同大小的情况下才有可能(在您的示例中确实如此,所以我只是假设)。
WIDTH = 6
level1 = [ 1,1,1,1,1,1,
1,0,0,0,0,1,
1,0,0,0,0,1,
1,0,0,0,0,1,
1,0,0,0,0,1,
1,1,1,1,1,1 ]
print level1[x + y*WIDTH] # print value at (x,y)
如果你使用位域而不是列表,你会更快:
WIDTH = 8 # better align your width to bytes, eases things later
level1 = 0xFC84848484FC # bit field representation of the level
print "1" if level1 & mask(x, y) else "0" # print bit at (x, y)
level1 |= mask(x, y) # set bit at (x, y)
level1 &= ~mask(x, y) # clear bit at (x, y)
with
def mask(x, y):
return 1 << (WIDTH-x + y*WIDTH)
但这只适用于字段只包含0或1的情况。如果你需要更多的值,你就必须组合几个比特,这将使问题变得更加复杂。
你有一个元组的元组。
将每个元组转换为列表:
[list(i) for i in level] # list of lists
——或——
map(list, level)
编辑完成后,只需将它们转换回来:
tuple(tuple(i) for i in edited) # tuple of tuples
- OR -(谢谢@jamylak)
tuple(itertools.imap(tuple, edited))
你也可以使用numpy数组:
>>> a = numpy.array(level1)
>>> a
array([[1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1]])
操纵:
if clicked[0] == 1:
x = (mousey + cameraY) // 60 # For readability
y = (mousex + cameraX) // 60 # For readability
a[x][y] = 1