Решил я тут, значится, игрушку склепать. И спустя несколько приятных недель, решил, а почему бы не поделиться сий историей с теми кому она будет интересна.
Самого кода тут не будет, т.к. это не хабр, ей Б-гу. Кроме того, не обязательно знать код, что бы интересоваться процессом разработки. Да и, не хочу я сейчас делиться своим говнокодом.
Запускаться все это добро будет в браузере. Написан проект с использованием Phaser JS.
Без лишних предисловий (как видите словоблудие дается мне плохо) начнем.
Первое, что я начал, это создание игрового мира. Необходимо было придумать алгоритм по которому его построение (хотя бы базовое) занимало как можно меньше времени и было максимально лёгким. Полистав библиотеку фейзер я остановился на одном интересном варианте.
Суть его такова: Мы загружаем на сцену тайлсет со всеми необходимыми изображениями, указываем размер одного спрайта, и Фэйзер автоматически присваивает каждому указанному изображению соответствующий id.
Вот как это выглядит:
Теперь, зная какая из ячеек с которое изображения отвечает, можно загрузить этот набор в игру, при помощи простенькой таблицы:
И мы получаем вот такой результат:
Не дурно. При этом, ее можно на ходу редактировать, внося соответствующие изменения в игровой мир:
Способ не самый изысканный, но достаточно простой, чтобы меня устроить.
Вероятно, есть способ, вместо того чтобы склеивать разное количество спрайтов в один тайлсет - использовать их по отдельности, но я о сим не ведаю, так что готов склеивать в один файл.
Игрового персонаж работает следующим образом:
Это физический блок, который я "тяну" в нужное направление.
Однако, собственно, с передвижением возникли нюансы.
Поскольку я перемещаю персонажа физикой, а не меняю его пространственные координаты, то я решил, что хорошей идеей было бы использовать встроенные в фейзер методы, для реализации коллизии. Но столкнулся с проблемой: поскольку здешняя физика рассчитана больше для платформеров - при отсутствии гравитации персонажа колбасило каждый раз, когда тот упирался в препятствие.
Поэтому пришлось придумывать собственную систему коллизии.
Но для того, чтобы ее описать, сначала я должен объяснить, как здесь вообще реализовано перемещение.
Итак, когда пользователь нажимает на область среди игрового поля - игра сохраняет координаты курсора, и с помощью Phaser.Physics тянет персонажа в соответствующем направлении.
Как я сказал выше, я мог просто, в каждом кадре, менять координаты персонажа. Но в таком случае, скорость его движения зависела бы от FPS, и это пришлось бы учитывать. А встроенная физика, все делает за меня.
Также, я не делал систему поиска пути. И если перед главным героем появляется препятствие - он должен просто останавливаться. К элементарности простая система.
Вернёмся назад. Коллизию я реализовал следующим образом:
игра постоянно проверяет все соседние от Главного Героя ячейки, и если на одну из них перемещение запрещено - игра прекращает его "тянуть" в этом направлении. В результате, если попросить персонажа двигаться по диагонали, и перед ним окажется препятствие - он будет продолжать двигаться вдоль "стены". В общем, мне нравится
Теперь, создадим врагов.
Во время разработки, я использую вот такого вот зомбака:
Его логика аналогична оной у ГГ, исключая лишь что точку направления определяет не курсор, а положение игрока.
Работает это так: если ГГ подходит на достаточную дистанцию до врага, то начинает двигаться в его направлении, но не забывая о коллизии
Да, в сим разе возникают комичные ситуации, когда враг не может обойти стену, но это уже будут проблемы геймдизайна.
Продолжим.
Боевая система.
Сделал я оную совершенно не изысканно (как и всё прочее):
Когда игрок приближается к врагу достаточно близко - запускается расчет нанесенного ущерба (нанесённый урон = сила атаки - броня)
А для визуализации, я накладываю на всех участвующих в бою анимацию с соответствующим эффектом (простите за качество):
Как по мне -- уже выглядит пристойно.
На сим -- кланяюсь, т.к. пока это всё.
Надеюсь было занимательно.
Ныне моя головная боль -- это инвентарь, так что следующий пост будет не скоро.
Но коли не загнусь -- продолжу