如何在Python中渲染一个等轴投影的基于瓦片的世界?

3

我在使用Python和Pygame编写以下代码时,遇到了渲染等角2D瓦片世界的一些问题:

'''
Map Rendering Demo
rendermap.py
By James Walker (trading as Ilmiont Software).
Copyright (C)Ilmiont Software 2013. All rights reserved.

This is a simple program demonstrating rendering a 2D map in Python with Pygame from a list of map data.
Support for isometric or flat view is included.
'''

import pygame
from pygame.locals import *

pygame.init()

DISPLAYSURF = pygame.display.set_mode((640, 480), DOUBLEBUF)    #set the display mode, window title and FPS clock
pygame.display.set_caption('Map Rendering Demo')
FPSCLOCK = pygame.time.Clock()

map_data = [
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]
]               #the data for the map expressed as [row[tile]].

wall = pygame.image.load('wall.png').convert()  #load images
grass = pygame.image.load('grass.png').convert()

tileWidth = 64  #holds the tile width and height
tileHeight = 64

currentRow = 0  #holds the current map row we are working on (y)
currentTile = 0 #holds the current tile we are working on (x)

for row in map_data:    #for every row of the map...
    for tile in row:
        tileImage = wall

        cartx = currentTile * 64    #x is the index of the currentTile * the tile width
        print(cartx)
        carty = currentRow * 64     #y is the index of the currentRow * the tile height
        print(carty)
        x = cartx - carty
        print(x)
        y = (cartx + carty) / 2
        print(y)
        print('\n\n')
        currentTile += 1    #increase the currentTile holder so we know that we are starting rendering a new tile in a moment

        DISPLAYSURF.blit(tileImage, (x, y)) #display the actual tile
    currentTile = 0 #reset the current working tile to 0 (we're starting a new row remember so we need to render the first tile of that row at index 0)
    currentRow += 1 #increment the current working row so we know we're starting a new row (used for calculating the y coord for the tile)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYUP:
            if event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()

    pygame.display.flip()
    FPSCLOCK.tick(30)

使用的瓷砖尺寸为64x64;当运行上述代码时,会生成以下输出: enter image description here 所有瓷砖都具有透明边缘,此示例仅显示“墙”瓷砖,但显然出了些问题,因为所有瓷砖之间的距离都太远了。
我已经尝试阅读一些在线教程,但似乎找不到一个真正用Python编写的教程,请告诉我我错在哪里。
提前致谢, Ilmiont
2个回答

2

试试这个:

  print(carty)
  x = (cartx - carty) / 2
  print(x)
  y = (cartx + carty)/4*3

经过测试,将convert()修改为convert_alpha(),因为优化会在convert()中清除alpha通道。

我还修改了y(/4*3),以考虑您的图像。这对我有效。


好的,这样做效果更好,但我现在得到了这个结果:http://i.stack.imgur.com/XJgBC.png 因此黑色三角形(部分)仍然存在。 - Ilmiont
你确定那些黑色部分是透明的吗? - Matthias
这是我正在演示的“wall.png”瓷砖:http://i.stack.imgur.com/oBrF0.png - Ilmiont
抱歉...A.H是对的,我没有转换为alpha。现在地图正在正确渲染,但它仍然不是真正的正确形状...我该如何将其渲染在屏幕中央??? - Ilmiont
我的地图肯定有问题,这是我能想到的唯一原因;仍然感谢任何帮助。至少现在透明度已经起作用了! - Ilmiont
显示剩余8条评论

2

您可以通过将colorkey设置为黑色来消除黑色三角形,我复制了您的示例并成功修复了它,只需更改:

for row in map_data:    #for every row of the map...
for tile in row:
    tileImage = wall

to

for row in map:
  for tile in row:
    tileImage = wall
    tileImage.set_colorkey((0,0,0))

来源: https://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_colorkey

可能有更好的设置所有colorkey的方法,但我尝试了这个方法,似乎可以工作。我看到了有关alpha的评论,我确信那也更好。

关于定位,您只需要从屏幕中间开始渲染即可。我通过简单地更改以下代码来完成您的代码:

x = cartx - carty
print(x)
y = (cartx + carty) / 2

为了

x = 320 + ((cartx - carty) / 2)
y = ((cartx+carty) / 4 * 3)

我希望这篇文章能对新来的读者有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接