Split the platform out of Core: new Host library + HeadlessHost
CI / build-test (push) Successful in 1m24s
CI / build-test (push) Successful in 1m24s
Core now depends only on Friflo.Engine.ECS — no MonoGame, no platform. The windowed MonoGame host moves to the new MrGameEng.Host library: GameHost, GameHostOptions, visual scene transitions (OverlayTransition, Transitions.Fade/Wipe, TransitionRenderer) and the Input feature (namespace MrGameEng.Input is unchanged). Transition timing stays in Core (SceneManager exposes ActiveTransition/TransitionCoverage/ TransitionPhase; the host draws the overlay). EngineContext loses its GraphicsDevice property: hosts publish the device as a service and graphics code reads it via context.GetGraphicsDevice() in Graphics. Core gains HeadlessHost: a fixed-timestep loop without a window or GPU (Tick/RunTicks, Run with wall-clock pacing and lag resync) for dedicated servers, batch simulation and tests. Graphics and Audio now carry their own MonoGame.Framework.DesktopGL reference instead of inheriting it from Core. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
79d406a9f4
commit
2ac074004a
+25
-13
@@ -33,7 +33,8 @@
|
||||
|
||||
| Библиотека (сборка) | Фичи (неймспейсы) и ответственность |
|
||||
|------------------------------|------------------------------------------------------------|
|
||||
| `MrGameEng.Core` | Игровой цикл (хост над `Game`), `EntityStore`, `SystemRoot`, сцены, время (`GameClock.TimeScale`; `GameSpeed` — дискретная скорость пауза/1×/3×/6× поверх часов; `Calendar` — игровые дни поверх масштабированного времени, `context.UseCalendar(...)`; `Climate` — непрерывная сезонная/суточная температура и сезон поверх календаря, `context.UseClimate(...)`), жизненный цикл. **Input** (`MrGameEng.Input`, `Core/Input/`): клавиатура, мышь, геймпад, action maps |
|
||||
| `MrGameEng.Core` | Платформо-независимое ядро (зависит только от Friflo): `EngineContext`, `EntityStore`, `SystemRoot`, сцены и переходы (тайминг — `Transition`, `SceneManager`; визуал переходов — в `Host`), время (`GameClock.TimeScale`; `GameSpeed` — дискретная скорость пауза/1×/3×/6× поверх часов; `Calendar` — игровые дни поверх масштабированного времени, `context.UseCalendar(...)`; `Climate` — непрерывная сезонная/суточная температура и сезон поверх календаря, `context.UseClimate(...)`), жизненный цикл, `ServiceRegistry`, `Log`. **`HeadlessHost`** — цикл без окна и GPU на фиксированном тике (`Tick`/`RunTicks`/`Run` с realtime-пейсингом): дедикейтед-серверы, батч-симуляция, тесты |
|
||||
| `MrGameEng.Host` | Оконный MonoGame-хост: `GameHost` (обёртка над `Game` — цикл, окно, `GraphicsDeviceManager`; публикует `GraphicsDevice` сервисом в контексте), визуальные переходы сцен (`OverlayTransition`, фабрики `Transitions.Fade/Wipe`, `TransitionRenderer`). **Input** (`MrGameEng.Input`, `Host/Input/`): клавиатура, мышь, геймпад, action maps |
|
||||
| `MrGameEng.Graphics` | Собственный батчер-рендерер (см. «Рендеринг»), камера, спрайты, анимации, слои. **Tilemaps** (`MrGameEng.Tilemaps`, `Graphics/Tilemaps/`): тайловые карты кодом — `TileGrid` + `TileSet` + компонент `Tilemap`, отрисовка видимых клеток через батчер. **Lighting** (`MrGameEng.Lighting`, `Graphics/Lighting/`): амбиент день/ночь поверх `Calendar` → `Renderer2D.AmbientLight`, `scene.UseDayNight(renderer)`; по-клеточный лайтмап — `LightmapBuilder` (амбиент × окклюзия + точечные `PointLight` с трассировкой теней), накладывается multiply поверх мира через `scene.UseLighting(...)`, сэмплируется `Lighting.SampleAt` |
|
||||
| `MrGameEng.Audio` | Звуковые эффекты и музыка (NVorbis); `AudioManager` с `SoundVolume`/`MasterVolume` (одна ручка на эффекты и музыку) |
|
||||
| `MrGameEng.Content` | Пайплайн контента. **Assets** (`MrGameEng.Assets`): runtime-загрузка без Content Pipeline, кэш, `AssetRef<T>`. **Atlases** (`MrGameEng.Atlases`): текстурные атласы — сборка из дерева картинок (`AtlasBuilder`) и рантайм-загрузка (`TextureAtlas`), CLI `tools/MrGameEng.AtlasTool`. **Mods** (`MrGameEng.Mods`): система модов — порядок загрузки, JSON-дефы, локализация, слияние деревьев контента |
|
||||
@@ -69,19 +70,27 @@
|
||||
### Правило зависимостей
|
||||
|
||||
```
|
||||
MrGameEng.Audio ─┐
|
||||
MrGameEng.Graphics ─┼──► MrGameEng.Core ──► MonoGame.Framework.DesktopGL
|
||||
│ └──► Friflo.Engine.ECS
|
||||
MrGameEng.Host ─┐
|
||||
MrGameEng.Audio ─┤
|
||||
MrGameEng.Graphics ─┼──► MrGameEng.Core ──► Friflo.Engine.ECS
|
||||
│
|
||||
MrGameEng.Content ─┤
|
||||
MrGameEng.Simulation ─┤ (Content — за Texture2DRegion,
|
||||
MrGameEng.UI ─┴──► MrGameEng.Graphics Simulation/UI — за Transform2D/рендер)
|
||||
```
|
||||
|
||||
Библиотека зависит **только от `Core` и `Graphics`**. `Core` зависит только от MonoGame
|
||||
и Friflo. Если двум библиотекам нужен общий тип — он переезжает в `Core` (или, если это
|
||||
графический тип, в `Graphics`). `Content` тянет `Graphics` (атласы выдают
|
||||
`Texture2DRegion`); `Simulation` тянет `Graphics` (`Collisions` использует `Transform2D`,
|
||||
`RectF`); `UI` — только `Core` (Myra рисует своим SpriteBatch).
|
||||
Библиотека зависит **только от `Core` и `Graphics`**. `Core` зависит только от Friflo —
|
||||
ни MonoGame, ни другой платформы: благодаря этому симуляция запускается и без окна
|
||||
(`HeadlessHost`). MonoGame (`MonoGame.Framework.DesktopGL`) тянут платформенные и
|
||||
графические библиотеки: `Host`, `Graphics`, `Audio` (и транзитивно их потребители).
|
||||
Платформенные ресурсы (например `GraphicsDevice`) хосты публикуют сервисами в
|
||||
`EngineContext.Services`; графический код достаёт девайс через
|
||||
`context.GetGraphicsDevice()` (расширение в `Graphics`). На `Host` не зависит никто,
|
||||
кроме самой игры — это точка входа оконной платформы. Если двум библиотекам нужен общий
|
||||
тип — он переезжает в `Core` (или, если это графический тип, в `Graphics`). `Content`
|
||||
тянет `Graphics` (атласы выдают `Texture2DRegion`); `Simulation` тянет `Graphics`
|
||||
(`Collisions` использует `Transform2D`, `RectF`); `UI` — только `Core` (Myra рисует
|
||||
своим SpriteBatch).
|
||||
|
||||
Фичи, собранные в одну библиотеку, делят её набор пакетов (например, `Content` несёт и
|
||||
FontStash, и StbImage). Тяжёлые/опциональные зависимости (Myra, NVorbis) держим в
|
||||
@@ -345,12 +354,15 @@ CLI-обёртка: `dotnet run --project tools/MrGameEng.AtlasTool -- <исто
|
||||
|
||||
- `SceneManager` владеет активной сценой; обычное переключение откладывается до начала
|
||||
следующего кадра (сцена никогда не выгружается посреди собственного кадра).
|
||||
- `Scenes.Switch(scene, Transition.Fade(0.5f))` — переключение с визуальным переходом:
|
||||
- `Scenes.Switch(scene, Transitions.Fade(0.5f))` — переключение с визуальным переходом:
|
||||
фаза закрытия (старая сцена живёт) → своп при полном покрытии → фаза открытия.
|
||||
Тяжёлый `OnLoad` новой сцены скрыт за полностью закрытым экраном.
|
||||
- Встроенные переходы: `Transition.Fade(duration, color)` и `Transition.Wipe(duration, color)`
|
||||
(шторка). Свои — наследованием от `Transition` (рисование через `TransitionRenderer.Fill`
|
||||
в нормализованных координатах экрана).
|
||||
- Тайминг-машина (`Transition` — длительности фаз, покрытие) живёт в `Core` и работает
|
||||
и в headless-контексте; визуал — в `Host`: встроенные `Transitions.Fade(duration, color)`
|
||||
и `Transitions.Wipe(duration, color)` (шторка). Свои — наследованием от
|
||||
`OverlayTransition` (рисование через `TransitionRenderer.Fill` в нормализованных
|
||||
координатах экрана); `GameHost` рисует оверлей поверх сцены, читая
|
||||
`Scenes.ActiveTransition`/`TransitionCoverage`/`TransitionPhase`.
|
||||
- Переходы идут по **unscaled**-времени: работают при паузе геймплея (`TimeScale = 0`).
|
||||
- Повторный `Switch` во время перехода заменяет целевую сцену, не перезапуская переход.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user