Isometri c координаты сетки - PullRequest
2 голосов
/ 09 мая 2020

Я пытаюсь сделать проекцию изометрии c в HTML5, и самое близкое, что я могу получить, это масштабирование и поворот области просмотра

window.addEventListener('DOMContentLoaded', (event) => {
    class Point {
        constructor() {
            this.x = 0;
            this.y = 0;
        }
    }
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    function tick(time) {
        ctx.save();

        ctx.translate(250,0);

        ctx.scale(1, 0.5);
        ctx.rotate(45 * Math.PI /180);
        let p = new Point();
        p.x = 4*32;
        p.y = 2*32;

        ctx.fillStyle = 'green';
        ctx.fillRect(p.x,p.y,32,32);
        for (var x = 0; x < 10; ++x) {
            for (var y = 0; y < 10; ++y) {
                ctx.strokeStyle = 'black';
                ctx.strokeRect(x*32, y*32, 32, 32);
            }
        }

        ctx.restore();

        requestAnimationFrame(tick);
    }
    requestAnimationFrame(tick);
});

И это работает .. но это не Это практическое решение, потому что тогда, когда я пытаюсь нарисовать изометрические c спрайты в этом масштабированном и повернутом виде, он выглядит действительно искаженным. Поэтому я бы предпочел не go этот маршрут, если я не смогу заставить его работать, не искажая мои спрайты.

Я также пробовал этот сайт https://gamedevelopment.tutsplus.com/tutorials/creating-isometric-worlds-primer-for-game-developers-updated--cms-28392

Который предоставил уравнение для создания сеток изометрии c. Я использовал их функцию cartesianToIsometri c, чтобы попытаться создать сетку iso

window.addEventListener('DOMContentLoaded', (event) => {
    class Point {
        constructor() {
            this.x = 0;
            this.y = 0;
        }
    }
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    function cartesianToIsometric(cartPt) {
        var tempPt = new Point();
        tempPt.x = cartPt.x - cartPt.y;
        tempPt.y = (cartPt.x + cartPt.y) / 2;
        return (tempPt);
    }
    function tick(time) {

        for (var x = 0; x < 50; ++x) {
            for (var y = 0; y < 50; ++y) {
                let p = new Point();
                p.x = x * 32;
                p.y = y * 32;
                let iso = cartesianToIsometric(p);

                ctx.strokeStyle = 'black';
                ctx.strokeRect(iso.x, iso.y, 32, 32);
            }
        }
        requestAnimationFrame(tick);
    }
    requestAnimationFrame(tick);
});

, но это все равно выглядело неправильно. Если я не поверну или не масштабирую область просмотра, чтобы исправить это. enter image description here

Итак, мой вопрос ... как я могу нарисовать сетку isometri c без масштабирования и поворота окна просмотра (если возможно)

Если у меня есть чтобы масштабировать область просмотра, как в первом примере, как я могу сделать это, не искажая мои спрайты .... Извините, если этот вопрос сбивает с толку, читать мои знания об этом сомнительно ..

Вот мой html файл index.html

<html>
    <head>
        <script src="index.js"></script>
    </head>
    <body>
        <canvas id="canvas"></canvas>
    </body>
</html>

1 Ответ

1 голос
/ 09 мая 2020

Похоже, вы так близки к решению, но немного запутались. Позвольте мне объяснить:

Обычно вам не нужно вращать и масштабировать область просмотра холста. Это то, что вы делаете, когда создаете свои isometri c спрайты. У вас уже должно быть несколько isometri c спрайтов, и все, что вам нужно сделать, просто поместить их в правильные isometri c координаты.

Ваш второй подход будет делать именно то, что я имею в виду, вычисляя изометри c точки с использованием декартовых координат. Это должно работать, не нужно рисовать прямоугольники, просто поместите изображения в координаты isometri c.

Единственный трюк вы должны разместить свои isometri c спрайты от их нижних центральных точек :

for (var x = 0; x < 50; ++x) {
    for (var y = 0; y < 50; ++y) {
        let p = new Point();
        p.x = x * 32;
        p.y = y * 32;
        let iso = cartesianToIsometric(p);

        // Apply offset to place each isometric image from its bottom center. 
        // The default pivot point (top left) won't do good 
        // because we need to stack them up according to their heights.
        let offset = {x: floorImageWidth/2, y: floorImageHeight}
        ctx.drawImage(floor, iso.x - offset.x, iso.y - offset.y);
    }
}

Я также предлагаю использовать отдельную функцию для рисования точек iso (не прямоугольников), чтобы вы могли отлаживать свои позиции :

let debug = true;

function debugDraw(time) {
    for (var x = 0; x < 50; ++x) {
        for (var y = 0; y < 50; ++y) {
            let p = new Point();
            p.x = x * tileWidth;
            p.y = y * tileWidth;
            let iso = cartesianToIsometric(p);

            // draw pivot point for each tile
            ctx.fillStyle = 'yellow';
            ctx.fillRect(iso.x - 5, iso.y - 5, 10, 10);
        }
    }
}

if(debug){
    requestAnimationFrame(debugDraw)
}

Плюс, вот рабочая демонстрация для дальнейших экспериментов: https://codepen.io/justintc/pen/eYpMabx

Надеюсь, это поможет, ура!

...