DefBall (codename). Месяц разработки
Всем привет!
Никогда не писал девлогов, но пост на Гамине к этому подтолкнул. Не знаю, насколько удачна эта затея, но попробовать давно стоило. Ну так вот.
Психолочное нематематичное вступление
Начну с того, что у меня есть вредная привычка. Время от времени я захожу на какой-нибудь CrazyGames и тешу свой мозг дофаминовыми играми с тупым геймплеем. Бывает, дело затягивается до четырёх утра, а на следующий день я «ни о чём не жалею». Чуть больше месяца назад шальной нейрон в моей голове решил повторить затею.
Игра называлась (и до сих пор называется) Battle Button Clicker. И так как я любитель несколько извращенных развлечений, спать в ту ночь я лёг с уставшим указательным пальцем правой руки. Но, что важнее, не только с ним, но и с парой мыслей:
- закликивание — зло;
- я ведь мог бы сделать так же, только лучше.
Разработчики бывают разные, и каждый случай уникальный. Я не исключение. 10-го мая 2024 года в моей голове роились
Есть чувство неудовлетворённости. Тяжесть в груди, как обычно бывает. Занятия, которые я себе придумываю, как будто не имеют шанса принести мне в конце концов желаемый профит.
Я снова начал копать в сторону Purple Dreams (вернее, Омнидельты). Неделю назад пришла в голову идея, и всё тут. Я вспоминаю, как начинал писать движок для реинкарнации Аиды на Си. Это долго. Это не то чтобы сложно. Но это долго. Это очень долго. Когда я начинаю подсчитывать, сколько времени у меня ушло просто на то, чтобы освоить азы кастомной аллокации и сколько времени прошло с начала работы над проектом, мне становится тяжело. Появляется мысль: я не успею. Непонятно, до чего не успею — до своей смерти или до скачка технологий, или ещё до чего-то.
С Дельтой — ну… Она подарила вдохновение на какое-то время. А теперь я опять не знаю, за что зацепиться, чтобы начать развитие проекта. Как будто я ищу вдохновения, радости, интриги; я как будто бы пытаюсь сам себя заинтересовать. Придумать сцены, которые заставят меня интересоваться.
А сейчас я испытываю тяжесть. Она мешает мне хотя бы просто начать… нет, она как будто бы лишает меня самой возможности чувствовать что-то другое, ведь она лежит сверху, а интерес лежит снизу. Как я почувствую интерес, если сверху — тяжесть?
Я знаю, что это было 10 мая, потому что сейчас передо мной лежит телефон, а в нём открытый SimpleMind с заметкой. Именно в тот день я возобновил привычку ежедневно выгружать свои мысли на физический носитель, по возможности устанавливать себе глобальные цели и постоянно себе о них напоминать.
Если кому-то покажется, что мысли были унылыми и депрессивными, то не переживайте. Уже на следующий день
Похоже, для меня решение в деньгах.
Сейчас это кажется таким простым. Как будто бы. Наверное, на деле не является. Но может быть, мне на самом деле надо просто взять готовый говно-движок и забабахать стрёмный вырвиглазный неотёсанный проект длиной в месяц (условно). Чтобы он просто начал приносить деньги. Ведь так проще. Не париться ни о чём. Просто что-нибудь сделать. Минуя всякие принципы, вопросы «а почему», «как лучше» и всё такое. Как было с финалкой.
Конечно, все мы, находящиеся здесь, понимаем, что решение для нас не только и не столько в деньгах. Если бы нам были нужны только деньги, мы бы точно не выбрали геймдев. Геймдев — это низкомаржинально. Геймдев — это высокорисково. Но мы раз за разом возвращаемся к играм, потому что у нас не остаётся другого выбора: нам нравится делать игры, и мы ничего не можем с этим поделать. Извращённые развлечения — действительно мой профиль, стоит признать это ещё раз.
Выбор движка
Тут всё оказалось совсем несложно. Я бы даже сказал, что не было никакого процесса выбора; вместо него был процесс попроще.
- Скачать и установить Unity.
- Создать пробный проект.
- Подождать 15 минут, пока пробный проект откроется.
- Удивиться количеству прошедшего времени, закрыть проект, и открыть его повторно.
- Подождать 10 минут, пока готовый проект откроется.
- Удивиться ещё раз, закрыть проект и открыть его повторно.
- Подождать 10 минут, пока готовый проект откроется, и сделать вывод, что 10 минут — это действительно 10 минут.
- Закрыть проект на Unity.
- Вспомнить про то, что когда-то пробовал Godot.
- Скачать и установить Godot.
- Создать пробный проект.
- Подождать несколько секунд, пока пробный проект откроется.
- Закрыть пробный проект.
- Открыть пробный проект.
- Обрадоваться.
- Снести Unity к херам.
Вот честно, ни разу не позавидовал Unity-разработчикам. Unity уже не тот. Конечно, по поводу Godot у меня тоже есть сомнения, но он в сравнении с Unity — как Blender четырёхлетней давности в сравнении с 3DS Max.
Может быть, вы ещё не слышали, но я пришел сюда для развязывания священных войн, так что скажувброшу прямо:
мне сразу же не понравился GDScript:
- обязательные точки с запятой, обозначающие конец строки и принятые во многих других нормальных языках, отменены; приходится переносить строки с помощью обратного слеша, и выглядит это настолько же уродски, как в макросах C++;
- фигурные скобки, обозначающие область видимости и границы
if...else
, заменены индентацией; - Visual Studio? Нет. Приходится пользоваться тем автокомплитом, который имеется в самом Godot (хотя я задумывался о том, чтобы попробовать VS Code плюс godot-tools);
- По той же причине забудьте об удобном рефакторинге — он даже в рамках одного скрипта не работает (есть
Ctrl-D
иCtrl-Shift-F
, но это совсем другое); - нет интерфейсов;
- класс из одного скрипта не всегда узнаёт о только что появившихся свойствах и методах класса в другом скрипте; спасает перезагрузка проекта (благо, длится она несколько секунд);
- присваивание внутри более сложного выражения не поддерживается, так что нельзя сделать
some_method(a = some_other_method())
(но этой фичи не было и в C#, так что можно и потерпеть); - автокомплит ломается при использовании
$
, хотя я таким всё равно не пользуюсь; - GDScript является интерпретируемым; я узнал об этом спустя месяц разработки;
- GDScript слизан с Python.
for i in 1e18: Python.burn_in_hell_with_exclamation_mark()
С другой стороны:
- к встроенному автокомплиту привыкаешь за неделю — ничего страшного, когда-то давно я и без него обходился;
- используя GDScript, никаких ограничений, связанных с .NET, не испытываешь и вообще о них не думаешь;
- по словам разрабов, из всех поддерживаемых языков GDScript имеет наиболее тесную интеграцию с движком, но я не проверял;
- так как большую часть времени я занимаюсь написанием кода, Godot стал для меня настоящим IDE с большой буквы… нет, со всех трёх заглавных букв. Ощущения от него примерно такие же, как от пользования Flash IDE в далеких нулевых: мне не приходится покидать редактор, чтобы начать писать код.
По большей части, ощущения от движка ровные и приятные. Можно сказать даже, что я испытываю удовольствие от его использования. Как минимум, мне не надо ждать десяти минут, чтобы открыть пустой проект.
Игры-референсы
В качестве референса был выбран DefBall образца 2016 года, который выглядел так:
Позже я развил идею в другую игру с кодовым названием Aida:
Моей задачей было сделать игру, похожую на Battle Button Clicker и использующую подходы из ДефБолла и Аиды. Про общую концепцию я напишу в одном из следующих постов, если они, конечно, будут. А пока что в этом тексте и так слишком много букв.
Начало разработки
Первым делом я вспомнил, что у меня 4K-монитор, а это, как оказалось, не всегда приятно. Я задумался, а как вообще делаются 2D-игры под разные разрешения, и вышел на статью, лежащую в доках Godot, как раз про это. Решил пока что рендерить в одно разрешение и растягивать отрендеренное по размеру окна.
Что дальше? Надо сделать главного героя — зонд игрока. Я засел в After Effects и сделал тестовый ассет. Импортировал его в движок, научил поворачиваться в сторону мышки. Но было видно, что вращение всего спрайта приводит к нехорошим искажениям, так что в дальнейшем надо было сделать по-другому.
Оказалось, Godot умеет рисовать круги программно и неплохо с этим справляется. Правда, без антиналожения. Метод рендеринга поддерживает нецелые радиусы, в результате круг уменьшается не рывками, а плавно:
Чтобы избежать использования ассетов на этапе разработки, я решил пока что рисовать блобы с помощью четырех кругов, как это было в Аиде. Тут же реализовал shrinking — растворение блоба в агрессивной окружающей среде и, как следствие, уменьшение его радиуса.
Затем я приделал к блобу физическое представление. Я унаследовал блоб от RidigBody2D
(чтобы в дальнейшем об этом пожалеть). А потом столкнулся с проблемой: при изменении радиуса соседние блобы перестают друг с другом взаимодействовать. Это происходило из-за того, что Shape2D
является ресурсом, а ресурсы не уникальны. Для того, чтобы можно было устанавливать радиус каждому блобу индивидуально, нужно было создавать дубликат формы, назначенной в сцене.
Дальше я попробовал создавать экземпляры CircleShape2D
в рантайме и навешивать их на блобы. Всё получилось. Но до полного создания блоба из-под кода, минуя сцены, я так и не добрался.
На тот момент меня ещё беспокоила зависимость геймплея от разрешения. Физика в Godot пиксельная, радиусы блобов тоже измеряются в пикселях, и при изменении разрешения (например, при игре на другом мониторе) какие-то вещи перестанут работать так, как надо. Я решил ввести аналог метрической системы. Отныне радиусы блобов задавались в условных внутриигровых юнитах, а при ините переводились в пиксели. То есть при создании блоба я устанавливал радиус radius
в нужное значение, а блоб уже затем рассчитывал значение _radius_px
. Ох и натерпелся я потом с этой системой. И ещё натерплюсь. Но, пожалуй, оно того всё же стоит.
Снаряды, враги и взрывы
После этого я реализовал снаряды, пока без пушек. Долго думал, как же быть с децентрализованной обработкой столкновений. Не придумал ничего лучше, чем просто смириться. В итоге не пожалел (но это только пока). Реализовал функционал появления блобов: их непрозрачность увеличивается от нуля до единицы после добавления на сцену.
И наконец-то добавил врагов. При столкновении с зондом враги должны были отнимать часть его здоровья (вернее, массы) и самоуничтожаться. При этом изначально я хотел сделать зонд неподвижным, как в оригинале; но после коллизии враг передавал зонду свой импульс, и тот начинал двигаться. В оригинальной Аиде у меня была самописная физика, и неподвижные объекты делались просто: я устанавливал массу блоба в +Infinity
, и он получался статическим; то ли я специально обрабатывал такие ситуации в движке, то ли просто все расчёты ускорения автоматически возвращали ноль из-за бесконечной массы — я уже не помню, да и лень смотреть. Так как в Godot у меня не было своей кастомной физики, я не мог просто установить массу зонда в бесконечность: физика руинилась, блобы пропадали с экрана. В итоге придумал применять к зонду силу, похожую на силу упругости: чем дальше от изначального положения, тем она выше. Выглядело интересно, и я эту штуку оставил.
Ввел понятия «логическая масса» и «физическая масса». Если вкратце, то они нужны были для того, чтобы отделить здоровье блоба от его поведения в физической подсистеме. Если подробнее, то вот
Возможно, придется вводить две массы: логическую и физическую. (Нужно заменить термин «логическая».) Логическая масса — это аналог здоровья блоба; она является произведением площади блоба на логическую плотность его материала. Физическая масса — это масса физического тела (внутри Godot’а); это произведение площади блоба и его физической плотности. Физическую массу я решил отделить от логической для того, чтобы было проще управлять поведением блобов при столкновении. Например, я хочу, чтобы у снаряда было много здоровья (логической массы), но при этом чтобы он не отталкивал врагов при столкновении; в этом случае логическую плотность я устанавливаю в обычное (или большое) значение, а физическую — в ноль (или в малое значение).
К слову, термин «логическая» я так и не заменил.
И всё-таки физика, сделанная за тебя — одновременно благословение и проклятие. Ты получаешь множество вещей из коробки, но лишаешься контроля. Если бы я захотел добавить в игру статические блобы, мне пришлось бы наследовать их не от RigidBody2D
, а от AnimatableBody2D
. Вроде бы, один класс блобов, просто одни неподвижны, а другие двигаются. Но в GDScript нет множественного наследования (может быть, оно к лучшему). Единственное решение, которое я придумал, — вводить классы поведений Behavior
и цеплять их к объектам, как компоненты в Unity. Но до этого я не дошёл, потому что пришлось бы полностью переписывать код.
Была ещё одна неприятная штука: снаряды после столкновения отлетали назад или начинали двигаться с меньшей скоростью; в оригинале такого не было.
Сделал отрисовку взрывной волны с помощью GradientTexture2D
. Меня беспокоило то, что при больших радиусах взрыва придется создавать слишком большую текстуру, и рендеринг будет тормозить. Поэтому я ограничил размер текстуры максимальным значением, а для больших взрывов просто растягивал спрайт, на который эта текстура была натянута. Но теперь на ней были видны пиксели; позже я решил эту проблему, просто установив фильтрацию в нужное значение: оказалось, и на низких разрешениях градиенты смотрятся отлично. Это ж градиенты.
После того, как с отрисовкой взрыва было покончено (но не насовсем), я добавил раздельные слои Node2D
для разных типов объектов: враги добавлялись на один слой, взрыв — на другой и так далее.
Реализовал расталкивающее поведение взрыва. Мне не нравилось, как взрыв себя ведёт, но на пока этого было достаточно.
К этому моменту я посмотрел на результаты своих трудов и подумал: пожалуй, для первой версии фич хватает. Стало быть, пора официально завершить работу над версией v0.0.0 и переходить к v0.0.1.
(На дату тега в TortoiseGit можно не смотреть, потому что я не пушил теги на гитхаб, а так как проект гулял с домашнего компа на рабочий и обратно, в какой-то момент локальный проект остался без тегов. Тег для версии v0.0.0 я создавал вручную гораздо позже.)
В описании к версии я указал:
Probe, Enemies, Bullets and Explosions are implemented.
Такая маленькая строчка, а сколько работы под ней спрятано!
Молния, пушки и приятные ништяки
Пришло время приступать к другим вещам. Я реализовал молнию, пока без визуальной части
а потом с ней. Отрисовку производил программно с помощью draw_line()
.
Наконец-то я решил проблему со снарядами, которая не давала мне покоя. Чтобы они не отскакивали и не теряли скорость при столкновениях, в _process()
я кэшировал текущую скорость в _prev_linear_velocity
, а в методе _on_body_entered()
восстанавливал ее из закэшированного _prev_linear_velocity
.
Да, это лечится настолько просто.
Сделал гансеты и пушки к ним. Наконец-то всё стало выглядеть, как в оригинале.
Гансет — это набор пушек. Пока что расстановка пушек контролируется относительным расстоянием до центра блоба-владельца и дельтой угла. Но такой подход не всегда красиво выглядит, и в будущем нужно будет ввести дополнительное условие для расстановки пушек.
К тому времени меня стала беспокоить ещё одна вещь: fluent interface. Несмотря на «неоптимизированность» самого подхода, он мне нравится: с его помощью можно удобно инициализировать сложные иерархии объектов, в большинстве случаев не прибегая к их именованию. Вот, например, как были сделаны мозги босса в Аиде:
В GDScript разделителем строк служит не точка с запятой, а, собственно, переход на новую строку; нельзя просто взять и разделить строку на несколько частей, нажав на Enter
, дописав нужную часть строки и поставив ;
(как это делается в C / C++ / C# / JavaScript и много где ещё). Перенести строку можно, используя обратный слеш, но это выглядит так себе. Решение, как всегда, оказалось простым: мы делаем простой метод fluent()
:
подготавливаем методы-инициализаторы, как обычно:
а потом оборачиваем всю инициализацию в вызов fluent()
, не забыв прикастовать результат к нужному типу:
Всё, что находится между открывающей и закрывающей скобкой при вызове любого метода, не будет делиться на части при переносе строк; GDScript понимает, что выражение ещё не завершено, поэтому нам не надо ставить обратные слеши в конце каждой незавершенной строки.
Вроде бы, мелочь, а приятно.
Мана и особые снаряды
Затем я реализовал методы _draw_circle()
и _draw_truncated_circle()
для отрисовки усеченного круга и круга с заданным количеством точек.
Это позволило мне добавить в игру ману. Казалось бы, отрисовка маны — простая задача, но, как оказалось, всё сложнее, и даже в оригинале я рисовал ее четырьмя частями.
Взрывные снаряды — то, чего не было в оригинале. Из-за того, что новые блобы появляются близко к центру взрыва, импульс, действующий на них, получается слишком большим, и их уносит далеко-далеко.
Искрящиеся снаряды — снаряды с молнией. Из-за отсутствия интерфейсов пришлось приделать способность обладания молнией вообще всем блобам на свете.
Тут я посмотрел, что у меня получилось, и снова сказал: молодец, могёшь!
- Lightning, GunSets with Guns, Probe’s mana, explosive Bullets and sparkling Bullets were implemented.
- Bullets don’t bounce off the Enemies after collision.
- Explosion now deals direct damage.
- Attenuation object was implemented; now it’s used inside Explosion.
- Enemies don’t stop accelerating towards the player’s Probe after being hit by Explosion.
Еще больше мелких ништяков
С новыми силами я сел за рисование задника. Вернее, не рисование, потому что рисовать я, видимо, не очень люблю. Я использовал After Effects и процедурный шум. На первое время пойдет.
На тот момент не было способа извне кастомизировать взрывы и молнии, приделанные к снарядам. Я ввел объекты-определения, наследующиеся от базового класса Def
; это легковесные объекты, подобные определениям в старом добром Box2D, которые содержат только данные, необходимые для инициализации объекта, и больше ничего.
Потом враги научились наносить урон зонду игрока. Вместе с тем появилась необходимость отображать минимальный и максимальный радиус зонда. Вообще мне хотелось придерживаться подхода, при котором GUI минимален или совсем отсутствует, а всю инфу о состоянии персонажа можно узнать, просто взглянув на него.
Затем я стал думать о том, как сделать врагов-пустышек, не наносящих урона зонду игрока. Такие враги могли бы пригодится на обучающих уровнях игры. Рассуждения привели меня к мысли о том, что придется вводить коэффициент прямого урона, как это было в оригинале. И хотя обсуждение камикадзе-взаимодействий должно было остаться за кадром, я всё же приведу цитату из лога:
Ввожу коэффициент прямого урона. Он необходим, так как если я захочу сделать пустышки, не наносящие урона, придется устанавливать логическую плотность в ноль. Это приведет к неопределенности радиуса. (…) Здесь логическую плотность можно рассматривать как защиту блоба, а коэффициент прямого урона — как атаку. (…) На самом деле, не всё так просто. Я не зря вводил понятие камиказде-взаимодействия: в случае попарного расчета урона могут возникать ситуации, когда оба блоба остаются живы. Камикадзе-взаимодействие решает эту проблему. Сначала блоб-камикадзе стремится истратить всю свою массу на прямой урон по противнику; если противник не выживает, камикадзе летит дальше. В этом случае расчет урона ведется в определенном порядке, и порядок его применения имеет большое значение.
Получается, я считал камикадзе-взаимодействия пережитком прошлого и хотел отказаться от него, а получилось так, что ранее ввел их неспроста. Даже собственные проекты со временем сильно забываются. Тем более проекты восьмилетней давности.
Последная фича, которую я реализовал, — эффекты. К ним относятся эффекты горения, оглушения, заморозки и прочие штуки, которые можно «прицепить» на объект и обновлять их вместе с ним. Я реализовал их следующим образом:
- каждый блоб обладает собственным экземпляром эффектора;
- эффектор, в свою очередь, может содержать ссылки на вложенные интеграторы;
- интеграторы могут быть разных типов: интегратор горения, интегратор оглушения и так далее;
- интегратор содержит эффекты своего типа: например, интегратор горения содержит эффекты горения;
- интегратор сам решает, каким образом ему обращаться со своими эффектами. Он может использовать самый мощный или самый продолжительный эффект, или объединять несколько маленьких эффектов в один большой;
- при добавлении эффекта к блобу мы просим эффектор: эй, эффектор, добавь эффект горения к блобу. Эффектор создает интегратор горения, если он ещё не создан, и добавляет к нему эффект.
- при обновлении блоб обновляет и эффектор, но блоб сам ответственен за применение эффектов к себе. В данный момент реализация именно такова.
Итоги
Конечно, было много другой работы, о которой я здесь не написал. Если навскидку, то:
- я портировал из старых проектов методы перевода цвета из HSL в RGB, потому что имеющиеся в Godot мне не подошли (или скорее, я торопился);
- дописал дополнительный класс для затухания взрывной волны; вместо степенной функции он использовал кривую Безье;
- более-менее поднастроил затухание взрывной волны (мда, на настройку механик иногда уходит слишком много времени);
- написал кастомный HSLA-градиент — нативный градиент Godot почему-то не справлялся с альфа-каналом;
- написал простую систему частиц для эффекта горения.
В итоге получилась играбельная технодемка, которой я зачем-то ни с кем не поделюсь, потому что устал и не буду билдить бинарники за просто так:
На этом всё. Я чуть-чуть замучился и хочу спать. Пишите, пожалуйста, в комментариях, любые мысли по поводу игры и девлога, куда мне следовало бы двигаться дальше, к какому издателю обращаться (хотя подождите. какой издатель. мы же инди), и вообще все мысли по поводу. Насколько перспективна задумка. Может, кому-то хочется поиграть в демку. Если будет надо, конечно же, соберу.
Ну, в общем, всё. Хорошо, что этот текст заканчивается. Подумали мы все.
Наверное, это моветон писать постскриптумы, так что.
P.
Вот теперь точно всё. Всем добра и удачи!
Обновление поста от 2024−05−23
Сделал билд под Винду. Скачать можно здесь.
Управление: стрельба — ЛКМ, взрыв — пробел.
- Зонд
- Максимальный радиус: 32
- Радиус смерти: 8.
- Логическая плотность: 1.
- Физическая плотность: 0.1.
- Гансет
- Характеристики всех снарядов.
- Скорость растворения всех снарядов, юнитов в секунду: 2.
- Логическая плотность: 1.
- Сопротивление среды (Godot-native, работает плохо): 0.6
- Главная пушка.
- Начальный радиус снарядов: 6.
- Начальная скорость снарядов: 200.
- Разрывные снаряды.
- Вероятность выпуска разрывных снарядов: 0.25.
- Дельта радиуса: 45.
- Импульс воздействия у эпицентра: 40.
- Прямой урон у эпицентра: 5.
- Время жизни взрыва: 0.4 секунды.
- Искрящиеся снаряды.
- Вероятность выпуска искрящихся снарядов: 0.25.
- Количество искр: 3.
- Собственный радиус молнии: 20.
- Урон на искру: 10.
- Две дополнительные пушки.
- Начальный радиус снарядов: 4.
- Начальная скорость снарядов: 200.
- Задняя пушка.
- Начальный радиус снарядов: 5.
- Начальная скорость снарядов: 200.
- Воспламеняющие снаряды.
- Все снаряды имеют 15-процентный шанс стать воспламеняющими.
- Урон в секунду: 50 единиц массы.
- Длительность горения: 2 секунды.
- Характеристики всех снарядов.
- Взрывной модуль.
- Дельта радиуса: 100.
- Кулдаун: 0.5 секунды.
- Стоимость: 30 единиц маны.
- Искровой модуль.
- Радиус: 40.
- Количество искр: 5.
- Урон на искру в секунду: 50.
- 21 мая 2024, 19:12
- 019
Хорошо и подробно, молодцом!
КМК, не хватает отдачи для подобного плана игры. Чтобы игрок лучше ощущал когда он играет правильно, а когда - нет.
1) Добавь импакта на получение урона (тряска экрана, например, если при этом вибрация на телефоне будет - ваще огонь).
2) И импакта на уничтоженного противника. Они сейчас просто сдуваются. Хочется какой-нибудь мини-взрывчик бы или хотя бы эффект лопающегося пузыря. Чтобы было визуальное поощрение, что я всё делаю правильно.
Тогда игра заиграет новыми красками, гарантирую.
Спасибо за обратную связь, с импактами обязательно поэкспериментирую.
Написано хорошо. Мне интересно демку попробовать.
По поводу физики, то в Godot мне с ней приходилось мучатся. Если погружаться, то как всем известно Godot разделён на модули, которые называются серверы (AudioServer, PhysicsServer2D и т.д.). Так вот если обращаться к ним, можно многое что делать "руками" с физическими телами и т.п. Это иногда помогает бороться с возникшими проблемами.
Ты нашёл аналогичную игру на веб-портале, и, возможно, захочешь там и свою выложить. Но размер движка не маленький (особенно с 4 версии), можно пересобрать с параметрами, чтобы уменьшить. Но есть ещё энтузиасты, которые ещё нашли возможности. Если пригодиться для HTML5-сборок:
В телеграмме увидел такое сообщение:
Ссылка на сообщение: https://t.me/webgamedev/1/11205
Ссылка на архив (я скачал и выложил): godot4pako.zip
Спасибо за сборку. Я опять же спустя месяц обнаружил, что Годо не хвалят за размеры билдов, немного расстроился. Подумал, ну ладно, раз уж он не для веба, то может хоть на компах попробую издаваться. В любом случае для меня сейчас важнее просто сделать прототип, который можно будет показать кому-нибудь, а там уже как пойдет. Ну и доделать игру до конца, конечно.
Из-под PhysicsServer2D я только запросы Shape Query выполнял, чтобы определять, до каких объектов дотягивается молния и взрыв. Мои первые эксперименты с физикой примерно год назад тоже были неутешительные (либо я делал что-то не так), поэтому я отложил Godot на потом.
Размер очень возрос в 4 версии, в 3 ещё терпимо. Для ПК мне кажется тут вообще не критично, я назвал бы его середнячком. Физика - "бессердечная..."
Ещё по поводу веба и 4 версии. В первых минорных версиях для работы в браузере обязательно требовалось поддержка SharedArrayBuffer. На itch, например, можно включить эту возможность (экспериментальная функция), но можно ли на других порталах? Для 3 версии движка такого нет. Вроде собирались вернуть поддержку GLES2, тогда всё будет лучше, но сейчас... Я новыми версиями не пользовался, но вот люди делают, значит, работает наверное.
Привет. Сборку сделал, обновил пост.
Попробовал. Приятно играется. Тут уже писали про ощущения от урона, так вот сейчас у противников не хватает, да они сдуваются, но мне это мало (особенно, когда краем глаза следишь за пушкой позади и пытаешься понять попадает она или нет). Объектов много и хочется видеть чтобы ты попадаешь более явно.
Также, предложил бы попробовать изменить поворот за мышью. Сейчас если провести по персонажу на противоположную сторону курсор, то пушки повернуть, что "не естественно". Возможно, просто делать плавный поворот в сторону мыши по самому маленькому углу. Но тогда немного уменьшиться динамика, ведь игрок не сможет быстро повернуть. Так что тут именно предложение попробовать, если интересно.
хм, у меня огромнейший рабочий проект на Unity открывается за 35 секунд.
Да, первичное создание может быть дольше, импорт, установка пакетов, но потом быстро.
Гифки классные
Может, я делаю что-то не так. Например, устанавливаю Юнити не на SSD. Но с последней версией, которую ставил, почему-то были долгие загрузки.
Офигенный пост! Было интересно читать о геймдизайнерских решениях.
А ещё девлог отлично дополнен гифками!
Проект выглядит весьма приятно, желаю дальнейших успехов)
Спасибо, от души!
Часть сделанных решений (как и претензии к пайтону) довольно странные, но написано здорово.
Благодарю.
Ну, вбросы они такие вбросы. Пожалуй, я действительно погорячился насчет пайтона. Если действительно понимать, как он работает, можно наворотить кучу дел, обучить кучу нейронок и захватить мир. Мои претензии основаны в основном на моей инертности и старческом нежелании принимать нововведения (а ведь я этот язык даже толком не знаю). И еще на одном открытии, которое я сделал ближе к тому моменту, как сел писать пост. Пусть знатоки языка меня поправят, но по моим представлениям строчка:
for i in 1e18: Python.burn_in_hell_with_exclamation_mark()
не заставит пайтон гореть в аду квинтиллион циклов (по крайней мере, на моем компьютере), потому что для ее выполнения пайтон сначала должен будет создать коллекцию, состоящую из квинтиллиона элементов, а затем с помощью итератора, спрятанного где-то под капотом, ее обойти. Естественно, для хранения такой коллекции понадобится в лучшем случае эксабайт памяти. Так что мои обвинения в сторону пайтона - это скорее крик души, чем что-то серьезное.
Я не знаток, но вроде как
for i in range(10**18)
не создает коллекции в python 3. В python 2 нужно было использовать xrange. А вот насчет gdscript не уверен, в 2017-м сказали while использовать.Да, не заставит... Но это скажем так лишь одна из ошибок. Мы в любом случае поняли твой псевдокод)
Данный код в
Python
не выполняется, потому что циклfor
пробегается по набору значений, помещает каждое значение в переменную:Python
сам по себе интерпретируемый язык (есть разные варианты "компиляции") и он разрабатывался как высокоуровневый язык с динамической типизацией, о высокой скорости работы и супер минимальном использование памяти речи не идёт. Это раз.GDScript
некорректно, они похожи синтаксисом, но их интерпретаторы разные.for i in range(10**18)
спокойно выполняет и сразу:Поэтому я остановился на версии 4.6.1. Пятая уже дичайше тормозит.
По поводу Python - я бросил его изучать когда понял что все может сломаться из-за лишнего Tab'а.
В таких случаях, кажется, советуют настраивать текстовый редактор таким образом, чтобы он заменял табы на пробелы. И отображать whitespace characters. Ну это я так, к слову.