FS.GG.Game.Core
0.7.1
Prefix Reserved
See the version list below for details.
dotnet add package FS.GG.Game.Core --version 0.7.1
NuGet\Install-Package FS.GG.Game.Core -Version 0.7.1
<PackageReference Include="FS.GG.Game.Core" Version="0.7.1" />
<PackageVersion Include="FS.GG.Game.Core" Version="0.7.1" />
<PackageReference Include="FS.GG.Game.Core" />
paket add FS.GG.Game.Core --version 0.7.1
#r "nuget: FS.GG.Game.Core, 0.7.1"
#:package FS.GG.Game.Core@0.7.1
#addin nuget:?package=FS.GG.Game.Core&version=0.7.1
#tool nuget:?package=FS.GG.Game.Core&version=0.7.1
FS.GG.Game.Core
BCL-only deterministic simulation core for FS.GG.Game — the platform's bottom layer.
Depends on nothing but FSharp.Core and reaches up to no other FS-GG package.
The sim vocabulary
The shared types — Point, Rect, Circle, ConvexPolygon, and the detection values Contact (a single-axis penetration manifold), Manifold (its multi-point form) and RayHit (a segment-cast result) — live directly in the FS.GG.Game.Core namespace, so open FS.GG.Game.Core is all a caller needs. The tile index Cell is namespace-level too. Everything below is a [<RequireQualifiedAccess>] module, called as Grids.cellAt, Rng.nextInt, and so on.
Rng— SplitMix64 seeded RNG (ofSeed/nextInt/nextFloat/nextBool/split), byte-identical across runs.FixedStep— fixed-timestep accumulator drain (drain/drainWith). No wall-clock read, so a scripted frame time replays exactly.Loop— the fixed-step double-buffered loop built onFixedStep.drain(advance/alpha): the world as of the last completed step (Current), the one before it (Previous), and the carried sub-step time (Accumulator). Renderers interpolatePrevious → Currentbyalpha, so motion is smooth at any frame rate while the sim only ever advances by whole fixed steps. The default for any continuously-moving simulation.InputCommand— the abstract, device-free vocabulary of input intents (Command.MoveNorth/…/Fire/Pause) as pure data. The policy half of the input split:Game.Coreowns which commands exist; the render/input layer owns how a device makes one and never learns a game action.
Collision — detection, then response
Geometry— the detection surface: overlap and containment for AABB, circle, and convex polygon (intersects/contains/aabbContact/circleContact/polygonContact/obbPolygon), swept tests (sweptIntersects), and segment casts (segmentAabbHit/segmentCircleHit/segmentPolygonHit/…). It returns manifests as values and never resolves them.Resolution— the response layer that consumes a detectionContactand produces transforms (pushOut/slide/push;knockbackis a deprecated shim overpush). Deliberately separate from detection; it never re-detects.SpatialGrid— uniform spatial partitioning for the broad phase (build/query/queryRadius).Physics— an opt-in mini rigid-body engine: a world of bodies, a broad phase, a narrow phase, and a semi-implicit Euler step with a warm-started sequential-impulse contact solver over bodies that sleep once they settle. Mass is derived from a shape's area, not given. ArcadeResolutionstays the first-class default; neither module knows the other.
The grid
Pathfinding— grid A*/BFS over walkable cells (astar/bfs), the turn-based-tactics move range (reachable/pathTo), and the many-to-one AI substratedistanceField/flowField/reachableWithin. Pick by the question:astarminimises steps and takes nocost, so it is the wrong tool for a unit spending a movement budget over non-uniform terrain —reachablecosts the highlight and the path in one search, andpathTowalks it.reachableWithinis that search with the predecessors dropped: the costed set, for scoring cells or a threat overlay, not for pathing to one.Grids— the parts of a square grid:Edge,Vertex,GridSpec, the six adjacency conversions, and the pixel↔cell map (cellRect/cellCenter/edgeSegment/cellAt). Names the boundary between two tiles, which is where a wall lives.
Sight
Los— point-to-point grid line of sight over a caller-supplied opacity predicate (line/supercover/trace/lineOfSight).Fov— grid field of view by symmetric shadowcasting (fov). Opacity is not walkability: this module consults opacity only.Visibility— the continuous-space sibling: exact point-to-point sight against arbitrary occluder segments, and the full angular-sweep visibility polygon (raySegment/isVisible/polygon). It can answer occlusion between two moving bodies, which a tile walk cannot.
Pathfinding, Los, and Fov all take terrain as a pure Cell -> bool predicate — the framework holds no map, so one terrain plugs into all three.
Combat and decision
Ballistics— projectile weapons over continuous space: a swept advance that cannot tunnel (a fast round is a segment, never a point), a lead / intercept solve, and a splash query with a caller-chosen falloff. Lifetimes are counted in whole ticks, not float seconds, so a replay cannot drift.Effects— the mitigation layer: what one incoming hit becomes at the target. It separates the damageSource(aDeclaredattack — the only thing cover and armor reduce — vsCollision/Environmental/Periodic) from the damage kind, which stays generic in'K(Game.Corenever learns what Frost is).Ai— the decision layer's vocabulary: a comparableAgentIdthat fixes iteration order (never hash order, which would diverge a replay), and the fog-of-warTeamView— an abstract value of what a team knows, whose sightings decay from spotted into ghosts. Its LOS is a caller-supplied oracle, so perception policy stays with the game.
Where it came from
Three provenances:
- Extracted from
FS.GG.UI.Canvas/FS.GG.UI.Sceneand reimplemented BCL-only, per ADR-0022 — the shared types,Geometry,Rng,FixedStep,Pathfinding,SpatialGrid. - Promoted from the frozen starter fragments in
FS.GG.Rendering(template/fragments/*), which every game that wanted them previously had to copy and diverge from —Los,Visibility,Grids. - Authored here through the SDD lifecycle, because the org had nothing to promote —
Fov,Resolution,Loop,InputCommand,Ballistics,Effects,Ai, andPhysics.
Guarantees
Headlessly testable — zero Skia, zero Scene. Purity, totality (degenerate and non-finite input degrades to a documented value rather than throwing), and determinism (integer logic / float presentation) are the contract each module's .fsi states and its tests hold it to — so identical input replays byte-identically across runs, and a module is safe to call from a replayed simulation step. Cross-platform byte-identity is unconditional for the integer / grid layer; the float-heavy modules scope it (Visibility to |coord| <= 1e6) or defer full lockstep to a later fixed-point ADR (Physics.checksum), so trust the per-module .fsi, not one blanket claim.
To project sim state onto drawables, add FS.GG.Game.Render.
House style: .fsi is the sole public surface; net10.0; -preview channel.
See FS-GG/FS.GG.Game and ADR-0022.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FSharp.Core (>= 10.1.302)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on FS.GG.Game.Core:
| Package | Downloads |
|---|---|
|
FS.GG.Game.Render
Pure Scene adapter and input policy for FS.GG.Game — projects FS.GG.Game.Core simulation primitives (Point/Rect/Cell and pathfinding routes) onto FS.GG.UI.Scene drawables at the render edge, and ships the default command→key keymap binding the Game.Core command vocabulary onto FS.GG.UI.KeyboardInput's keymap mechanism. Reaches UP to FS.GG.UI.*; no Skia, deterministic. Per ADR-0022 §2. |
|
|
FS.GG.Game.Harness
Deterministic, headless gameplay test harness on FS.GG.Game.Core. Drives a game's world through the standard Command input frontier — scripted raw-key→keymap→Command, an in-process Bot policy, and a multi-seed bot-vs-bot matrix — folds whole fixed steps, and fingerprints the world trace as a value so a replay is a comparison, not a tolerance check. A typed synthetic-state escape hatch keeps its own evidence self-identifying. Depends on nothing but FS.GG.Game.Core and the BCL. |
GitHub repositories
This package is not used by any popular GitHub repositories.