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

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

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

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

Добавлен: 25.10.2018

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

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

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

Реализация логики поведения объектов

91

Данное условие не отличается от примера «Свободное

падение».
if(Math.abs(pos.imp) > 0.01)

Условие проверяет абсолютное значение (Math.abs)

импульса (pos.imp), если импульс по модулю достаточно
велик, то выполняются следующие шаги. В данном при
мере выбрано значение 0.01. Это значение разработчик
подбирает эмпирическим путем с учетом видимой скоро
сти затухания падения.
pos.imp = pos.dy = pos.imp / 2;

Уменьшение импульса. В данном примере импульс

уменьшается в 2 раза. Степень уменьшения импульса оп
ределяется разработчиком, чем сильнее уменьшается им
пульс, тем менее упругое столкновение. Результат умень
шения импульса сохраняется в pos.dy в качестве нового
ускорения.
pos.y += pos.dy;

Чтобы объект «отскочил» необходимо сразу изменить

значение координаты по вертикали (pos.y) с учетом новой
скорости (pos.dy).

Если импульс оказался достаточно мал, то демонстра

ция начинается сначала. Предлагаемый код по своей сути
не отличается от программы «Изменение двух координат
с учетом свободного падения», но записан в сокращенном
виде.
pos = {x:20, y:320, dx:4, dy:-15, imp:-15};

Объекту pos присваиваются те же значения, что и при

инициализации.

В зависимости от особенностей реализуемых законов

физики разработчик может выбрать тот или иной вари
ант реализации функций update.

5.2.

МЕНЕДЖЕР ФИЗИКИ ОБЪЕКТОВ

При создании объектов у каждого из них могут быть

свои  особенности отображения, изменения состояния,
влияния на другие объекты, но законы движения с боль
шой вероятностью будут общие [13], [14]. В связи с этим


background image

92

Глава 5

целесообразно общую логику по обновлению вынести в
специальный объект — менеджер физики объектов (physic
Manager).

var physicManager = {

update: function (obj){

if(obj.move_x === 0 && obj.move_y === 0)

return "stop"; // ñêîðîñòè äâèæåíèÿ íóëåâûå

var newX = obj.pos_x + Math.floor(obj.move_x * obj.speed);

var newY = obj.pos_y + Math.floor(obj.move_y * obj.speed);

// àíàëèç ïðîñòðàíñòâà íà êàðòå ïî íàïðàâëåíèþ äâèæåíèÿ

var ts = mapManager.getTilesetIdx(newX + obj.size_x / 2,

newY + obj.size_y / 2);

var e = this.entityAtXY(obj, newX, newY); // îáúåêò íà ïóòè

if(e !== null && obj.onTouchEntity) // åñëè åñòü êîíôëèêò

obj.onTouchEntity(e); // ðàçáîð êîíôëèêòà âíóòðè îáúåêòà

if(ts !== 7 && obj.onTouchMap) // åñòü ïðåïÿòñòâèå

obj.onTouchMap(ts); // ðàçáîð êîíôëèêòà ñ ïðåïÿòñòâèåì

// âíóòðè îáúåêòà

if(ts === 7 && e === null) { // ïåðåìåùàåì îáúåêò íà ñâîáîäíîå

// ìåñòî

obj.pos_x = newX;

obj.pos_y = newY;

} else

return "break"; // äàëüøå äâèãàòüñÿ íåëüçÿ

return "move"; // äâèãàåìñÿ

},

entityAtXY: function(obj, x, y) { // ïîèñê îáúåêòà ïî êîîðäèíàòàì

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

var e = gameManager.entities[i]; // âñå îáúåêòû êàðòû

if(e.name !== obj.name) { // èìÿ íå ñîâïàäàåò (èìåíà

// óíèêàëüíû)

if (x + obj.size_x < e.pos_x || // íå ïåðåñåêàþòñÿ

y + obj.size_y < e.pos_y ||

x > e.pos_x + e.size_x ||

y > e.pos_y + e.size_y)

continue;


background image

Реализация логики поведения объектов

93

return e; // íàéäåí îáúåêò

}

} // êîíåö öèêëà for

return null; // îáúåêò íå íàéäåí

}

};

Менеджер физики объектов содержит две функции:

основную (update) для обновления состояния объекта и
вспомогательную (entityAtXY) для определения столкно
вения с объектом по заданным координатам.

При реализации функции update используются сле

дующие особенности объекта: уникальное имя объекта
(name), его координаты (pos_x,  pos_y), размеры (size_x,
size_y), направление движения по координатам (move_x,
move_y), скорость движения (speed). Объект может содер
жать функции встречи с другим объектом (onTouchEntity)
и встречи с границей карты (onTouchMap) или не содер
жать их. Если проанализировать метод parseEntities ме
неджера карты, то можно обнаружить, что в нем инициа
лизируются имя, координаты и размеры объекта. Если
проанализировать описания объектов, то в них задаются
скорость и направления движения.

Предполагается, что массив объектов хранится в ме

неджере игры gameManager.entities, обращение к этому
полю выполняется в функции entityAtXY при поиске
объектов, находящихся по заданным координатам.

Для определения касания карты используется код бло

ка, обозначающего пустое пространство: в приведенном
фрагменте кода — это число 7.

Функция update изменяет состояние объекта и возвра

щает информацию о внесенных или не внесенных измене
ниях (коды: stopbreakmove).
if(obj.move_x === 0 && obj.move_y === 0) return "stop";

Условие проверяет, что скорости движения нулевые,

в таком случае выполнение функции прекращается и воз
вращается код «stop» (объект стоит).
var newX = obj.pos_x + Math.floor(obj.move_x * obj.speed);

var newY = obj.pos_y + Math.floor(obj.move_y * obj.speed);


background image

94

Глава 5

Создаются две переменные для хранения новых коор

динат объекта (newXnewY). Новые координаты вычис
ляются как сумма предыдущих координат и направления
движения, умноженного на скорость. Для вычисления
используется функция floor, обеспечивающая округление
до меньшего целого числа встроенного объекта Math.
var  ts  =  mapManager.getTilesetIdx(newX  +  obj.size_x  /  2,  newY  +

obj.size_y / 2);

Создается новая переменная ts, в которую сохраняют

ся результаты вызова функции getTilesetIdx менеджера
карты, в качестве координат используется середина объек
та. Функция getTilesetIdx возвращает индекс блока кар
ты, который находится на пути объекта.
var e = this.entityAtXY(obj, newX, newY);

Создается переменная e, в которую сохраняются ре

зультаты вызова функции entityAtXY и которая сообща
ет с кем произойдет столкновение, если объект будет на
ходиться в координатах (newXnewY).
if(e !== null && obj.onTouchEntity) obj.onTouchEntity(e);

Если переменная e содержит значение и в объекте есть

функция обработки встречи с другим объектом (onTouch
Entity
), то эта функция вызывается, а в качестве парамет
ра передается переменная e.
if(ts !== 7 && obj.onTouchMap) obj.onTouchMap(ts);

Если значение переменной ts не равно 7 (в данном при

мере число 7 — индекс блока, по которому может двигать
ся объект) и объект содержит функцию встречи с грани
цей карты (onTouchMap), то эта функция вызывается, а в
качестве параметра передается значение переменной ts.
if(ts === 7 && e === null)

Если не произошло столкновения с границей карты

и другим объектом, то сохраняются новые координаты:
obj.pos_x = newX; obj.pos_y = newY. Иначе возвращается
код «break» (дальнейшее движение невозможно).
return "move";


background image

Реализация логики поведения объектов

95

Возвращается код «move» (продолжаем движение).

При наличии отличий в отображении объекта при движе
нии влево, вправо, вверх или вниз целесообразно в этой
функции вычислить реальное направление движение и
вместо кода «move» вернуть код с направлением движе
ния, например, «move_left» (двигаемся налево).

Функция entityAtXY принимает три параметра: объ

ект и его новые координаты (xy).

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

Цикл for обеспечивает проход по всем объектам карты.

Предполагается, что объекты хранятся в массиве game
Manager.entities
.

var e = gameManager.entities[i];

Создается новая переменная e, в которую сохраняется

текущий анализируемый объект карты.

if(e.name !== obj.name)

Проверяем, что имя анализируемого объекта не совпа

дает с именем объекта, передаваемого в качестве парамет
ра функции. Именно здесь используется свойство уникаль
ности имени объекта.

if (x + obj.size_x < e.pos_x || y + obj.size_y < e.pos_y ||

 x > e.pos_x + e.size_x || y > e.pos_y + e.size_y) continue;

Если анализируемый объект и передаваемый в каче

стве параметра не пересекаются, то с использованием клю
чевого слова continue осуществляется переход к очеред
ной итерации цикла for для анализа следующего объекта:

return e;

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

return null;

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

объектами не обнаружено).

Простейшее применение функции update менеджера

физики объектов позволяет упростить функции update
объекта.