Existe uma maneira simples de obter uma verdadeira projeção isométrica com o elemento de tela HTML5?
Existe uma maneira simples de obter uma verdadeira projeção isométrica com o elemento de tela HTML5?
Respostas:
Uma das propriedades de uma projeção isométrica (e todas as projeções axonométricas) é que os objetos à distância não ficam menores.
Portanto, trivialmente, o HTML5 suporta projeções isométricas porque você pode simplesmente desenhar todos os seus recursos artísticos dessa maneira e sobrepor-los para criar a profundidade.
Editar: Revisou a resposta para que fique mais clara.
Aqui está uma nota rápida sobre como modificar algo simples como um quadrado para que ele seja isométrico. O que faço aqui é executar três rotinas de desenho. Primeiro, eu desenho um quadrado normal cuja origem central é o meio da tela (mas sua origem pode estar em qualquer lugar). Então, faço alguns cálculos básicos para transformá-lo em um polígono isométrico. Essa não é a maneira "correta" de fazer isso, mas deve ajudá-lo a entender o que a matemática na próxima rotina de desenho está fazendo. Em seguida, redesenho o polígono usando uma transformação isométrica, que é um atalho para fazer o que fizemos manualmente no exemplo anterior.
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<script type="text/javascript" src="..\tccore\jquery.min.js"></script>
<script type="text/javascript">
var cellWidth = 30;
var cellHeight = 30;
var context;
function getCellBoundaries(theCellX, theCellY) {
//right
var aOffset = { "offsetX": (cellWidth * -1) / 2, "offsetY": (cellHeight * -1) / 2 };
var aCell = { "x": theCellX, "y": theCellY };
var p1 = getScreenCoords(aCell, aOffset);
//bottom
aOffset = { "offsetX": (cellWidth) / 2, "offsetY": (cellHeight * -1) / 2 };
var p2 = getScreenCoords(aCell, aOffset);
//left
aOffset = { "offsetX": (cellWidth) / 2, "offsetY": (cellHeight) / 2 };
var p3 = getScreenCoords(aCell, aOffset);
//top
aOffset = { "offsetX": (cellWidth * -1) / 2, "offsetY": (cellHeight) / 2 };
var p4 = getScreenCoords(aCell, aOffset);
return { "point1": p1, "point2": p2, "point3": p3, "point4": p4 };
}
function getScreenCoords(Cell, offset) {
var posX = Cell.x * cellWidth + offset.offsetX;
var posZ = Cell.y * cellHeight - offset.offsetY;
var xCart = (posX - posZ)
var yCart = (posX + posZ) / 2;
var rX = -xCart + 400;
var rY = +yCart + 300;
return { "x": Math.floor(rX), "y": Math.floor(rY) };
}
function drawIsoCellBorders (cellX, cellY) {
var cellPoints = getCellBoundaries(cellX, cellY);
context.beginPath();
context.strokeStyle = "red";
context.moveTo(cellPoints.point1.x, cellPoints.point1.y);
context.lineTo(cellPoints.point2.x, cellPoints.point2.y);
context.lineTo(cellPoints.point3.x, cellPoints.point3.y);
context.lineTo(cellPoints.point4.x, cellPoints.point4.y);
context.lineTo(cellPoints.point1.x, cellPoints.point1.y);
console.log("Translated:");
console.log("Bottom: " + cellPoints.point2.x+","+ cellPoints.point2.y);
console.log("Right:" + cellPoints.point1.x +","+ cellPoints.point1.y);
console.log("Top:" + cellPoints.point4.x+","+ cellPoints.point4.y);
console.log("Left: " + cellPoints.point3.x+","+ cellPoints.point3.y);
context.stroke();
context.closePath();
}
$(document).ready(function () {
context = $("#gamescreen")[0].getContext('2d');
/*let's saw we want to draw an isometric square in the center of the page.
Before we do that though, let;s draw a normal square in the center of the page
so you know where some of these wild assumptions come from. To do that, we need to know
where the square should go. We know our canvas is 800 wide and our cells are 30 wide so
we can assume that our canvas can fit around 800/30 cells.*/
var cells_wide = 800/cellWidth;
var cells_high = 600/cellHeight;
//half are our centers positions for 2d
var xCenter = cells_wide/2 * cellWidth;
var yCenter = cells_high/2 * cellWidth;
var centerCellNumberX = cells_wide/2;
var centerCellNumberY = cells_high/2;
//to draw a square in the center of the canvas, we just draw the points.
context.beginPath();
context.strokeStyle = "blue";
context.moveTo(xCenter-cellWidth/2,yCenter-cellHeight/2); //move to top left corner
context.lineTo(xCenter+cellWidth/2, yCenter-cellHeight/2); //move to top right corner
context.lineTo(xCenter+cellWidth/2, yCenter+cellHeight/2); //move to bottom right corner
context.lineTo(xCenter-cellWidth/2, yCenter+cellHeight/2); //move to bottom left corner
context.lineTo(xCenter-cellWidth/2,yCenter-cellHeight/2); //move back to top left corner
context.stroke(); //draw and yay - we've got a little gray square in the center of our canvas
context.closePath();
//now, give this an isometric perspective is pretty easy, we essentially tilt the square.
//a sort of simplified way to do this is as follows -
//It means that we essentially draw a diamond instead of a square, and then halve the height
//and double the width.
//the first point, (the top of the diamond) is 1/2 the width of the square from where the top left
//corner of a normal square would be, to the right
//to Draw: first clear our other rect
//context.clearRect(0, 0, 800, 600);
context.beginPath();
context.strokeStyle = "gray";
console.log("Hacked:");
context.moveTo(xCenter, yCenter+cellHeight/2); //bottom of diamond
console.log("Bottom: " + xCenter + "," + (yCenter+cellHeight/2)); //bottom of diamond
context.lineTo(xCenter+cellWidth, yCenter); //right of diamond
console.log("Right:" + (xCenter+cellWidth) + "," + yCenter); //right of diamond
context.lineTo(xCenter,yCenter-cellHeight/2); //top of diamond
console.log("Top:" + xCenter + "," + (yCenter-cellHeight/2)); //top of diamond
context.lineTo(xCenter-cellWidth, yCenter); //left of diamond
console.log("Left: " + (xCenter-cellWidth) + "," +yCenter); //left of diamond
context.lineTo(xCenter, yCenter+cellHeight/2); //back to bottom of diamond
context.stroke(); //boom, we have an isotile and isopositioning based on some 2s cell-grid coord
context.closePath();
//now let's draw the same exact iso polygon but use our transform
drawIsoCellBorders(0,0);
});
</script>
</head>
<body>
<canvas id="gamescreen" width="800" height="600" style="border-style: dotted; float: left;">
</canvas>
</body>
</html>
Uma explicação de como esse código funciona pode ser encontrada aqui (acabei de encontrar hoje): http://www.kirupa.com/developer/actionscript/isometric_transforms.htm . Isso explica um pouco sobre um sistema de coordenadas semelhante ao que usamos. Infelizmente, isso realmente não explica a matemática, o que farei em breve (preciso executar).
Além disso, como mencionado no post anterior, parte desse código é retirada de http://github.com/j03m/trafficcone, que é um mecanismo de jogo isométrico para html5 que eu escrevi. Para ver como esse código é usado para criar um mundo completo, consulte Engine.js e GameWorldModelIso.js. Engine.js mostra como uma grade completa pode ser desenhada (drawMock3dGrid) e GameWorldModelIso.js mostra como criar o fórum básico usado acima para ajudá-lo a navegar no mundo do jogo, colocar coisas nas células etc. sem ter que pensar nos ângulos e coisas assim.