Có cách nào đơn giản để thực hiện phép chiếu đẳng cự thực với khung vẽ HTML5 không?


7

Có cách nào đơn giản để có được phép chiếu đẳng cự thực với phần tử canvas HTML5 không?


Bạn đang tìm kiếm thư viện hoặc cách kết xuất bằng Html5 Canvas?
FxIII

Đây là một hướng dẫn tuyệt vời cho độc giả tương lai: youtube.com/watch?v=go1qrWFw_bs Nó giải thích toán học đằng sau phép chiếu đẳng cự và chạm vào cả 2D và 3D.
DUUUDE123

Câu trả lời:


13

Một trong những tính chất của phép chiếu đẳng cự (và tất cả các phép chiếu axonometric) là các vật thể ở khoảng cách không phát triển nhỏ hơn.

Do đó, một cách tầm thường, HTML5 hỗ trợ các phép chiếu đẳng cự vì bạn chỉ có thể vẽ tất cả các tài sản nghệ thuật của mình theo cách đó và phủ chúng để tạo chiều sâu.


1

Chỉnh sửa: Sửa đổi câu trả lời để rõ ràng hơn.

Dưới đây là một lưu ý nhanh về cách sửa đổi một cái gì đó đơn giản như hình vuông sao cho nó là đẳng cự. Những gì tôi làm ở đây là chạy 3 thói quen vẽ. Đầu tiên, tôi vẽ một hình vuông bình thường có nguồn gốc trung tâm là giữa khung vẽ (nhưng nguồn gốc của bạn có thể ở bất cứ đâu). Sau đó, tôi thực hiện một số tính toán cơ bản để biến nó thành một đa giác đẳng cự. Đây không phải là cách "đúng" để làm điều này, nhưng nó sẽ giúp bạn hiểu toán học trong thói quen vẽ tiếp theo đang làm gì. Sau đó, tôi vẽ lại đa giác bằng cách sử dụng một phép biến đổi đẳng cự, đây là một cách rút gọn các loại để thực hiện những gì chúng ta đã làm thủ công trong ví dụ trước.

   <!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>

Một lời giải thích về cách thức hoạt động của mã này có thể được tìm thấy ở đây (tôi mới tìm thấy mã này ngày hôm nay): http://www.kirupa.com/developer/ilitiescript/isometric_transforms.htmlm . Điều này giải thích một chút về một hệ tọa độ tương tự như những gì chúng ta đã sử dụng. Thật không may, nó không thực sự giải thích toán học, mà tôi sẽ làm ngay (cần phải chạy).

Ngoài ra như đã đề cập trong bài viết trước, một số mã này được lấy từ http://github.com/j03m/trafficcone , một công cụ trò chơi isometric cho html5 mà tôi đã viết. Để xem cách mã này được sử dụng để tạo một thế giới đầy đủ, hãy xem Engine.js và GameWorldModelIso.js. Engine.js cho thấy cách vẽ lưới đầy đủ (drawMock3dGrid) và GameWorldModelIso.js cho thấy cách xây dựng trên forumla cơ bản được sử dụng ở trên để giúp bạn điều hướng thế giới trò chơi, đặt mọi thứ vào các ô, v.v. mà không phải suy nghĩ về các góc và như vậy.


Sẽ tốt hơn nếu bạn chỉ ra các ví dụ cụ thể (tệp / hàm / vv) thay vì liên kết với toàn bộ dự án của bạn.
Tetrad

hiểu, sửa đổi.
j03m
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.