Pathfinding (depends on Core only): GridPathfinder with A* (octile/
Manhattan heuristic), Dijkstra and BFS over a game-implemented
IPathGrid; 4/8 connectivity, diagonals never cut corners. FlowField +
FlowFieldBuilder (multi-source Dijkstra) give crowds O(1) steering per
agent per frame. All buffers are grid-sized once and invalidated by a
generation stamp - repeated queries allocate nothing and clear nothing.
Collisions (Graphics exception: Transform2D, RectF): Collider component
(circle/AABB, offset, two-way layer masks), CollisionWorld - a uniform
spatial hash on flat arrays rebuilt from scratch each tick (O(n) for
movers, zero alloc after warm-up, deterministic pair order), pair
collection, QueryAabb and closest-hit Raycast. scene.UseCollisions()
registers CollisionSystem after movement systems.
30 new tests (string-map mazes, cost weighting, corner cutting, flow
descent; pair/mask/query/raycast). Sample gains a PathfindingScene
('path' console command): click to set the goal, 250 agents follow the
flow field, the A* path is highlighted, colliding agents flash red.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.4 KiB
mrgameeng
2D game engine built on MonoGame 3.8.4 (DesktopGL), .NET 8, C#. ECS-first: Friflo.Engine.ECS 3.6 is tightly integrated into the core — all gameplay state lives in components, all logic in systems.
Design docs and developer documentation live in docs/ and are written in Russian.
Keep them up to date when architecture or conventions change.
Solution layout
src/ MrGameEng.* engine libraries (one per functional area)
samples/ MrGameEng.Sample — demo game showcasing every engine feature
tests/ xUnit test projects, one per engine library
docs/ architecture, conventions, roadmap (Russian)
Engine modules: Core (game loop, ECS world, scenes, time), Graphics (custom batched
renderer, camera, sprites), Input, Audio, Assets (runtime loading, no content
pipeline), Assets.Generator (Roslyn source generator for typed asset handles),
Atlases (texture-atlas builder + runtime loader; CLI wrapper in tools/MrGameEng.AtlasTool),
Tilemaps (code-built tile grids rendered through the batcher; scene.UseTilemaps()
after UseRenderer2D()), Pathfinding (grid A*/Dijkstra/BFS and flow fields over a
game-implemented IPathGrid; Core-only, owns no world data), Collisions (Collider
component, spatial hash rebuilt per tick, pairs/queries/raycast; scene.UseCollisions()
after movement systems), UI (Myra integration: scene.UseUI() after UseRenderer2D()),
DevConsole (in-game console capturing Core.Log; scene.UseDevConsole() last in OnLoad).
Dependency rule: every module may depend only on Core; Core depends only on
MonoGame and Friflo.Engine.ECS. Assets.Generator is a netstandard2.0 analyzer.
Documented exceptions: Myra renders with its own SpriteBatch internally; Atlases
depends on Graphics (Texture2DRegion) and Assets (loader registration);
Tilemaps depends on Graphics (regions, layers, renderer);
Collisions depends on Graphics (Transform2D, RectF).
Commands
dotnet build MrGameEng.sln
dotnet test MrGameEng.sln
dotnet run --project samples/MrGameEng.Sample
Architecture rules
- ECS-first: components are plain data (
structimplementingIComponent), behavior goes into Friflo systems (QuerySystem), wired throughSystemRoot. NoUpdate()methods on game objects, no inheritance-based entities. - Hot paths (per-frame systems) must be allocation-free below the renderer's parallel threshold; above it Parallel.For scheduler overhead is the accepted trade. A Friflo chunk holds a whole archetype — parallelize by slicing chunks into segments, never by chunk alone. Measure in Release only, using the Renderer2D phase timings.
- Rendering: custom batcher in
Graphics(vertex buffers, layer→depth→texture sort, atlas support);SpriteBatchis not used in engine code. Draw systems write vertices directly from Friflo chunk iteration. Orthographic camera (one active per scene), registered render layers (World or Screen space, optional Y-sort), AABB culling against the camera rect before vertices are written. - No MGCB content pipeline. Assets are raw files under
Assets/, loaded at runtime (textures viaTexture2D.FromFile, fonts via FontStashSharp, ogg via NVorbis, shaders precompiled bydotnet-mgfxcat build time). Game code references assets only through generated typed handles (AssetRef<T>), never string paths. - New engine functionality goes into the matching module, or a new
MrGameEng.<Area>library if it is a distinct area — never intoCoreby default. - Every public engine feature must be demonstrated in
MrGameEng.Sampleand covered by tests where logic is testable without a GPU.
Code conventions
- Nullable reference types enabled, warnings as errors, file-scoped namespaces.
- Public engine API requires XML doc comments (English).
- Tests: xUnit, named
Method_Scenario_Expectation.
Memory (echovault MCP)
- At session start, call
memory_contextto load prior decisions for this project; callmemory_searchbefore working on a topic that may have prior context (e.g. "renderer", "transitions", "generator"). - Before ending a session where you decided, fixed or learned something, save it with
memory_save: decisions (X over Y + why), bug root causes, non-obvious gotchas (e.g. Friflo/Myra API traps). Write for a future agent with zero context. - Don't save what the repo already records (code, docs/, git history) or trivia.