HTML5のcanvas要素で真の等角投影を取得する簡単な方法はありますか?
HTML5のcanvas要素で真の等角投影を取得する簡単な方法はありますか?
回答:
等角投影(およびすべての不等角投影)のプロパティの1つは、遠くにあるオブジェクトが小さくならないことです。
したがって、簡単に言えば、すべてのアートアセットをそのように描画し、それらをオーバーレイして奥行きを作成できるため、HTML5は等角投影をサポートします。
編集:より明確になるように回答を修正しました。
ここでは、正方形のような単純なものを等尺性に変更する方法について簡単に説明します。ここでは、3つの描画ルーチンを実行しています。最初に、中心の原点がキャンバスの中央である通常の正方形を描画します(ただし、原点はどこにあってもかまいません)。次に、いくつかの基本的な計算を行って、等角ポリゴンに変換します。これは「正しい」方法ではありませんが、次の描画ルーチンの計算が何をしているかを理解するのに役立ちます。次に、アイソメトリック変換を使用してポリゴンを再描画します。これは、前の例で手動で行った処理を行うためのショートカットです。
<!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>
このコードがどのように機能するかについての説明は、こちら(今日見つけたところ)にあります:http : //www.kirupa.com/developer/actionscript/isometric_transforms.htm。これは、使用したものと同様の座標系について少し説明しています。残念ながら、それは実際には数学を説明していません。これについてはすぐに説明します(実行する必要があります)。
さらに、前の投稿で述べたように、このコードの一部は、私が書いたhtml5用の等尺性ゲームエンジンであるhttp://github.com/j03m/trafficconeから取得されています。このコードを使用して完全な世界を作成する方法については、Engine.jsおよびGameWorldModelIso.jsを参照してください。Engine.jsは、フルグリッドを描画する方法(drawMock3dGrid)を示し、GameWorldModelIso.jsは、上で使用した基本的なフォーラムで構築する方法を示し、角度などを考慮せずにゲームワールドをナビゲートし、セルなどに配置するのに役立ちます。