Actualización: Se corrigió el algoritmo de representación del mapa, se agregaron más ilustraciones, se cambió el formato.
Quizás la ventaja de la técnica de "zig-zag" para mapear los mosaicos a la pantalla se puede decir que los mosaicos x
y las y
coordenadas están en los ejes vertical y horizontal.
Enfoque "Dibujar en un diamante":
Al dibujar un mapa isométrico usando "dibujar en un diamante", lo que creo que se refiere a solo renderizar el mapa usando un for
bucle anidado sobre la matriz bidimensional, como este ejemplo:
tile_map[][] = [[...],...]
for (cellY = 0; cellY < tile_map.size; cellY++):
for (cellX = 0; cellX < tile_map[cellY].size cellX++):
draw(
tile_map[cellX][cellY],
screenX = (cellX * tile_width / 2) + (cellY * tile_width / 2)
screenY = (cellY * tile_height / 2) - (cellX * tile_height / 2)
)
Ventaja:
La ventaja del enfoque es que es un for
bucle anidado simple con una lógica bastante sencilla que funciona de manera consistente en todos los mosaicos.
Desventaja:
Una desventaja de ese enfoque es que las coordenadas x
y y
de los mosaicos en el mapa aumentarán en líneas diagonales, lo que podría hacer que sea más difícil asignar visualmente la ubicación en la pantalla al mapa representado como una matriz:
Sin embargo, habrá un obstáculo para implementar el código de ejemplo anterior: el orden de representación hará que los mosaicos que se supone que estén detrás de ciertos mosaicos se dibujen encima de los mosaicos en el frente:
Para corregir este problema, el for
orden del bucle interno debe invertirse, comenzando desde el valor más alto y volviéndose hacia el valor más bajo:
tile_map[][] = [[...],...]
for (i = 0; i < tile_map.size; i++):
for (j = tile_map[i].size; j >= 0; j--): // Changed loop condition here.
draw(
tile_map[i][j],
x = (j * tile_width / 2) + (i * tile_width / 2)
y = (i * tile_height / 2) - (j * tile_height / 2)
)
Con la corrección anterior, la representación del mapa debe corregirse:
Enfoque "zig-zag":
Ventaja:
Quizás la ventaja del enfoque "zig-zag" es que el mapa renderizado puede parecer un poco más compacto verticalmente que el enfoque "diamante":
Desventaja:
Al intentar implementar la técnica de zig-zag, la desventaja puede ser que es un poco más difícil escribir el código de representación porque no puede escribirse tan simple como un for
bucle anidado sobre cada elemento en una matriz:
tile_map[][] = [[...],...]
for (i = 0; i < tile_map.size; i++):
if i is odd:
offset_x = tile_width / 2
else:
offset_x = 0
for (j = 0; j < tile_map[i].size; j++):
draw(
tile_map[i][j],
x = (j * tile_width) + offset_x,
y = i * tile_height / 2
)
Además, puede ser un poco difícil tratar de averiguar la coordenada de un mosaico debido a la naturaleza escalonada del orden de representación:
Nota: Las ilustraciones incluidas en esta respuesta se crearon con una implementación Java del código de representación de mosaico presentado, con la siguiente int
matriz como mapa:
tileMap = new int[][] {
{0, 1, 2, 3},
{3, 2, 1, 0},
{0, 0, 1, 1},
{2, 2, 3, 3}
};
Las imágenes de mosaico son:
tileImage[0] ->
Una caja con una caja adentro.
tileImage[1] ->
Una caja negra
tileImage[2] ->
Una caja blanca.
tileImage[3] ->
Una caja con un objeto alto y gris.
Una nota sobre los anchos y alturas de los azulejos
Las variables tile_width
y las tile_height
que se usan en los ejemplos de código anteriores se refieren al ancho y la altura del mosaico de tierra en la imagen que representa el mosaico:
El uso de las dimensiones de la imagen funcionará, siempre que las dimensiones de la imagen y las dimensiones del mosaico coincidan. De lo contrario, el mapa de mosaicos podría representarse con espacios entre los mosaicos.
j = (2 * x - 4 * y) / tilewidth * 0.5; i = (p.x * 2 / tilewidth) - j;
.De cualquier manera se hace el trabajo. Supongo que por zigzag te refieres a algo como esto: (los números son orden de representación)
Y por diamante quieres decir:
El primer método necesita más mosaicos renderizados para que se dibuje la pantalla completa, pero puede hacer fácilmente una verificación de límites y omitir cualquier mosaico completamente fuera de la pantalla. Ambos métodos requerirán un poco de cálculo numérico para averiguar cuál es la ubicación de la ficha 01. Al final, ambos métodos son aproximadamente iguales en términos de matemática requerida para un cierto nivel de eficiencia.
fuente
Si tiene algunas fichas que exceden los límites de su diamante, le recomiendo dibujar en orden de profundidad:
fuente
La respuesta de Coobird es la correcta, completa. Sin embargo, combiné sus sugerencias con las de otro sitio para crear un código que funciona en mi aplicación (iOS / Objective-C), que quería compartir con cualquiera que venga a buscar tal cosa. Por favor, si le gusta / vota esta respuesta, haga lo mismo con los originales; todo lo que hice fue "estar sobre los hombros de gigantes".
En cuanto al orden de clasificación, mi técnica es un algoritmo de pintor modificado: cada objeto tiene (a) una altitud de la base (llamo "nivel") y (b) una X / Y para la "base" o "pie" de la imagen (ejemplos: la base del avatar está a sus pies; la base del árbol está en sus raíces; la base del avión es la imagen central, etc.) Luego solo clasifico de menor a mayor nivel, luego de menor a mayor (en la pantalla) a la base más alta Y, luego la más baja (más a la izquierda) a la más alta base-X. Esto hace que los mosaicos de la manera que uno esperaría.
Código para convertir la pantalla (punto) a mosaico (celda) y viceversa:
fuente
Puede usar la distancia euclidiana desde el punto más alto y más cercano al espectador, excepto que no es del todo correcto. Resulta en un orden de clasificación esférico. Puede enderezarlo mirando desde más lejos. Más lejos, la curvatura se aplana. Entonces solo agregue say 1000 a cada uno de los componentes x, y y z para dar x ', y' y z '. La ordenación en x '* x' + y '* y' + z '* z'.
fuente
El verdadero problema es cuando necesita dibujar algunos mosaicos / sprites que se cruzan / cruzan dos o más mosaicos.
Después de 2 (duros) meses de análisis personal del problema, finalmente encontré e implementé un "dibujo de renderizado correcto" para mi nuevo juego cocos2d-js. La solución consiste en mapear, para cada mosaico (susceptible), qué sprites son "frontal, posterior, superior y posterior". Una vez que lo hagas, puedes dibujarlos siguiendo una "lógica recursiva".
fuente