Кодовый парусный корабль #3
Первым делом хочу выразить благодарность всем пользователям, которые давали мне годные советы, что помогло улучшить...эмм...архитектуру этого модуля, его внутренние связи и тд.
Предыдущий пост: http://pikabu.ru/story/kodovyiy_parusnyiy_korabl_2_5089935
Если нет желания читать, самые актуальные файлы тут: https://gitlab.com/open_sourse/pirate
Начну с краткого пояснения:
1) Я решил отойти от модели проектирования, когда сначала писался класс на чистом языке и тд. (совет @DDeni). Изначально мне казалось что более удобно хранить информацию в виде чистых классов, потому что так просто организовать магазин, но потом подумал еще раз и понял, что мне так или иначе нужно будет хранить спрайты, иконки и прочее для организации магазина.
2) Я убрал лишние методы Instantiate() в пользу использования пула объектов (совет @HartMagic), однако, сам пул объектов не добавляю в список файлов, ибо он достаточно топорный (один класс, 2 метода, 2 переменные на все возможные объекты) и не имеет прямого отношения к теме постов (конечно, без него не получиться запустить проект просто скопировав его, но, думаю, этим никто не занимается, но при желание можно заменить метод Pop на Instantiate(), а Push на Destroy()). Сначала я думал над тем, чтобы купить уже готовый пул, но посмотрев количество файлов и скриптов в продающихся пакетах передумал.
3) Переделана модель стрельбы и пушек (совет @fon.prima). Данный раздел также затрагивает и пункт 1.
Ладно, предисловие закончилось. Начнем с рассмотрения основного класса корабля:
Изменений визуально немного. Добавлены два скрипта - shipControll, содержащий методы управления кораблем и ShipInfo, содержащий просто данные о корабле, которые ранее были вынесены в класс App.Items.Ship.Ship, ныне канувший в лета. Также лист для пуль теперь один, причины изменения в подходе к стрельбе - о ней позже.
Сразу обращу ваше внимание: все объекты, которые могут умереть (в принципе), включают в себя атрибут, который добавляет класс Shape (элемент для объектного пула). Он нужен для возврата объекта в пул и выглядит так:
Итак, рассмотрим класс управления кораблем:
Метод Move: управляет кораблем. По кнопкам W и S паруса поднимаются и опускаются (если подняты, то набор скорости идет, если нет - то убывание скорости). Также я добавил проверку на то, что если скорость больше 10 (цифра от балды), то только тогда корабль может делать повороты, ибо по логике корабль не умеет поворачивать с минимальной скоростью. Таким образом, я убрал зависимость порядка исполнения Move и Rotation, которая была в предыдущем посте.
В самом низу метода тройной тернарный оператор ограничивает максимальную и минимальную скорость корабля.
Метод Fire: тут мы по кнопке для каждой пушке в одном из листов запускаем метод Fire. Более подробно будет рассмотрено в классе Cannon.
Метод Rotation: без изменений (убрал только изменения булевой переменной moving, но об этом сказано выше).
Вот так теперь выглядит наш корабль с пушками (белые зефирки - это пушки).
А вот так выглядит движение:
Итак, перейдем к классу пушки, который, вероятно, самый занятный из всего поста:
Это первая часть класса, весь не влез.
Переменная power отвечает за силу пушки и начальный импульс снаряда.
Метод Loaded: ранее этот метод был в похожем классе, но другом. Изменения: метод стал возвращать bool ииии...все! В остальном все так же. 26 строка - берем снаряд из пула, так что не смущайтесь её внешнего вида.
Метод Fire: если пушка не заряжена, то ничего не делает. Иначе, запускает метод FireProcess и корутину перезарядки. Вот насчет правильности выбора корутины я не уверен, ибо, возможно, есть менее затратные по ресурсам методы, но в голову ничего не пришло подходящего. Если есть идея - сообщайте в комментарии, буду благодарен.
Метод FireProcess: задает полученному снаряду начальную точку, наполняет полями и дает импульс для полета. Также тут мы записываем в переменную lastFire время выстрела (нужно для перезарядки с помощью следующего метода). По поводу пули и её импульса поговорим чуть позже.
Метод Recharging: словами делает следующее: если текущее время больше времени последнего выстрела и скорость огня, то перезарядить. К слову, по профайлеру, вызов этой корутины занимает относительно много ресурсов всего 1 раз - в момент вызова.
Рассмотрим результат стрельбы из разнообразных пушек:
Вот так мы стреляем из одинаковых пушек (снаряды летят вместе, может стоит сделать небольшой заброс, чтобы снаряды вылетали с задержкой для красоты, но это скорее всего будет решено небольшим рандомным изменением силы пушек при их установке на корабль)
А вот так мы стреляем из пушек с разной силой (тут находятся позиции пуль за равное поле после выстрела). Цифрами показана сила пушки (чем меньше сила, тем более медленно летит снаряд и в целом преодолевает меньшую дистанцию)
А вот так стрельба выглядит в динамике.
Итак, перейдем к классу снаряда:
Класс снаряда: Мы сюда внесли понятие импульса, времени "пробуждения", что по сути время появления и времени жизни.
На каждый кадр пуля пересчитывает свою позицию. Отмечу, что был изменен способ изменения позиции с transform.Translate(), потому что этот метод тут не походит, так как он может изменять позицию объекта по Y, что для нашего 2д пространства недопустимо.
Также тут мы добавляем к текущей скорости импульс, умноженный на дельту времени, что является способом ускорения снаряда.
Остаток класса проверяет не закончилось ли время жизни пули и если закончилось, то возвращает её в пул.
Теперь проект имеет следующую структуру (но в гит не положил файлы, которые не имеют отношения к кораблю).
На этом все. В следующем посту мы добавим такие механики:
1) получение урона кораблем;
2) нанесение урона снарядами;
3) возможность уничтожения корабля;
4) зависимость скорости поворота корабля от текущей скорости движенияю
(в целом, я не могу полноценно сейчас придумать что еще добавить в след. пост, ибо этих позиций может быть мало.)
Всем спасибо за внимание!
Лига Разработчиков Видеоигр
6.6K пост22.1K подписчиков
Правила сообщества
ОБЩИЕ ПРАВИЛА:
- Уважайте чужой труд и используйте конструктивную критику
- Не занимайтесь саморекламой, пишите качественные и интересные посты
- Никакой политики
СТОИТ ПУБЛИКОВАТЬ:
- Посты о Вашей игре с историей её разработки и описанием полученного опыта
- Обучающие материалы, туториалы
- Интервью с опытными разработчиками
- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе
НЕ СТОИТ ПУБЛИКОВАТЬ:
- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры
- Посты, единственная цель которых - набор команды для разработки игры
- Посты, не относящиеся к тематике сообщества
Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.
ЗАПРЕЩЕНО:
- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции
- Выдавать чужой труд за свой
Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.
О РАЗМЕЩЕНИИ ССЫЛОК:
Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:
- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества
- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз
- Cсылка размещается в формате: "Страница игры в Steam: URL"