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

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

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

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

Добавлен: 25.10.2018

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

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

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

Менеджер игры

101

Игра регулярно обновляется. Обновление игры может

происходить с частотой несколько раз в секунду. Чем чаще
оно происходит, тем более плавные движения на экране
наблюдает пользователь, тем большие требования предъ
являются к компьютеру, на котором выполняется про
грамма. Назовем это регулярное обновление «такт» игры.
Предположим ситуацию взаимного уничтожения двух
объектов, при последовательном выполнении команды
уничтожения будет уничтожен только один объект либо
придется реализовывать сложную логику по контролю
взаимного уничтожения. Есть простой подход — исполь
зовать объект отложенного удаления объектов, тогда оба
объекта поместят друг друга в массив laterKill и после
выполнения всех действий текущего такта достаточно
проверить и удалить хранящиеся в нем объекты.
initPlayer: function(obj) { this.player = obj; }

Функция  initPlayer принимает в качестве параметра

объект (obj) и сохраняет его значение в поле player, инициа
лизирует игрока. Функция используется в parseEntities
менеджера карты (п. 2.3).
kill: function(obj) { this.laterKill.push(obj); }

Функция kill принимает в качестве параметра объект

(obj) и предназначена для сохранения его в массив laterKill
для отложенного удаления.

Действия, выполняемые программой в функциях об

новления игры на каждом такте (update), отображения
игрового поля пользователю (draw), загрузке данных игры
(loadAll) и запуске игры (play), могут существенно отли
чаться в зависимости от требований, предъявляемых к
игре. Рассмотрим возможный вариант реализации данных
функций.
function draw(ctx) {

for(var e = 0; e < this.entities.length; e++)

this.entities[e].draw(ctx);

}

Функция отображения игрового поля пользователю

(draw) принимает в качестве параметра контекст холста.
for(var e = 0; e < this.entities.length; e++)


background image

102

Глава 6

Выполняется цикл по всем объектам карты, храня

щимся в массиве entities менеджера игры. В качестве ин
декса используется новая переменная e:

this.entities[e].draw(ctx);

Вызывается команда отображения (draw) для каждо

го объекта (entities[e]) карты.

function update() { // îáíîâëåíèå èíôîðìàöèè

if(this.player === null)

return;

// ïî óìîë÷àíèþ èãðîê íèêóäà íå äâèãàåòñÿ

this.player.move_x = 0;

this.player.move_y = 0;

// ïîéìàëè ñîáûòèå - îáðàáàòûâàåì

if (eventsManager.action["up"]) this.player.move_y = -1;

if (eventsManager.action["down"]) this.player.move_y = 1;

if (eventsManager.action["left"]) this.player.move_x = -1;

if (eventsManager.action["right"]) this.player.move_x = 1;

// ñòðåëÿåì

if (eventsManager.action["fire"]) this.player.fire();

// îáíîâëåíèå èíôîðìàöèè ïî âñåì îáúåêòàì íà êàðòå

this.entities.forEach(function(e) {

try { // çàùèòà îò îøèáîê ïðè âûïîëíåíèè update

e.update();

} catch(ex) {}

});

// óäàëåíèå âñåõ îáúåêòîâ, ïîïàâøèõ â laterKill

for(var i = 0; i < this.laterKill.length; i++) {

var idx = this.entities.indexOf(this.laterKill[i]);

if(idx > -1)

this.entities.splice(idx, 1); // óäàëåíèå èç ìàññèâà 1 îáúåêòà

};

if(this.laterKill.length > 0) // î÷èñòêà ìàññèâà laterKill

this.laterKill.length = 0;

mapManager.draw(ctx);

mapManager.centerAt(this.player.pos_x, this.player.pos_y);

this.draw(ctx);

}


background image

Менеджер игры

103

Функция обновления (update) вызывается на каждом

такте игры и обеспечивает обновление информации об иг
роке и остальных объектах игры.
if(this.player === null) return;

Если игрок (player) не инициализирован, то функция

завершает свое выполнение. Следующие две строки ини
циализируют нулем параметры скорости игрока: this.
player.move_x = 0; this.player.move_y = 0
. Данные строч
ки позволяют упростить программный код, используемый
для задания направления движения («up», «down», «left»,
«right»).
if (eventsManager.action["up"]) this.player.move_y = -1;

Проверяется условие, что необходимо выполнить дей

ствие «moveup», тогда объекту игрока устанавливается
направление движения вверх (скорость по вертикали —
отрицательная). Аналогичным образом настраиваются
направления движения вниз, влево и вправо.
if (eventsManager.action["fire"]) this.player.fire();

Проверяется условие, что необходимо выполнить дей

ствие «fire», тогда вызывается функция игрока fire.
this.entities.forEach(function(e) { try { e.update(); } catch(ex) {} });

Встроенная функция forEach массива принимает в ка

честве параметра функцию, которая должна быть вызва
на для каждого элемента массива. В качестве парамет
ра передается новая функция без имени с параметром e.
В теле функции использована конструкция try { … }
catch(ex) { … }
, которая гарантирует, что в случае возник
новения ошибочной ситуации при обновлении объектов
массива не произойдет прекращение исполнения програм
мы. В теле try вызывается функция обновления (update)
для каждого элемента массива.
for(var i = 0; i < this.laterKill.length; i++)

После обновления всех объектов игры выполняется

цикл for по всем элементам, попавшим в массив отложен
ного удаления (laterKill).
var idx = this.entities.indexOf(this.laterKill[i]);


background image

104

Глава 6

Встроенная функция массива indexOf определяет ин

декс в массиве элемента, laterKill[i], подлежащего удале
нию. Результат сохраняется в новую переменную idx.
if(idx > -1) this.entities.splice(idx, 1);

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

удалось, после чего с использованием встроенной функ
ции массива splice выполняется удаление 1 элемента мас
сива, начиная с индекса idx. Данная функция позволяет
удалять произвольное количество элементов (не мень
ше 1).
if(this.laterKill.length > 0) this.laterKill.length = 0;

Если в массиве отложенного удаления есть элементы,

то все элементы удаляются путем установления длины
массива в ноль.
mapManager.draw(ctx);

Вызывается функция отображения карты (draw) ме

неджера карты.
mapManager.centerAt(this.player.pos_x, this.player.pos_y);

Вызывается функция изменения видимой области

(centerAt) менеджера карты в зависимости от позиции
игрока (player.pos_xplayer.pos_y).
this.draw(ctx);

Выполняется отображение всех объектов, размещен

ных на карте.

Для корректной работы всех менеджеров игры они дол

жны быть корректно инициализированы в правильной
последовательности, для этого должна быть вызвана функ
ция загрузки (loadAll).

function loadAll() {

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

spriteManager.loadAtlas("atlas.json", "img/tankattack.png");

// çàãðóçêà àòëàñà

gameManager.factory['Player'] = Player; // èíèöèàëèçàöèÿ ôàáðèêè

gameManager.factory['Tank'] = Tank;

gameManager.factory['Bonus'] = Bonus;


background image

Менеджер игры

105

gameManager.factory['Rocket'] = Rocket;

mapManager.parseEntities(); // ðàçáîð ñóùíîñòåé êàðòû

mapManager.draw(ctx); // îòîáðàçèòü êàðòó

eventsManager.setup(canvas); // íàñòðîéêà ñîáûòèé

}

Использование отдельной функции загрузки позволя

ет вносить изменения только в одном методе при измене
нии исходных данных для программы.

mapManager.loadMap("tilemap.json");

Функция loadMap менеджера карты загружает карту

из файла «tilemap.json», при необходимости может исполь
зоваться относительный или абсолютный путь к файлу.

spriteManager.loadAtlas("atlas.json", "img/tankattack.png");

Функция loadAtlas менеджера спрайтов обеспечивает

загрузку атласа из файла «atlas.json» и изображения из
файла «img/tankattack.png». В данном случае для изоб
ражения использован относительный путь — изображе
ние находится во вложенной папке с именем «img».

Следующие четыре строки инициализируют фабрику

(factory) менеджера игры.

gameManager.factory['Player'] = Player;

Полю с именем «Player» присваивается указатель на

объект Player (разработан в п. 3.1). Аналогичные операции
выполняются для объектов TankBonus и Rocket. В дан
ном случае имена полей — типы, которые использованы
при описании объектов в редакторе карт (п. 2.1).

mapManager.parseEntities();

После настройки фабрики вызывается функция parse

Entities редактора карты (п. 2.3).

mapManager.draw(ctx);

К данному моменту загружена карта, загружены все

объекты и спрайты, вызывается функции отображения
(draw) менеджера карты.

eventsManager.setup(canvas);