Voidwalker - я напишу тебя на джава!

Я напишу тебя на джава, рукою сильной скомпилю, и в луговых пахучих травах, дебагом сильным отлюблю! - Н. Б. Джигурда

Сегодня вас ждут новости разработки, структура проекта и немного про сборку мусора в Java, Unreal Engine и Unity.

Дневник разработчика

Шли четвертые сутки разработки. Теперь в нашей прелестной игре появился антиалиасинг, сердечки для восполнения здоровья (работающие как пули наоборот ❤), раздельная реализация FTS и рендеринга, а окно стало resizable с корректным расчётом расстояний.

Тот, кто любит цветы, Тот, естественно, пулям не нравится. Пули — леди ревнивые. Стоит ли ждать доброты? - Е. А. Евтушенко

Джигурда и структура

А игра написана на Java. Вот так выглядит структура, необходимая для отрисовки видоса выше:

. ├── GameApplication.java ├── Game.java ├── FrameVTSThread.java ├── UpdateFTSThread.java ├── config │   ├── HealthConfiguration.java │   └── KeybindingConfiguration.java ├── model │   ├── Drawable.java │   ├── HitBox.java │   ├── Position.java │   ├── feature │   │   ├── Collidable.java │   │   ├── Destroyable.java │   │   ├── Interactable.java │   │   ├── Movable.java │   │   └── Playable.java │   └── game │   └── State.java ├── sprite │   ├── Bullet.java │   ├── FractalTree.java │   ├── Heart.java │   ├── Obstacle.java │   └── Player.java └── tasks └── CollisionDetection.java

С описанием:

. ├── GameApplication.java - входная точка в приложение, создание инстанса игры и запуск потоков ├── Game.java - контейнер с игрой, её состоянием, окном, методами отрисовки и шагов ├── FrameVTSThread.java - поток для рендеринга игры (выдает over 3000 FPS) ├── UpdateFTSThread.java - поток для шагов игры (работает в строгие 60 Гц) ├── config │   ├── HealthConfiguration.java - здоровье игрока, HP препятствий и урон оружия │   └── KeybindingConfiguration.java - раскладка ├── model │   ├── Drawable.java - рисуемый элемент (имя, позиция, хитбокс) │   ├── HitBox.java - хитбокс │   ├── Position.java - позиция (x, y) │   ├── feature │   │   ├── Collidable.java - признак "сталкиваемости" │   │   ├── Destroyable.java - признак разрушаемости │   │   ├── Interactable.java - признак наличия взаимодействий │   │   ├── Movable.java - признак перемещения (ускорение) │   │   └── Playable.java - признак управляемости │   └── game │   └── State.java - состояние игры, размер окна, лимит FPS/FTS, ускорение, очки ├── sprite │   ├── Bullet.java - пуля, содержит KeyListener на кнопку стрельбы и логику удара │   ├── FractalTree.java - дерево, рисуется в фоне │   ├── Heart.java - сердце, появляется когда HP падает ниже 30% │   ├── Obstacle.java - препятствие, по 3 штуки до уничтожения, снимают 30% HP │   └── Player.java - игрок, содержит KeyListener на влево-вправо и прыжок └── tasks └── CollisionDetection.java - задача поиска коллизий (находит объекты с признаком Collidable и пересечением координат, и сталкивает их друг с другом

Вот и всё, что нужно для движка Mario-подобной игры.

Системные требования, Java и сборка мусора

На данный момент ваш ПК должен обладать не менее 8 Мб ОЗУ для игры в Voidwalker в 3000 FPS с просадками шагов (FTS - не путать с FPS), и 16 Мб ОЗУ для комфортной игры.

При этом сама игра занимает всего около 6 Мб в ОЗУ. Тогда откуда 16 Мб?

Здесь язык Java играет особую роль. Пару статей назад я показывал, как спрайт без кэширования может отожрать вагон памяти. Это связано с тем, что Java - язык со сборкой мусора (GC - Garbage Collector).

В отличии от Си, где разработчик самостоятельно управляет жизненным циклом каждой переменной, в Java он не управляет памятью, и может только создавать новые объекты, а GC уже самостоятельно решает в какой момент ей остановить выполнение приложения и выполнить сборку мусора (неиспользуемых более переменных).

Современные GC выполняют эту работу параллельно с работой приложения, но это аффектит утилизацию CPU. Если памяти слишком мало, а игра постоянно спавнит новые объекты (по кнопке стрелять, например), для отрисовки нового объекта нужно освободить память от элементов, которые уже отмечены на удаление.

8 Мб ОЗУ дают нам всего около 2 Мб пространства для маневра, а мы генерируем одних только фреймов более 3000 каждую секунду, и в таком случае GC вынужден постоянно запускаться и FTS падает с 60 до приблизительно 50 (то есть 17% единицы времени затрачивается на сборку мусора).

Со сборкой мусора есть несколько интересных подходов, в том числе так называемый No GC - когда мы просто даём много памяти и падаем, когда свободной не осталось. А еще с прямыми руками и при большом желании можно написать приложение даже на Java, которое вообще не будет аллоцировать новых элементов в процессе работы.

Большая часть игр (движков) разрабатывается в итоге на Си или C++, которые дают полный контроль над памятью - например, Unreal Engine, id Tech и CryEngine.

При этом Unity написан на C#, который, как и Java, использует GC. И как мы видим, гигантской проблемы с этим не наблюдается, но и жирного AAA на нём маловато откровенно.

Задавайте вопросы, пишите письма, всех поцеловал!

Предыдущая часть саги:

1
11 комментариев