Файл: Беляев С А - Разработка игр на языке JavaScript - 2016.pdf
Добавлен: 25.10.2018
Просмотров: 7605
Скачиваний: 136
Отображение объектов
61
Условие проверяет, что запрос выполнен корректно.
spriteManager.parseAtlas(request.responseText);
Вызывается функция разбора атласа (parseAtlas) ме
неджера спрайтов результатом запроса. Данная функция
будет рассмотрена ниже. Важно, что функция вызывает
ся не с использованием ключевого слова this, а с исполь
зованием переменной spriteManager.
request.open("GET", atlasJson, true);
Указывается, что запрос будет выполняться с исполь
зованием метода «GET», запрос будет асинхронным и бу
дет выполняться к адресу atlasJson.
request.send();
Отправка запроса:
this.loadImg(atlasImg);
Вызывается функция загрузки изображения (loadImg)
менеджера спрайтов, в качестве параметра — путь к изоб
ражению (atlasImg).
function loadImg(imgName) { // çàãðóçêà èçîáðàæåíèÿ
this.image.onload = function () {
spriteManager.imgLoaded = true; // êîãäà èçîáðàæåíèå
// çàãðóæåíî - óñòàíîâèòü â true
};
this.image.src = imgName; // äàâàéòå çàãðóçèì èçîáðàæåíèå
}
Функция загрузки изображения в качестве параметра
принимает путь к изображению imgName.
this.image.onload = function() { spriteManager.imgLoaded = true; };
В приведенном фрагменте кода полю onload изображе
ния менеджера спрайтов (image) присваивается функция,
содержащая всего одну строку, в которой значение поля
imgLoaded менеджера спрайтов устанавливается в true
(изображение загружено). Данная функция будет вызва
на по окончании загрузки изображения. Важно, что внут
ри функции для обращения к полю imgLoaded использу
ется не ключевое слово this, а переменная spriteManager.
this.image.src = imgName;
62
Глава 3
Полю src объекта image присваивается путь imgName,
после чего JavaScript начинает загрузку изображения.
function parseAtlas(atlasJSON) { // ðàçîáðàòü àòëàñ ñ îáúåêòàìè
var atlas = JSON.parse(atlasJSON);
for (var name in atlas.frames) { // ïðîõîä ïî âñåì èìåíàì â frames
var frame = atlas.frames[name].frame; // ïîëó÷åíèå ñïðàéòà è
// ñîõðàíåíèå â frame
// ñîõðàíåíèå õàðàêòåðèñòèê frame â âèäå îáúåêòà
this.sprites.push({name: name, x: frame.x, y: frame.y, w: frame.w, h:
frame.h});
}
this.jsonLoaded = true; // êîãäà ðàçîáðàëè âåñü àòëàñ - true
}
Функция parseAtlas в качестве параметра принимает
атлас в формате JSON (atlasJSON). По сравнению с разбо
ром JSON карты из 2 главы предлагаемый метод намного
проще и короче.
var atlas = JSON.parse(atlasJSON);
Функция parse встроенного объекта JSON принимает
в качестве параметра JSON в виде строки, а возвращает
объект, который сохраняется в новую переменную atlas.
for (var name in atlas.frames)
Цикл по всем именам спрайтов в атласе:
var frame = atlas.frames[name].frame;
Создание новой переменной frame, в которой сохраня
ется объектспрайт из загруженного атласа.
this.sprites.push({name: name, x: frame.x, y: frame.y, w: frame.w, h:
frame.h});
У массива спрайтов sprites вызывается метод добав
ления объекта в качестве последнего элемента массива
(push). При этом создается новый объект, содержащий
пять параметров: имя (name), координаты (x, y) и разме
ры (w, h). В рассматриваемом примере вся необходимая
информация хранится в спрайте (frame), если размеры в
переменной frame не совпадают с реальными размерами
Отображение объектов
63
спрайта или спрайт был повернут, то разработчику необ
ходимо получить из atlas.frames[name] необходимые ему
объекты и поля и соответствующим образом обработать.
this.jsonLoaded = true;
По окончании цикла в переменной jsonLoaded сохра
няется информация об успешном окончании загрузки
JSON. В результате программирования перечисленных
методов менеджер спрайтов умеет загружать спрайты, но
полезно уметь их отображать.
function drawSprite(ctx, name, x, y) {
// åñëè èçîáðàæåíèå íå çàãðóæåíî, òî ïîâòîðèòü çàïðîñ ÷åðåç
// 100 ìñåê
if (!this.imgLoaded || !this.jsonLoaded) {
setTimeout(function () { spriteManager.drawSprite(ctx, name,
x, y); }, 100);
} else {
var sprite = this.getSprite(name); // ïîëó÷èòü ñïðàéò ïî èìåíè
if(!mapManager.isVisible(x, y, sprite.w, sprite.h))
return; // íå ðèñóåì çà ïðåäåëàìè âèäèìîé çîíû
// ñäâèãàåì âèäèìóþ çîíó
x -= mapManager.view.x;
y -= mapManager.view.y;
// îòîáðàæàåì ñïðàéò íà õîëñòå
ctx.drawImage(this.image, sprite.x, sprite.y, sprite.w, sprite.h, x,
y, sprite.w, sprite.h);
}
}
Функция отображения спрайтов (drawSprite) прини
мает в качестве параметров контекст холста (ctx), имя
спрайта, требующего отображения (name), координаты, в
которых необходимо отобразить спрайт (x, y).
if (!this.imgLoaded || !this.jsonLoaded)
Выполняется проверка, что изображение и атлас за
гружены, иначе используется таймер для повторного вы
зова функции отображения спрайтов.
setTimeout(function () { spriteManager.drawSprite(ctx, name, x, y); },
100);
64
Глава 3
Встроенная функция setTimeout в качестве парамет
ра принимает функцию, которую необходимо вызвать по
таймеру и время в миллисекундах (в данном примере —
100 мс). В качестве функции вызывается drawSprite с теми
же параметрами.
var sprite = this.getSprite(name);
С использованием функции getSprite, которая прини
мает в качестве параметра имя спрайта (name) и будет опи
сана ниже, в новую переменную (sprite) сохраняется спрайт.
if(!mapManager.isVisible(x, y, sprite.w, sprite.h))
Используется предусмотрительно подготовленная функ
ция isVisible менеджера карты, которая сообщает: виден
ли спрайт на экране, если нет, то выполняется выход из
функции отображения спрайта (return).
x -= mapManager.view.x; y -= mapManager.view.y;
Координаты спрайта (x, y) передаются относительно
карты, а не относительно видимой части карты, поэтому
используется объект view менеджера карты (mapManager)
для сдвига координат.
ctx.drawImage(this.image, sprite.x, sprite.y, sprite.w, sprite.h, x, y, sprite.w,
sprite.h);
Функция drawImage контекста холста отображает
фрагмент изображения (image), описанный координата
ми (sprite.x, sprite.y) и размерами (sprite.w, sprite.h) в за
данных координатах (x, y) с теми же размерами (sprite.x,
sprite.y).
Для работы функции drawSprite необходима функция
getSprite, обеспечивающая получение спрайта по имени.
function getSprite(name) { // ïîëó÷èòü îáúåêò ïî èìåíè
for (var i = 0; i < this.sprites.length; i++) {
var s = this.sprites[i];
if (s.name === name) // èìÿ ñîâïàëî - âåðíóòü îáúåêò
return s;
}
return null; // íå íàøëè
}
Отображение объектов
65
Функция получения спрайта (getSprite) в качестве
параметра использует его имя (name).
for (var i = 0; i < this.sprites.length; i++)
Организуется цикл for по всем элементам массива
sprites (от 0 до sprites.length) с использованием времен
ной переменной i.
var s = this.sprites[i];
Создается временная переменная s, в которую сохра
няется элемент массива (sprites) с номером i.
if (s.name === name)
Проверяется, что имя элемента массива совпадает с
искомым.
return s;
Возвращает найденный спрайт.
return null;
Если цикл for закончился, значит, спрайт с заданным
именем (name) не найден, поэтому возвращается значе
ние null.
Подготовленный менеджер спрайтов позволяет допол
нить созданные объекты из параграфа 3.1. Например, функ
ция draw объектов Player и Tank может выглядеть следую
щим образом:
function draw(ctx) { // ïðîðèñîâêà îáúåêòà
spriteManager.drawSprite(ctx, "tank_left_1", this.pos_x, this.pos_y);
}
Идентично может выглядеть отображение объекта
Bonus.
function draw(ctx) { // ïðîðèñîâêà îáúåêòà
spriteManager.drawSprite(ctx, "star", this.pos_x, this.pos_y);
}
Для Rocket:
function draw(ctx) { // ïðîðèñîâêà îáúåêòà
spriteManager.drawSprite(ctx, "rocket_up", this.pos_x, this.pos_y);
}