Рендерер; Начало игры на JavaScript

Недавно я начал делать игру на JavaScript, но на самом деле создал только рендерер. Это первая «настоящая» игра, над которой я начал работать, и я не знаю, делаю ли я какие-то серьезные ошибки и есть ли что-то, что нужно улучшить.

renderer.js

function Renderer(atlas){
    this.canvas = document.querySelector("canvas");
    this.ctx = this.canvas.getContext("2d");
    

    this.width = this.canvas.width = screen.width;
    this.height = this.canvas.height = screen.height;

    this.loaded = 0;
    this.tileSize = 64;
    if(atlas){
        this.tileAtlas = new Image(this.tileSize, this.tileSize);
        this.loaded = 1;
        this.tileAtlas.src = atlas;
    }

    this.showImg = function(arg, x, y){
        let offset = arg * 16 - 16;

        if(arg){
            this.ctx.drawImage(this.tileAtlas, offset, 0, 16, 16, x, y, this.tileSize + 1, this.tileSize + 1);
        }
    }

    this.renderMap = function(map, xd, yd){
        this.ctx.imageSmoothingEnabled = false;
        for(let y = 0; y < map.length; y++){
            for(let x = 0; x < map[y].length; x++){
                if(x*this.tileSize+xd<-this.tileSize){continue}
                if(x*this.tileSize+xd>this.canvas.width){break}

                this.showImg(map[y][x], x*this.tileSize+xd, y*this.tileSize+yd);
            }
        }
    }

    this.clear = function(){
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gayme test</title>
    <style>
        body{
            overflow: hidden;
            background-color: white;
        }
        canvas{
            position: absolute;
            background-color: rgb(0, 140, 255);
            top: 0px;
            left: 0px;
            z-index: -1;
        }
    </style>
</head>
<body>
    <canvas></canvas>
    <p></p>
    <script src="terrain.js"></script>
    <script src="renderer.js"></script>
    <script src="main.js"></script>
</body>
</html>

1 ответ
1

this.loaded = 0;

Я не вижу смысла в этой переменной; не намного дольше он будет установлен в 1, но он никогда нигде не отображается.


this.width = this.canvas.width = screen.width;
this.height = this.canvas.height = screen.height;

Я думаю, это должен быть параметр для рендерера со значением по умолчанию. Зачем тебе нужен this.width если ты собираешься использовать только canvas.width? Убедитесь, что все значения представлены только однажды, иначе вы непременно попадете в нелегальное состояние позже.


this.showImg = function(arg, x, y){

arg = “Арг!” – переменные должны быть названы в соответствии с их функцией; это не так. По-видимому, это индекс на основе 1, но, по крайней мере, назовите его index или indexInAtlas. Это проясняет всю идею использования атласа за один раз. Лично я всегда используйте индексирование с нуля – и не без оснований, но если вы используете один на основе затем используйте: (indexInAtlas - 1) * 16 для увеличения понимания.


if(arg){

Если вы не хотите ничего рисовать, то не вызывайте метод, который начинается с show; пропустить вызов функции в renderMap.


this.renderMap = function(map, xd, yd){

Нет никаких указаний на то, что xd и yd есть, и это еще больше сбивает с толку x и y параметры в функции прямо над ним. Вроде какой-то запас, но в таком случае он должен быть marginX и marginY. Однако я не ожидаю, что поля будут меняться при каждом вызове: это должно быть свойством холста, а не параметром.


    for(let y = 0; y < map.length; y++){
            if(x*this.tileSize+xd<-this.tileSize){continue}

Здесь вы показываете читаемость строки с пробелами и строки без них. Всегда используйте пробелы:

            if(x * this.tileSize + xd < -this.tileSize) {
                continue
             }

Видите, какая разница?


Где тестирование y и yd? Вы предполагаете, что там бесконечное пространство? В таком случае, по крайней мере, создайте для него заметку / комментарий.


            this.showImg(map[y][x], x*this.tileSize+xd, y*this.tileSize+yd);

Чертеж карты пока не должен выполнять эти вычисления. Намного лучше иметь drawTile функция, которая использует x и y для карты, а затем извлекает поля из свойств.


Настоятельно рекомендуется разделить вычисления на карте, вычисления для извлечения изображений из атласа и вычисления, чтобы как можно больше выполнить фактический рисунок. Это избавит вас от множества проблем, пытающихся понять код позже, когда игра начнет становиться все более и более сложной. Разделяй и властвуй – это не просто стратегия игры; это также лучшая стратегия во время разработки.

  • Хорошо, большое спасибо! Что касается последнего ответа, если бы я добавил функцию drawTile (), смог бы я передать x и y в качестве входных данных для вычисления в указанной функции? Я действительно не понимаю, что вы подразумеваете под «извлекать поля из свойств», извините.

    – Coenicorn


  • Да, поэтому вы проверяете, нужно ли рисовать плитку в renderMap, и вы вычисляете фактическое место, куда поместить изображение в drawTile функции. Может я неправильно понял dx и dy значения – если начальная точка карты может меняться при каждом вызове renderMap тогда они, возможно, не являются полями и действительно должны быть параметрами. Часто вы можете избежать такого рода недоразумений, создав, например, CanvasPosition(x,y) класс, а затем создайте CanvasPosition mapPosition переменный или аналогичный. Сюда x и y просто x и y но функция координат ясна.

    – Маартен Бодевес


  • Хорошо, теперь я понял. Спасибо, сэр!

    – Coenicorn

  • В этом случае вы получите, например, drawTile(tileIndex, positionOnMap, mapPositionOnCanvas).

    – Маартен Бодевес


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *