我对Python很陌生,我想测试一下tilemap系统。当我尝试加载图块时,收到错误消息IndexError: list index out of range
。为了解决此问题,以及将来其他类似问题,我需要做什么?
确切的错误:
Traceback (most recent call last):
File "N:/Python/Projects/Projects/First Topdown/First Topdown.py", line 114, in <module>
pygame.draw.rect(screen, colors[tilemap[row][column]], (column*tilesize, row*tilesize, tilesize, tilesize))
IndexError: list index out of range
我听说这意味着我正在尝试访问一个none
或为空的值。
这是与tilemap
有关的代码部分。没有最后的绘图位,其余的工作正常。 (不是很多其他代码,只是运动。)
import pygame
pygame.init()
tilesize = 64
mapwidth = 16
mapheight = 13
screen = pygame.display.set_mode((mapwidth*tilesize, mapheight*tilesize))
pygame.display.set_caption("Aspen")
WALLTOP = 0
WALLBOT = 1
GRASS = 2
wallTop = (128, 128, 128)
wallBot = (210, 105, 30,)
grass = (50, 205, 50)
colors = {
WALLTOP : wallTop,
WALLBOT: wallBot,
GRASS : grass
}
tilemap = [
[WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP,
WALLTOP, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP]
]
running = True
while running:
screen.fill((64, 64, 64))
for row in range(mapheight):
for column in range(mapwidth):
pygame.draw.rect(screen, colors[tilemap[row][column]], (column*tilesize, row*tilesize, tilesize, tilesize))
pygame.display.update()
答案 0 :(得分:0)
您之所以得到IndexError
是因为您仅在tilemap
中定义了一个行,但是外部for
循环提供了{{1} }从row
到0
的索引,原因如下:
mapheight-1
为避免该错误,请尝试将其更改为:
for row in range(mapheight):
更新
我想我已经弄清楚了您要做什么。正如我之前说的,for row in range(len(tilemap)):
是因为IndexError
中的行数与您尝试使用嵌套tilemap
循环显示的行数不匹配。
下面,我更正了for
的定义方式,使其具有适当的行数和列数(还简化了一些其他定义,并在显示循环中添加了一些事件处理功能,以使脚本可以正常关机,而不是无限循环运行。
tilemap
答案 1 :(得分:0)
好吧,我终于明白了你在做什么。
即使您的图块是一维的,您也尝试制作第二个图块。对于多维数组,最好使用numpy数组imo。当您在代码中打印出tmap时,您会明白我的意思,它更具可读性。另外,由于python使用缩进,因此最好通过将不同的参数分隔到单独的行来组织长函数调用。否则,您的代码中会出现一条长行,真是难以理解。
import pygame
import numpy as np
pygame.init()
# Define base values for tiles
tsize, width, height = 64,16,13
# Set the stage with an empty 2D array full of zeroes
# Create the tilemap dynamically from width and height.
tmap = np.zeros((height,width),dtype=int)
# defines the screen I guess?
screen = pygame.display.set_mode((width*tsize, height*tsize))
pygame.display.set_caption("Asspain")
# You can now change the tilemap manually.
# You have three unique rows, so you can
# just make lists of those and later insert
# them into your np.array
r1 = [1]*width
r2 = [1]
r2.extend([2]*14)
r2.extend([1])
r3 = [1]
r3.extend([0]*14)
r3.extend([1])
# turn your lists into np.arrays so they work
# with your tmap.
r1, r2, r3 = np.array(r1),np.array(r2),np.array(r3)
# insert the rows at the appropreate positions
# mind you, indexing works a bit different in
# np.arrays than in python builtin lists.
tmap[0] = r1.copy()
tmap[1] = r2.copy()
tmap[2:12] = r3.copy()
tmap[12] = r1.copy()
# You now have a nice and readable tmap.
# You can make the map creation process
# as manual as you want, I just used shortcuts
# based on symmetry.
print(tmap)
# Now you can just iterate over every element
# via double iteration, or using indices.
# I've heard iterating over indices using range
# is always faster.
# define colormap
cmap = {0:(50, 205, 50),
1:(128, 128, 128),
2:(210, 105, 30,)}
# this is unneccessary, but it's good to know
# that numpy arrays also have a len() like
# attribute called shape.
width, heigth = tmap.shape[0], tmap.shape[1]
# Gameloop
while True:
# Is this the default color of a tile?
# Do you need that?
screen.fill((64, 64, 64))
for row in range(width):
for col in range(heigth):
pygame.draw.rect(screen,
cmap[tmap[row][col]],
(col*tsize,
row*tsize,
tsize,
tsize))
pygame.display.update()
编辑:我注意到您做了很多词典切片,这非常慢。如果您不需要在游戏循环内重复切片字典(即地图不变),请不要。我已经写了一些额外的代码,它会生成与上面相同的tmap
数组作为您的图块的模板,但是这次,我也正在投射一个数组,该数组将三色组映射到这些位置。 / p>
这样,您可以使用快速的numpy数组一次创建整个地图,该数组利用dtype类型化数组,同时仍受益于先前指定的tmap的可读性。
import numpy as np
import matplotlib.pyplot as plt
tsize, width, height = 64,16,13
tmap = np.zeros((height,width),dtype=int)
cmap = np.zeros((height,width,4),dtype=int)
r1 = [1]*width
r2 = [1]
r2.extend([2]*14)
r2.extend([1])
r3 = [1]
r3.extend([0]*14)
r3.extend([1])
r1, r2, r3 = np.array(r1),np.array(r2),np.array(r3)
tmap[0] = r1.copy()
tmap[1] = r2.copy()
tmap[2:12] = r3.copy()
tmap[12] = r1.copy()
cdct = {0:np.array((50, 205, 50, 200),dtype=int),
1:np.array((128, 128, 128, 200),dtype=int),
2:np.array((210, 105, 30, 200),dtype=int)}
for posy, row in enumerate(tmap):
for posx, col in enumerate(row):
cmap[posy,posx] = cdct[col].copy()
fig, ax = plt.subplots()
plt.axis('off')
ax.imshow(cmap)
如您所见,matplotlib
可以轻松地可视化X,Y,Z数组,imshow()
函数可以将其读取为位图。 X是行,Y是列,Z是彩色三元组。实际上,我将Z元素的长度设置为四个,以切换第四个元素的透明度。这样,您可以一次将位图创建为背景,然后直接在颜色四倍体上进行迭代,而无需在while循环的每次迭代中进行16 * 13慢速字典切片。显然,该绘图只是其外观的视觉展示,并且是用于对游戏地图进行建模的漂亮小工具。
并且由于它使用类型转换的numpy数组并避免了很多缓慢的操作,因此与以前相比,它应闪电般快。