Файл: Беляев С А - Разработка игр на языке JavaScript - 2016.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Программирование

Добавлен: 25.10.2018

Просмотров: 7596

Скачиваний: 136

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Отображение карты игры

41

Функция  isVisible содержит единственное условие,

которое проверяет, что два прямоугольника пересекают
ся: параметры первого прямоугольника переданы в функ
цию isVisible в виде xywidth и height. Параметры вто
рого прямоугольника хранятся в this.view.

Если прямоугольники пересекаются, возвращается

true, иначе — false.

Для запуска полученной программы необходимо под

ключить приведенный JavaScript в HTMLстраницу, со
держащую холст canvas с объявлением переменных canvas
и ctx (по аналогии с примерами из главы 1), затем вызвать
две функции вновь созданного mapManager:

mapManager.loadMap("tilemap.json"); // çàãðóçèòü êàðòó

mapManager.draw(ctx); // íàðèñîâàòü êàðòó

Пример работы программы приведен на рисунке 2.2.

2.3.

ДОПОЛНИТЕЛЬНЫЕ МЕТОДЫ РАБОТЫ

С КАРТОЙ

Рассмотренные методы позволяют создать и отобра

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

Рис. 2.2

Пример внешнего вида карты,

загруженной с помощью

mapManager


background image

42

Глава 2

и игры возникнет необходимость в разработке дополни
тельных функций mapManager, которые на этапе отобра
жения карты могут показаться не очевидными.

Это такие функции, как: разбор слоя типа objectgroup,

получение блока по его координатам на холсте, центров
ка карты относительно заданных координат (xy).

function parseEntities() { // ðàçáîð ñëîÿ òèïà objectgroup

if (!mapManager.imgLoaded || !mapManager.jsonLoaded) {

setTimeout(function () { mapManager.parseEntities(); }, 100);

} else

for (var j = 0; j < this.mapData.layers.length; j++)

// ïðîñìîòð âñåõ ñëîåâ

if(this.mapData.layers[j].type === 'objectgroup') {

var entities = this.mapData.layers[j];

// ñëîé ñ îáúåêòàìè ñëåäóåò "ðàçîáðàòü"

for (var i = 0; i < entities.objects.length; i++) {

var e = entities.objects[i];

try {

var obj = Object.create(gameManager.factory[e.type]);

// â ñîîòâåòñòâèè ñ òèïîì ñîçäàåì ýêçåìïëÿð îáúåêòà

obj.name = e.name;

obj.pos_x = e.x;

obj.pos_y = e.y;

obj.size_x = e.width;

obj.size_y = e.height;

// ïîìåùàåì â ìàññèâ îáúåêòîâ

gameManager.entities.push(obj);

if(obj.name === "player")

// èíèöèàëèçèðóåì ïàðàìåòðû èãðîêà

gameManager.initPlayer(obj);

} catch (ex) {

console.log("Error while creating: [" + e.gid + "] " + e.type +

", " + ex); // ñîîáùåíèå îá îøèáêå

}

} // Êîíåö for äëÿ îáúåêòîâ ñëîÿ objectgroup

} // Êîíåö if ïðîâåðêè òèïà ñëîÿ íà ðàâåíñòâî objectgroup

}

JSON карты может содержать не только слой tilelayer,

но и слой objectgroup, который хранит информацию о том,
какие объекты и где находятся на карте.


background image

Отображение карты игры

43

В первой строчке функции «разбора» слоя объектов

parseEntities выполняется проверка условия, что изобра
жения и описание карты загружены (по аналогии с функ
цией draw).
for (var j = 0; j < this.mapData.layers.length; j++)

Цикл for проверяет все слои, сохраненные в mapData.

layers.
if(this.mapData.layers[j].type === 'objectgroup')

Данное условие if проверяет, что тип слоя (type) явля

ется слоем objectgroup.
var entities = this.mapData.layers[j];

Создается переменная entities для сокращения записи

при обращении к слою.
for (var i = 0; i < entities.objects.length; i++)

Цикл for ходит по массиву objects для слоя objectgroup.

Следует обратить внимание, что два цикла for являются
вложенными друг относительно друга, поэтому перемен
ные для счетчиков цикла выбраны разные (i и j).
var e = entities.objects[i];

Вводится временная переменная для объекта (сущно

сти), полученная из описания слоя objectgroup.

Конструкция try {…} catch(ex) {…} предназначена для

выполнения действий, которые могут привести к ошибоч
ным ситуациям. В случае возникновения ошибки управ
ление передается в блок, ограниченный фигурными скоб
ками после catch.
var obj = Object.create(gameManager.factory[e.type]);

В данной строке создается новый объект, который бу

дет размещаться на карте. Здесь используется новый объ
ект gameManager (см. главу 6). В данном случае поле e.type
хранит строковое название объекта, который необходимо
разместить на карте. Значение поля type в визуальном
интерфейсе вводится дизайнером игры. Конструкция
gameManager.factory[e.type] вернет объект JavaScript,
описанный в главе 3 и дополненный в главе 5. Встроенная
функция Object.create создает новый объект на основании


background image

44

Глава 2

gameManager.factory[e.type]. При этом копируются все
поля и функции из исходного объекта. Ошибка может воз
никнуть, если разработчик не описал объект с типом e.type.

В новом объекте сохраняются его имя (name), коор

динаты в пискелах (pos_x,  pos_y), размеры в пикселах
(size_xsize_y).
gameManager.entities.push(obj);

Объект функцией push помещается в массив entities

менеджера игры gameManager (глава 6).
if(obj.name === "player")

Выполняется проверка, что полученный объект соот

ветствует «игроку», которым будет управлять пользова
тель. Поле name — текст, который в визуальном интерфей
се вводится дизайнером игры. В связи с этим разработчик
должен учитывать, что данный текст может быть не введен
или будет найдено несколько объектов с тем же текстом.
gameManager.initPlayer(obj);

Вызывается функция initPlayer менеджера игры

gameManager (глава 6), в качестве параметра задается
объект, соответствующий «игроку», которым будет управ
лять пользователь.

Функция  log встроенного объекта console выводит в

консоль разработчика браузера информацию, передавае
мую в качестве параметра. Доступ к консоли разработчи
ка описан в параграфе 1.3.
function getTilesetIdx(x, y){

// ïîëó÷èòü áëîê ïî êîîðäèíàòàì íà êàðòå

var wX = x;

var wY = y;

var idx = Math.floor(wY / this.tSize.y) * this.xCount + Math.floor

(wX / this.tSize.x);

return this.tLayer.data[idx];

}

Функция  getTilesetIdx, используя размеры блоков

(tSize.x,  tSize.y) и количество блоков по горизонтали
(xCount), вычисляет индекс блока в массиве data (idx).
return this.tLayer.data[idx];


background image

Отображение карты игры

45

Функция возвращает блок из массива data с индексом

idx.

function centerAt(x, y) {

if(x < this.view.w / 2) // Öåíòðèðîâàíèå ïî ãîðèçîíòàëè

this.view.x = 0;

else

if(x > this.mapSize.x - this.view.w / 2)

this.view.x = this.mapSize.x - this.view.w;

else

this.view.x = x - (this.view.w / 2);

if(y < this.view.h / 2) // Öåíòðèðîâàíèå ïî âåðòèêàëè

this.view.y = 0;

else

if(y > this.mapSize.y - this.view.h / 2)

this.view.y = this.mapSize.y - this.view.h;

else

this.view.y = y - (this.view.h / 2);

}

Функция centerAt предназначена для центрирования

области mapManager.view относительно положения игро
ка (xy). Функция делится на две логические части: цент
рирование по горизонтали и центрирование по вертика
ли. Они абсолютно идентичны за исключением замены x
на y и ширины (view.w) на высоту (view.h).

if(x < this.view.w / 2)

Первой строчкой выполняется проверка, что x мень

ше половины ширины холста, если это верно, то view.x
присваивается значение ноль.

if(x > this.mapSize.x - this.view.w / 2)

Затем проверяется, что x больше ширины карты, умень

шенной на половину ширины холста, если это верно, то
view.x присваивается разность между шириной карты и
шириной холста, иначе view.x присваивается разность
между x и половиной ширины холста.

Идентичные действия выполняются при центрирова

нии по вертикали.