我当时正在网上寻找python的射线广播,并决定调查一些已发布的代码;所以大部分不是我本来的代码我只想了解它的工作原理。
程序从读取文本文档开始运行其地图,每个文本文档均由“ 1”和空格组成,如下所示:
11111111111111111
1 11 11
1 111 11 11 11 11
1 1 1 11 11
1 1 1 1 11
1 1 111 11 1
1 1 1111 11
1 1 11 11 11
1 1 1 11
1 1 11 1 11
1 1 1 1 111 11
1 1 11 1 11
1 1 1 1 11
1 11 1 1 1
1 1 111
11111111111111111
读取将其编译为可用信息的代码表明...
它将字符串转换为列表,将空格更改为“ 0”,对列表进行两次枚举(以便可以隔离每个字符),然后将其以地图的网格形式发送出去(每个“ 1”或“ 0”是列表中自己的元素。
那部分代码看起来像这样:
def create_level(file):
if file[-4:] != '.txt': file += '.txt'
f = open(os.path.join(path, file), 'r')
file = f.readlines()
for i, line in enumerate(file):
file[i] = list(line.rstrip('\n'))
for j, char in enumerate(file[i]):
if char == ' ':
file[i][j] = 0
else:
file[i][j] = int(char)
f.close()
mapBoundX = len(file)
mapBoundY = len(file[0])
mapGrid = []
for i, line in enumerate(file):
mapGrid.append([])
for j, char2 in enumerate(file[i]):
if char2 != 0:
mapGrid[i].append(char2)
else:
mapGrid[i].append(0)
return mapBoundX, mapBoundY, mapGrid
在某些后续功能中,将从先前代码中获取的数据转换为实际的射线投射。我并不完全热衷于它的全部含义,但是我正在学习。这是那部分:
def main():
mapBoundX, mapBoundY, mapGrid = create_level(levelNum)
posX, posY = 8.5, 10.5
dirX, dirY = 1.0, 0.0
planeX, planeY = 0.0, 0.66
while True:
#Input handling
for event in pygame.event.get():
if event.type == QUIT:
Quit()
return
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
Quit()
return
#CEILING AND FLOOR
pygame.draw.rect(SCREEN, ceiling_colour, (0, 0, WIDTH, (HEIGHT - map_size) / 2))
pygame.draw.rect(SCREEN, floor_colour, (0, (HEIGHT - map_size) / 2, WIDTH, (HEIGHT - map_size) / 2))
for x in range(0, WIDTH, resolution):
#Initial setup
cameraX = 2 * x / WIDTH - 1
rayPosX = posX
rayPosY = posY
rayDirX = dirX + planeX * cameraX + 0.000000000000001 #Add small value to avoid division by 0
rayDirY = dirY + planeY * cameraX + 0.000000000000001 #Add small value to avoid division by 0
#Which square on the map the ray is in
mapX = int(rayPosX)
mapY = int(rayPosY)
#The length of one ray from one x-side or y-side to the next x-side or y-side
deltaDistX = sqrt(1 + rayDirY ** 2 / rayDirX ** 2)
deltaDistY = sqrt(1 + rayDirX ** 2 / rayDirY ** 2)
zBuffer = []
#Calculate step and initial sideDist
if rayDirX < 0:
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
else:
stepX = 1
sideDistX = (mapX + 1 - rayPosX) * deltaDistX
if rayDirY < 0:
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
else:
stepY = 1
sideDistY = (mapY + 1 - rayPosY) * deltaDistY
#Digital differential analysis (DDA)
while True:
#Jump to next map square
if sideDistX < sideDistY:
sideDistX += deltaDistX
mapX += stepX
side = 0
else:
sideDistY += deltaDistY
mapY += stepY
side = 1
#Check if ray hits wall or leaves the map boundries
if mapX >= mapBoundX or mapY >= mapBoundY or mapX < 0 or mapY < 0 or mapGrid[mapX][mapY] > 0:
break
#Calculate the total length of the ray
if side == 0: rayLength = (mapX - rayPosX + (1 - stepX) / 2) / rayDirX
else: rayLength = (mapY - rayPosY + (1 - stepY) / 2) / rayDirY
#Calculate the length of the line to draw on the screen
lineHeight = (HEIGHT / rayLength) * wall_height
#Calculate the start and end point of each line
drawStart = -lineHeight / 2 + (HEIGHT - map_size) / 2
drawEnd = lineHeight / 2 + (HEIGHT - map_size) / 2
#Calculate where exactly the wall was hit
if side == 0: wallX = rayPosY + rayLength * rayDirY
else: wallX = rayPosX + rayLength * rayDirX
wallX = abs((wallX - floor(wallX)) - 1)
#Find the x coordinate on the texture
texX = int(wallX * texWidth)
if side == 1 and rayDirX > 0: texX = texWidth - texX - 1
if side == 1 and rayDirY < 0: texX = texWidth - texX - 1
c = max(1, (255.0 - rayLength * 27.2) * (1 - side * .25))
yStart = max(0, drawStart)
yStop = min(HEIGHT, drawEnd)
pixelsPerTexel = lineHeight / texHeight
colStart = int((yStart - drawStart) / pixelsPerTexel + .5)
colHeight = int((yStop - yStart) / pixelsPerTexel + .5)
yStart = int(colStart * pixelsPerTexel + drawStart + .5)
yHeight = int(colHeight * pixelsPerTexel + .5)
column = texture.subsurface((texX, colStart, 1, colHeight))
column = column.copy()
column.fill((c, c, c), special_flags=BLEND_MULT)
column = pygame.transform.scale(column, (resolution, yHeight))
SCREEN.blit(column, (x, yStart))
现在,我的主要问题:
我在专栏文章中看到了对纹理的引用,并且该引用已经过初始化,但是我似乎无法让它一次加载两个不同的纹理。理想情况下,我希望一些墙砖成为一种纹理,而另一些成为另一种。我尝试在原始地图文本文档中添加第三个字符“ 2”,以查看程序是否可以区分它们,但我似乎也无法使它正常工作。
如果有人可以向我解释这是如何工作的,或者我在编辑中做错了什么,那将非常感谢您。谢谢!