Update README.md to include project description, developer documentation links, and license information.
CI / build-test (push) Successful in 1m6s
CI / build-test (push) Successful in 1m6s
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
# Архитектура mrgameeng
|
||||
|
||||
## Обзор
|
||||
|
||||
**mrgameeng** — кроссплатформенный 2D игровой движок на базе MonoGame 3.8.4
|
||||
(DesktopGL: Windows, Linux, macOS), .NET 8, C#.
|
||||
|
||||
Ключевое архитектурное решение — **ECS-first**: движок плотно интегрирует
|
||||
[Friflo.Engine.ECS](https://github.com/friflo/Friflo.Engine.ECS) (v3.6) как ядро
|
||||
модели объектов. Это самая производительная ECS-библиотека в .NET по результатам
|
||||
[Ecs.CSharp.Benchmark](https://github.com/Doraku/Ecs.CSharp.Benchmark): ноль аллокаций
|
||||
в горячих путях, archetype-хранилище, встроенные системы, события и индексы.
|
||||
|
||||
## Принципы
|
||||
|
||||
1. **Данные отдельно от логики.** Всё состояние игры — в компонентах
|
||||
(`struct : IComponent`), вся логика — в системах (`QuerySystem<T>`).
|
||||
Никаких `Update()` у игровых объектов и иерархий наследования сущностей.
|
||||
2. **Ноль аллокаций в кадре.** Системы, выполняющиеся каждый кадр, не должны
|
||||
аллоцировать память. Проверяется бенчмарками и code review.
|
||||
3. **Модульность.** Движок разбит на библиотеки по функциональным областям.
|
||||
Игра подключает только то, что использует.
|
||||
4. **Всё демонстрируется.** Каждая публичная возможность движка показана
|
||||
в `MrGameEng.Sample` и покрыта тестами (где логика тестируема без GPU).
|
||||
|
||||
## Модули
|
||||
|
||||
| Библиотека | Ответственность |
|
||||
|------------------------------|------------------------------------------------------------|
|
||||
| `MrGameEng.Core` | Игровой цикл (хост над `Game`), `EntityStore`, `SystemRoot`, сцены, время, жизненный цикл |
|
||||
| `MrGameEng.Graphics` | Собственный батчер-рендерер (см. «Рендеринг»), камера, спрайты, анимации, слои |
|
||||
| `MrGameEng.Input` | Абстракция ввода: клавиатура, мышь, геймпад; action maps |
|
||||
| `MrGameEng.Audio` | Звуковые эффекты и музыка |
|
||||
| `MrGameEng.Assets` | Runtime-загрузка ресурсов без Content Pipeline, кэш, `AssetRef<T>` |
|
||||
| `MrGameEng.Assets.Generator` | Roslyn incremental source generator: классы с типизированными хендлами ресурсов |
|
||||
|
||||
Планируемые модули (по мере развития): `Physics2D`, `Tilemap`, `UI`, `Particles`.
|
||||
|
||||
### Правило зависимостей
|
||||
|
||||
```
|
||||
MrGameEng.Graphics ─┐
|
||||
MrGameEng.Input ─┤
|
||||
MrGameEng.Audio ─┼──► MrGameEng.Core ──► MonoGame.Framework.DesktopGL
|
||||
MrGameEng.Assets ─┘ └──► Friflo.Engine.ECS
|
||||
```
|
||||
|
||||
Модули зависят **только от `Core`** и никогда друг от друга. `Core` зависит только
|
||||
от MonoGame и Friflo. Если двум модулям нужен общий тип — он переезжает в `Core`.
|
||||
|
||||
`MrGameEng.Assets.Generator` — особый случай: это анализатор (netstandard2.0),
|
||||
он подключается к проекту игры как `Analyzer`, в рантайме не участвует и не зависит
|
||||
от других модулей движка.
|
||||
|
||||
## Загрузка ресурсов (без Content Pipeline)
|
||||
|
||||
MGCB / Content Pipeline **не используется**. Все ресурсы лежат в папке `Assets/`
|
||||
проекта игры как сырые файлы (копируются в output при сборке) и грузятся в рантайме:
|
||||
|
||||
| Тип | Форматы | Как грузим |
|
||||
|----------------|-----------|---------------------------------------------------------|
|
||||
| Текстуры | png, jpg | `Texture2D.FromFile` |
|
||||
| Шрифты | ttf | FontStashSharp (растеризация в рантайме, динамический атлас) |
|
||||
| Звуки | wav | `SoundEffect.FromFile` |
|
||||
| Музыка | ogg | Стриминг через NVorbis + `DynamicSoundEffectInstance` |
|
||||
| Шейдеры | fx | Компиляция `dotnet-mgfxc` на этапе сборки (MSBuild target), в рантайме грузится байткод `.mgfx` |
|
||||
|
||||
`AssetManager` (в `MrGameEng.Assets`) грузит ресурсы по типизированному хендлу
|
||||
`AssetRef<T>` (путь + тип), кэширует по пути и владеет временем жизни (Dispose
|
||||
при выгрузке сцены/игры).
|
||||
|
||||
### Кодогенератор хендлов
|
||||
|
||||
`MrGameEng.Assets.Generator` — Roslyn **incremental source generator**. Файлы из
|
||||
`Assets/` передаются ему через `AdditionalFiles` (один glob в `.csproj` игры).
|
||||
По дереву папок он генерирует статический класс с типизированными хендлами,
|
||||
тип выводится из расширения файла:
|
||||
|
||||
```csharp
|
||||
// Assets/Textures/player.png →
|
||||
public static partial class GameAssets
|
||||
{
|
||||
public static class Textures
|
||||
{
|
||||
public static readonly AssetRef<Texture2D> Player = new("Textures/player.png");
|
||||
}
|
||||
}
|
||||
|
||||
// использование: Texture2D tex = assets.Load(GameAssets.Textures.Player);
|
||||
```
|
||||
|
||||
Обращение к ресурсу по строковому пути в коде игры — запрещено соглашением;
|
||||
строки существуют только внутри сгенерированного кода.
|
||||
|
||||
## Рендеринг
|
||||
|
||||
`SpriteBatch` в движке **не используется** — в `MrGameEng.Graphics` свой батчер,
|
||||
спроектированный под ECS.
|
||||
|
||||
### Камера
|
||||
|
||||
Ортографическая 2D-камера — из коробки, отдельная сущность с компонентом `Camera`:
|
||||
|
||||
- Позиция, зум, поворот, опциональные границы мира (clamp).
|
||||
- Строит ортографическую view-projection матрицу; виртуальное разрешение
|
||||
с letterbox/scale под размер окна.
|
||||
- Активная камера — одна на сцену. Утилиты `ScreenToWorld` / `WorldToScreen`.
|
||||
|
||||
### Слои (render layers)
|
||||
|
||||
- Слои регистрируются явно при настройке рендерера: имя + порядок отрисовки
|
||||
(например, `Background → World → Foreground → UI`).
|
||||
- У каждого слоя — **пространство**: `World` (через трансформ камеры) или
|
||||
`Screen` (screen-space, без камеры — HUD, UI).
|
||||
- Сортировка внутри слоя — по `float depth` спрайта; слой можно переключить
|
||||
в режим **Y-sort** (depth = позиция Y, для top-down игр).
|
||||
- Спрайт ссылается на слой компактным id (`LayerId`), не строкой.
|
||||
|
||||
### Culling
|
||||
|
||||
- Перед записью вершин AABB спрайта (с учётом rotation/scale) проверяется против
|
||||
world-прямоугольника камеры; невидимые сущности не попадают в батчер.
|
||||
- Screen-space слои не куллятся по камере (они всегда на экране).
|
||||
- Culling — простой broad-phase в draw-системе, без пространственных структур;
|
||||
если профилирование покажет, что на больших мирах его не хватает,
|
||||
добавим spatial hash отдельным этапом.
|
||||
|
||||
### Батчер
|
||||
|
||||
- Draw-системы итерируют чанки Friflo (`Chunks<Position, Sprite, ...>`) и пишут
|
||||
вершины напрямую в CPU-буфер батчера — без промежуточных списков и аллокаций.
|
||||
- Порядок сортировки: **слой → depth (или Y) → текстура**; спрайты с одной
|
||||
текстурой сливаются в один draw call (динамический vertex buffer + общий
|
||||
quad index buffer).
|
||||
- Текстурные атласы — первоклассный гражданин: `Sprite` хранит регион атласа,
|
||||
спрайты одного атласа батчатся автоматически.
|
||||
- Цель по производительности: ≥100k спрайтов при 60 FPS на среднем десктопе,
|
||||
0 аллокаций на кадр. Контролируется бенчмарками (BenchmarkDotNet) и
|
||||
стресс-сценой в Sample.
|
||||
|
||||
## Интеграция ECS
|
||||
|
||||
- На каждую сцену создаётся свой `EntityStore` (мир) и **два** `SystemRoot`:
|
||||
`UpdateSystems` (логика) и `DrawSystems` (рендер). Порядок систем детерминирован
|
||||
и задаётся явно при регистрации.
|
||||
- Модули подключаются к сцене extension-методами из `OnLoad`:
|
||||
`scene.UseRenderer2D()`, `scene.UseInput()`, `scene.UseSpriteAnimation()`,
|
||||
`context.UseAssets()`, `context.UseAudio()`. Сервисы модулей живут в
|
||||
`EngineContext.Services` (общие между сценами), системы — в сцене.
|
||||
- Базовый трансформ — один компонент `Transform2D` (position + rotation + scale):
|
||||
один массив на чанк дешевле трёх отдельных компонентов.
|
||||
- Модули поставляют готовые компоненты и системы
|
||||
(например, `Sprite` + `SpriteRenderSystem` из `Graphics`), игра добавляет свои.
|
||||
|
||||
## Кадр (frame pipeline)
|
||||
|
||||
```
|
||||
Game.Update ──► Scene.Update ──► SystemRoot (Update-фаза): input → логика игры → анимации
|
||||
Game.Draw ──► Scene.Draw ──► SystemRoot (Draw-фаза): камера → culling → запись вершин в батчер → flush (draw calls)
|
||||
```
|
||||
|
||||
## Структура репозитория
|
||||
|
||||
```
|
||||
MrGameEng.sln
|
||||
src/ библиотеки движка (MrGameEng.*)
|
||||
samples/ MrGameEng.Sample — демо всех возможностей
|
||||
tests/ xUnit-тесты, по проекту на библиотеку
|
||||
docs/ документация (русский)
|
||||
```
|
||||
|
||||
## Зафиксированные версии
|
||||
|
||||
| Зависимость | Версия | Назначение |
|
||||
|---------------------------------|----------|----------------------------------|
|
||||
| .NET (target framework) | net8.0 | |
|
||||
| MonoGame.Framework.DesktopGL | 3.8.4.1 | Базовый фреймворк |
|
||||
| Friflo.Engine.ECS | 3.6.0 | ECS |
|
||||
| FontStashSharp.MonoGame | 1.5.6 | Шрифты (ttf) в рантайме |
|
||||
| NVorbis | 0.10.5 | Декодирование ogg |
|
||||
| dotnet-mgfxc (dotnet tool) | 3.8.4.1 | Компиляция шейдеров при сборке |
|
||||
@@ -0,0 +1,24 @@
|
||||
# Roadmap
|
||||
|
||||
Базовый движок (ядро, рендер, ассеты с кодогенерацией, ввод, звук, демо) реализован —
|
||||
текущие возможности описаны в [architecture.md](architecture.md). Здесь — только планы.
|
||||
|
||||
Пункт считается завершённым, когда покрыт тестами и показан в `MrGameEng.Sample`;
|
||||
после завершения он убирается отсюда и фиксируется в architecture.md.
|
||||
|
||||
## Ближайшее
|
||||
|
||||
- [ ] Текст: рендер шрифтов FontStashSharp через батчер движка
|
||||
(новый модуль `MrGameEng.Text`, потребует зависимости от Graphics)
|
||||
- [ ] MSBuild target для автоматической компиляции `.fx` → `.mgfx` через `dotnet-mgfxc`
|
||||
(лоадер `.mgfx` в AssetManager уже готов; target — когда появится первый кастомный шейдер)
|
||||
|
||||
## Бэклог
|
||||
|
||||
- Physics2D (выбор библиотеки: Aether.Physics2D / своя)
|
||||
- Tilemap (поддержка Tiled)
|
||||
- Particles
|
||||
- UI
|
||||
- Бенчмарки BenchmarkDotNet для систем (сейчас производительность контролируется стресс-сценой)
|
||||
- Стабильная сортировка спрайтов с равным ключом (сейчас порядок не гарантирован между кадрами)
|
||||
- Spatial hash для culling на очень больших мирах (если профилирование покажет необходимость)
|
||||
Reference in New Issue
Block a user