Четверг, 21 Ноября 2024, 19:46

Приветствую Вас Гость

Меню сайта
Категории каталога
Создание игр [358]
Статьи об общих понятиях связанных с созданием игр.
Программирование [83]
Гайды по программированию на разных ЯП.
Движки и Гейммейкеры [147]
Статьи о программах для создания игр, уроки и описания.
Софт [43]
Различные программы, в том числе в помощь игроделам.
2D-графика [14]
Уроки по рисованию, растр, пиксель-арт, создание спрайтов и пр.
3D-графика [17]
Уроки по моделированию, ландшафт, модели, текстурирование и пр.
Моддинг игр [5]
Модификация компьютерных игр, создание дополнений, перевод, хакинг.
Игры [167]
Статьи об играх, в том числе и сделанных на гейммейкерах.
Разное [132]
Статьи, которые не вошли в определённые разделы.
Наш опрос
Какой ЯП вы знаете?
Всего ответов: 27909
Главная » Статьи » Создание игр

Игра на Blend4Web. Логика движения в 2D (ч.1)
Итак, игра «Воин Света» — это двухмерный космосим с видом сверху. Blend4Web является трехмерным движком и в его API нет готовых методов для работы с 2D. Конечно имеется большое количество низкоуровневых функций. Поэтому приходиться работать с ними.

На данном этапе разработки игры я озадачился вопросами математических вычислений в двухмерном пространстве для создания логики функционирования кораблей противника. Первым в моем списке стоит «Дальний разведчик». По задумке, данный корабль представляет собой слабовооруженное судно, стремящееся покинуть поле битвы в случае обнаружения. Исходя из сказанного, логика поведения разведчика выглядит следующим образом:
  • Хаотичное движение по ключевым точкам.
  • В случае обнаружения корабля Игрока, прекратить предыдущее перемещение и удалиться из поля видимости с увеличением скорости. Отстреливаться по ходу движения.
  • Вернуться к патрулированию через некоторое время.

Есть два варианта создания игрового уровня: все действующие объекты сразу находятся на своих местах, либо генерируются в соответствии с заданным временем. Я выбрал второй вариант, что несколько усложняет программирование и балансировку, но с другой стороны имеет свои преимущества в виде экономии вычислительных ресурсов и некоторого случайного фактора.

В соответствии с этой концепцией, основная камера является неподвижной, все вспомогательные объекты также неподвижны, а иллюзия движения выполняется с помощью эффекта параллакса.



Всего в игре два глобальных места для генерации объектов. Верхние точки значительно удалены от экрана и предназначены для генерации метеоритов. Для последних случайным образом выбираются места создания, скорость перемещения и размер. Именно поэтому есть некоторое пространство между пунктами генерации метеоритов и самим экраном, чтобы несколько раскидать их стройные ряды. Другие точки вокруг экрана являются ключевыми местами для движения и генерации игровых объектов, например, кораблей противника.

Рассмотрим простое движение по координатным осям в двухмерном пространстве.
Код

var speed = 1.0; //скорость движения
var elapsed = m_ctl.get_sensor_value(obj, id, 0);  
var coord = m_trans.get_translation(obj); // координаты объекта

coord [2] += speed*elapsed; //выбираем координату для движения
m_trans.set_translation_v(obj.object, obj.coord);


Несколько сложнее выглядит перемещение по ключевым точкам.



Стандартные формулы расчета это:

velocity = normalize(target - position) * max_velocity
position = position + velocity

В случае JavaScript и Blend4Web реализация их выглядит следующим образом:
Код

var velocity = new Float32Array(3);
var maxVelocity = 0.7; //максимальная скорость перемещения

var obj = m_scene.get_object_by_name(“Object”);
var objPos = m_trans.get_translation(obj);
var destObj = m_scene.get_object_by_name(“TargetPoint”);
var targetPos = m_trans.get_translation(destObj);

targetPos [1] = 0;
m_vec3.subtract(targetPos, objPos,velocity);
velocity[1] = 0;
m_vec3.normalize(velocity,velocity);
velocity[0] *= elapsed * maxVelocity;
velocity[2] *= elapsed * maxVelocity;
m_vec3.add(objPos, velocity,objPos);
m_trans.set_translation_v(obj, objPos);

Этот код заставит двигаться объект Object в сторону точки TargetPoint с неизменной скоростью. Если нужно замедление и ускорение, то достаточно убрать нормализацию вектора (m_vec3.normalize()).

Когда объект достигает указанного места, то выполняется проверка на расстояние и вызывается функция выбора новой точки движения (из имеющихся в сцене).
Код

if (m_trans.distance(obj, destObj) < 0.5) GenerateWP (destObj.name);

// oldName - название старой точки движения
function GenerateWP (oldName) {
  var min = 0;
  var max = 7; //максимальное количество пунктов -1
  do {
  var number = Math.floor(Math.random() * (max - min + 1)) + min;
  var name = m_vars.WPS[number];//массив названий точек движения
  } while (oldName == name);
   
  return name;
}


Функция GenerateWP принимает на входе «отработавшую» точку движения и выдает имя нового пункта перемещения. Выбор выполняется случайным способом, но достаточно умно, с проверкой на дублирование.

В указанной схеме и алгоритме движения есть один недостаток: объект выполняет резкие переходы между точками. Наиболее простой способ устранить его — добавить плавный поворот объекта от предыдущего направления к новому.

Этой цели может служить следующая часть кода:
Код

var cur_dir = new Float32Array(3);  
var dir_to_dest =new Float32Array(3);  
var cur_rot_q = new Float32Array(4);
var new_rot_q =new Float32Array(4);
   
var obj = m_scene.get_object_by_name("Player"); //объект А
var objPos = m_trans.get_translation(obj);
var destObj = m_scene.get_object_by_name("Target"); //объект Б
var targetPos = m_trans.get_translation(destObj);

m_trans.get_rotation(obj, cur_rot_q);
m_vec3.transformQuat(m_util.AXIS_Z, cur_rot_q, cur_dir);
m_vec3.subtract(objPos,targetPos, dir_to_dest);
m_vec3.normalize(dir_to_dest, dir_to_dest);
m_quat.rotationTo(cur_dir, dir_to_dest, new_rot_q);
m_quat.multiply(new_rot_q, cur_rot_q, new_rot_q);
var vec_dot = m_vec3.dot(cur_dir, dir_to_dest);
vec_dot = vec_dot > 1? 1: vec_dot < -1? -1: vec_dot;
var angle_to_turn = Math.acos(vec_dot);
var angle_ratio = Math.abs(angle_to_turn) / Math.PI;
var slerp = elapsed / angle_ratio * 1;//скорость разворота
m_quat.slerp(cur_rot_q, new_rot_q, Math.min(slerp, 1), new_rot_q);
m_trans.set_rotation_v(obj, new_rot_q);




Или как это выглядит в игре (красные объекты — контрольные точки, которые я специально разместил для демонстрации в видимой части экрана).

Категория: Создание игр | Добавил: Prand (09 Июня 2016)
Просмотров: 5740 | Рейтинг: 5.0/4 |
Теги: 2d, Blender, Blend4Web, логика
Дополнительные опции:
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:

Игровые объявления и предложения:
Если вас заинтересовал материал «Игра на Blend4Web. Логика движения в 2D (ч.1)», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела. Предлагаются такие схожие материалы: Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.

Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск по сайту
10 случ. движков
  • Construct 3
  • GINCS Studio
  • Golden Realm
  • Murl
  • Eclipse Wold
  • Supertuxkart
  • Jo Engine
  • Bitsy
  • PointJS
  • ZDoom
  • Друзья сайта
    Игровой форум GFAQ.ru Перевод консольных игр
    Все права сохранены. GcUp.ru © 2008-2024 Рейтинг