Merge goalie-tester worktree: modes, 3v3 goalies, OOB faceoffs, CF deploy.
Bring main menu (1v1/3v3), scrimmage with nets and goalies, dead-puck whistles at the nearest faceoff circle, skater board re-entry, and Cloudflare Workers/Pages deploy config. Keep main jersey gear stack and compact goalie floaters.
This commit is contained in:
@@ -0,0 +1,606 @@
|
||||
# Sports Framework — Expansion Plan
|
||||
|
||||
What you already have is not a hockey demo with spare parts. It is a **character +
|
||||
physics + intent** stack that happens to be wired as ice hockey. The goal of this
|
||||
document is to name the seams honestly, list what still has to become *sport-agnostic*,
|
||||
and outline what would remain as **sport packs** so the same building blocks can
|
||||
ship football, basketball, soccer, fighting, racing-on-foot, and contact sports
|
||||
without forking the engine.
|
||||
|
||||
This is complementary to [ROADMAP.md](ROADMAP.md) (hockey product depth) and
|
||||
[README.md](README.md) (current architecture). Here the question is:
|
||||
|
||||
> What would it take for *this package* to be the framework under *any* sport game?
|
||||
|
||||
---
|
||||
|
||||
## 1. The thesis
|
||||
|
||||
A general sports framework is not “one locomotion model that does everything.”
|
||||
It is a **small set of contracts** plus **pluggable sport modules**:
|
||||
|
||||
| Layer | Owns | Sport-specific? |
|
||||
|-------|------|-----------------|
|
||||
| **Body stack** | skeleton, mesh, skinning, body style, ragdoll, proxy | mostly shared |
|
||||
| **Equipment stack** | gear builders, sockets, coverage, colliders | shared builders; sport kits |
|
||||
| **Motion stack** | pose buffer, crossfade, IK, override layers, clips later | shared runtime; sport poses |
|
||||
| **Locomotion** | intent → velocity → footing | **one model per surface/gait family** |
|
||||
| **Impact** | did hit / what kind / severity / handoff limp↔driven | shared core; sport rules |
|
||||
| **Object play** | ball/puck possession, tool use, goals | sport packs |
|
||||
| **AI** | roles, intent writers, formation | shared brain shell; sport tactics |
|
||||
| **Arena** | bounds, surfaces, markings, static colliders | sport packs |
|
||||
| **Rules / match** | clock, score, phases, sanctions | sport packs |
|
||||
| **Studio / harness** | shot sheets, drills, capture, regression | shared tooling; sport catalogs |
|
||||
|
||||
Hockey already forces the hard problems (anisotropic friction, limb-level contact,
|
||||
tool-in-hand IK, pure sim in `shared/`). That is why a framework *can* fall out of
|
||||
this — but only if hockey stops being the type system.
|
||||
|
||||
---
|
||||
|
||||
## 2. What you already have (framework seeds)
|
||||
|
||||
These are reusable with little or no redesign.
|
||||
|
||||
### 2.1 Character body pipeline
|
||||
- **23-bone A-pose skeleton** (`skeleton.js`) with regions, bone radii, segment graph
|
||||
- **Procedural lofted body** (`body.js`) + **distance-field skinning** (`skinning.js`)
|
||||
- **Body style morphs** mass / muscle / fat (`bodyStyle.js`) — already sport-neutral
|
||||
- **Materials / team tints** (`materials.js`) — team identity, not hockey identity
|
||||
|
||||
### 2.2 Equipment geometry kit
|
||||
- **`gearMesh.js`**: `loft`, `carvedShell`, `tube` — sport-agnostic mesh grammar
|
||||
- **Socket + skinned cloth pattern** (hard shells on bones, cloth skinned with `aPart`/`aT`)
|
||||
- **`hideCoveredBody`** coverage masks so kit replaces flesh
|
||||
|
||||
Hockey gear (`skaterGear`, `goalieGear`, `stick`) is content *on top of* that grammar.
|
||||
|
||||
### 2.3 Animation runtime
|
||||
- **Pose buffer + state crossfade + override layers** (`skateAnimator.js`)
|
||||
- **Two-bone analytic IK** (legs; goalie legs; stick grip reach partially)
|
||||
- **Override layers that multiply spine** while replacing arms (stickwork) — correct
|
||||
pattern for “keep locomoting while acting”
|
||||
- **Animator does not own movement** — sim/proxy own position (critical for all sports)
|
||||
|
||||
### 2.4 Physics character loop
|
||||
- **Proxy capsule for standing presence** + **kinematic ragdoll for pose/hits**
|
||||
- **Limp handoff** with root re-expression so get-up does not double-apply slide
|
||||
- **Limb-pair hit classification** from posed capsules (`hits.js`) — the right
|
||||
separation of *did hit* vs *what hit*
|
||||
- **Collision layers / tags** (`bridge.js`) — extensible KIND system
|
||||
|
||||
### 2.5 Intent seam
|
||||
- **`applyIntent`** clamped entry (`skaterSim.js`) — controller, AI, and netcode all
|
||||
write the same shape
|
||||
- **Camera-relative stick** (`input.js`) — gamepad/keyboard already abstracted
|
||||
|
||||
### 2.6 Pure sim island
|
||||
- **`shared/`** free of three.js, headless-testable, server-ready
|
||||
- **Headless test culture** (pose, AI, physics, hits) + **capture / img2mesh** tools
|
||||
|
||||
### 2.7 Studio / reference loop (seed)
|
||||
- **Character studio** (`character.html` + `img2mesh`) with pose presets, fixed views,
|
||||
shot sheets, optional live drill (puck machine)
|
||||
- Pattern: *author → capture sheet → drop refs → re-capture → diff by eye (or later pixel)*
|
||||
|
||||
---
|
||||
|
||||
## 3. What is still hockey-shaped (must peel off)
|
||||
|
||||
These block “any sport” until they become interfaces + plugins.
|
||||
|
||||
| Hardcoded today | Why it blocks generality |
|
||||
|-----------------|---------------------------|
|
||||
| `shared/skaterSim.js` is *the* locomotion | Running, plant-and-cut, swim, bike, skate all need different footing models |
|
||||
| `shared/rink.js` is the arena | Rect + corner radius is not a pitch, court, ring, or track |
|
||||
| `shared/ai.js` puck roles + rink half | Roles are puck/carrier/chaser; no ball/goal/zone abstraction |
|
||||
| `possession.js` + stick blade | Magnetism dial is excellent, but assume blade + cylinder puck |
|
||||
| `stick.js` grip-space tool | Need generic **held tool / ball socket / two-hand implement** |
|
||||
| `hits.js` CAN_DELIVER / ice thresholds | Sport contact rules differ (tackle vs check vs foul vs strike) |
|
||||
| `goalie` as special entity type | “Keeper” should be a role/locomotion profile, not only a hockey class |
|
||||
| `match.js` / `shootout.js` | Match loop is sport session; not a generic phase machine |
|
||||
| `input.js` Skill Stick / hockey stop | Sport action maps differ; need bindable action sets |
|
||||
| Pose catalogs only skate / stick / goalie | Need gait families + sport action libraries |
|
||||
| Physics world assumes ice plane + boards | Surfaces (friction, bounce), goals, posts, glass, hoops, cages |
|
||||
| Package name / scripts assume hockey MVP | Cosmetics; real issue is import graph coupling |
|
||||
|
||||
---
|
||||
|
||||
## 4. Target architecture
|
||||
|
||||
```
|
||||
packages/ (or src/ layered)
|
||||
core/ math, rng, time, determinism helpers
|
||||
body/ skeleton, body loft, skinning, bodyStyle, ragdoll, proxy
|
||||
gear/ loft/shell/tube builders, socket attach, coverage
|
||||
anim/ pose buffer, blend, IK solvers, layer stack, clip hooks
|
||||
locomotion/ interface + models: skate, run, plant, crouch-shuffle, …
|
||||
impact/ contact resolution, limb pairs, severity curves, handoff
|
||||
object/ free bodies, attachment/magnetism, tools, projectiles
|
||||
arena/ surfaces, bounds, static colliders, markings API
|
||||
brain/ intent writer, roles, blackboard, formation helpers
|
||||
match/ phase machine, clock, score, events (sport-agnostic shell)
|
||||
input/ device → action set → intent
|
||||
render/ materials, camera presets, arena mesh helpers
|
||||
studio/ pose/view catalogs, capture API, ref sheets, drills
|
||||
harness/ headless scenarios, golden metrics, capture regression
|
||||
|
||||
sports/
|
||||
hockey/ rink, skate loco, stick, puck, check rules, shootout, AI
|
||||
(future packs)
|
||||
football/
|
||||
basketball/
|
||||
soccer/
|
||||
fighting/ (Ludus-adjacent — already half-solved)
|
||||
…
|
||||
```
|
||||
|
||||
**Rule:** a sport pack may depend on the framework. The framework must not import a sport pack.
|
||||
|
||||
Hockey becomes the first pack that proves the contracts. Ludus fighting is the second
|
||||
pack if contact + minigame reuse is the priority (see ROADMAP fighting note).
|
||||
|
||||
---
|
||||
|
||||
## 5. Contracts to extract (the real work)
|
||||
|
||||
### 5.1 Locomotion model (`ILocomotion`)
|
||||
|
||||
**Have:** carve/glide blade model + intent fields (`ix, iz, sprint, brake`).
|
||||
|
||||
**Need:**
|
||||
|
||||
```
|
||||
createState(spawn, profile) → state
|
||||
applyIntent(state, msg) // clamped, never trusts client
|
||||
step(state, dt, env) // env: surface, contacts, clamps
|
||||
readout(state) → { speed, gaitPhase, bank, plantL, plantR, … }
|
||||
```
|
||||
|
||||
**Locomotion families to support eventually:**
|
||||
|
||||
| Family | Examples | Key physics |
|
||||
|--------|----------|-------------|
|
||||
| **Blade / edge** | ice hockey, figure, speed skate | anisotropic friction, carve |
|
||||
| **Run plant** | soccer, basketball, football | foot plant, cut friction, acceleration |
|
||||
| **Crouch / shuffle** | goalies, catchers, linemen | lateral step without full gait |
|
||||
| **Contact-limited** | rugby ruck, board pin | reduced mobility under constraint |
|
||||
| **Aerial / jump** | basketball, volleyball, headers | ballistic + land recovery |
|
||||
| **Vehicle-assisted** | cycling, wheelchair, luge | separate later; not v1 |
|
||||
|
||||
**Left to build:**
|
||||
- Shared `env` (surface µ, max slope, out-of-bounds clamp hooks)
|
||||
- Foot plant bookkeeping for run gaits (world-planted feet vs mover-local skate feet)
|
||||
- Profile data (top speed, accel, turn radius by sport / position / fatigue)
|
||||
- Unit tests per model mirroring `test/skaterSim.mjs`
|
||||
|
||||
### 5.2 Footing & IK policy
|
||||
|
||||
**Have:** mover-local foot targets for skating; world-height leg IK for goalie pads.
|
||||
|
||||
**Need:**
|
||||
- **`IFootPolicy`**: glide | plant | pivot | kick | slide
|
||||
- World-space plant IK for walk/run (Ludus-style), without regressing skate glide
|
||||
- Arm IK generic: **two-hand implement**, **one-hand hold**, **catch**, **block**
|
||||
- Spine/look-at IK for tracking ball / opponent (broadcast + AI readability)
|
||||
- Hand-to-object solve that reports *reach error* (you already see this on stick grip)
|
||||
|
||||
**Left to build:**
|
||||
- Unified IK module (two-bone + simple FABRIK/pole vectors), shared by sports
|
||||
- Constraint priorities (feet > implement > look) so layers don’t fight
|
||||
- Authoring helpers: target sockets in mover-local vs world
|
||||
|
||||
### 5.3 Pose / animation system generalization
|
||||
|
||||
**Have:** states + stick override layers + goalie stance set.
|
||||
|
||||
**Need:**
|
||||
- **Locomotion graph** (idle, walk, run, sprint, cut, stop, jump, land, fall, getup)
|
||||
- **Action layers** (shoot, pass, tackle, catch, block, celebrate) with blend masks
|
||||
- **Clip adapter** interface early — procedural remains default; mocap/clips plug in
|
||||
without rewriting sports (ROADMAP already names motion matching as the ceiling)
|
||||
- Shared **get-up / knockdown / stagger** presentation states (physics-driven entry)
|
||||
|
||||
**Left to build:**
|
||||
- Pose catalog format (JSON or pure JS) keyed by sport + role
|
||||
- Layer stack API (replace vs multiply vs additive per bone set)
|
||||
- Phase drivers from locomotion readout (gait phase, effort, bank)
|
||||
- Optional motion-match slot (even if empty) so content pipeline isn’t a rewrite later
|
||||
|
||||
### 5.4 Equipment framework
|
||||
|
||||
**Have:** builders + hockey kits + stick as special tool.
|
||||
|
||||
**Need:**
|
||||
|
||||
```
|
||||
EquipmentDef {
|
||||
id, sockets[], skinnedParts[], rigidParts[],
|
||||
colliders[], coverage[], massAdd, tags[]
|
||||
}
|
||||
ToolDef extends Equipment // stick, bat, racket, gloves-as-weapons
|
||||
WearableDef extends Equipment // helmet, pads, jersey, cleats
|
||||
```
|
||||
|
||||
**Left to build:**
|
||||
- Data-driven attach (bone name + local TRS + optional skin weights)
|
||||
- Size from physique (you already scale gear off `physique` — generalize)
|
||||
- Collider generation from mesh bounds or authored capsules
|
||||
- Damage/armor hooks by `REGION` (skeleton already has regions “from GDD”)
|
||||
- Asset path: procedural first, imported glTF meshes later behind same sockets
|
||||
- **Reference-driven iteration**: shot sheet per equipment part (front/side/3q/detail)
|
||||
|
||||
### 5.5 Player assembly (`createAthlete`)
|
||||
|
||||
**Have:** `createSkater`, `createGoalie` — two assembly paths.
|
||||
|
||||
**Need:** one factory:
|
||||
|
||||
```
|
||||
createAthlete({
|
||||
seed, bodyStyle, team,
|
||||
locomotion: 'skate' | 'run' | …,
|
||||
role: 'skater' | 'keeper' | 'striker' | …,
|
||||
loadout: EquipmentDef[],
|
||||
animProfile,
|
||||
impactProfile,
|
||||
})
|
||||
```
|
||||
|
||||
Roles swap locomotion, gear, AI profile, and action map — not hard forks of the character.
|
||||
|
||||
### 5.6 Impact / contact sports core
|
||||
|
||||
**Have:** proxy collision + limb pair + severity tiers + limp handoff + get-up fix.
|
||||
|
||||
**Need:**
|
||||
- **Impact profiles** (thresholds, limbShare, bonuses, legal deliverers) per sport
|
||||
- Legal / illegal contact classification as *rules callback*, not hardcoded hockey
|
||||
- Multi-body pile stability (proxy equilibrium already soft under pressure)
|
||||
- Grapple / pin / clinch states (football tackle finish, wrestling, board battle)
|
||||
- Strike profiles for combat sports (Ludus) reusing limb pairs + reaction curve
|
||||
- Surface hits (wall, boards, post) feeding same severity pipeline
|
||||
- Injury / fatigue hooks off region + severity (data only; presentation later)
|
||||
|
||||
**Left to build:**
|
||||
- `createImpactSystem({ profile, rules })` replacing hockey-tuned `HIT` constants
|
||||
- Deliverer allow-lists as data
|
||||
- Contested body state (pinned, held, blocked) separate from limp
|
||||
- Harness scenarios: open ice hit, wall pin, tackle wrap, pile-up
|
||||
|
||||
### 5.7 Object / ball / tool play
|
||||
|
||||
**Have:** puck body, blade collider, magnetism possession dial, release step-clear.
|
||||
|
||||
**Need:**
|
||||
- Generic **`PlayObject`**: sphere / cylinder / prolate (ball types), mass, restitution
|
||||
- **Attachment models**: hard parent, soft magnetism, carry socket, two-hand cradle
|
||||
- **Release models**: impulse from tool velocity, throw arc, kick from foot bone
|
||||
- Contested possession (you already noted nearest-index-wins is too coarse)
|
||||
- Multi-object (only one puck today)
|
||||
|
||||
**Left to build:**
|
||||
- `object/possession.js` parameterized (radius, catch cone, break force, magnetism)
|
||||
- Tool velocity sampling at release (stick already aims; generalize to foot/hand)
|
||||
- Interaction matrix: body part × object × surface
|
||||
- Sport rules for out-of-bounds / last touch (thin event layer)
|
||||
|
||||
### 5.8 Arena / surface system
|
||||
|
||||
**Have:** NHL rink numbers, board outline, ice clamp, markings texture, nets.
|
||||
|
||||
**Need:**
|
||||
|
||||
```
|
||||
ArenaDef {
|
||||
bounds, // polygon or compound
|
||||
surfaces[], // friction, restitution, name
|
||||
staticColliders[],
|
||||
goals[] | targets[],
|
||||
spawns[],
|
||||
markings, // render only
|
||||
}
|
||||
```
|
||||
|
||||
**Left to build:**
|
||||
- Containment for rect, rounded-rect, circle, custom polyline
|
||||
- Surface queries under feet (ice vs turf vs hardwood changes loco)
|
||||
- Goal/score volumes as triggers (net is hockey-specific geometry)
|
||||
- Camera volumes / broadcast rails optional metadata
|
||||
|
||||
### 5.9 AI brain shell
|
||||
|
||||
**Have:** waypoint steer, personal space, board lookahead, carry/chase/support/defend
|
||||
via nearest-to-puck, intent-only outputs.
|
||||
|
||||
**Need:**
|
||||
|
||||
```
|
||||
Brain {
|
||||
sense(world) → facts
|
||||
rolePolicy(facts) → role
|
||||
tactic(role, facts) → goal
|
||||
motor(goal) → intent + actions
|
||||
}
|
||||
```
|
||||
|
||||
**Left to build:**
|
||||
- Blackboard / facts schema (ball, goals, teammates, opponents, clock, score)
|
||||
- Role set as data per sport (not four hockey enums only)
|
||||
- Formation / spacing utilities (slots relative to ball and own goal)
|
||||
- Difficulty as parameter on reaction lag, aim cone, decision rate
|
||||
- Keeper brain as role using shuffle locomotion (generalize goalie)
|
||||
- Headless scenario tests: “defend lead”, “press high”, “box out” per pack
|
||||
|
||||
Hockey AI depth (forecheck systems, etc.) stays in the hockey pack / ROADMAP.
|
||||
|
||||
### 5.10 Match / rules shell
|
||||
|
||||
**Have:** `createMatch` loop, shootout phase machine, goal detection helpers.
|
||||
|
||||
**Need:**
|
||||
- Generic **phase machine**: warmup → live → stoppage → restart → end
|
||||
- Event bus: goal, foul, out, period, possession change, hit
|
||||
- Score / clock / period as configurable
|
||||
- Restart spawns from arena + rules (faceoff, kickoff, freethrow, scrum)
|
||||
|
||||
**Left to build:**
|
||||
- `match/runtime.js` with sport rules plugin
|
||||
- Deterministic event log (gates replay + netcode later)
|
||||
- Minimal HUD adapter (score/clock) sport-agnostic
|
||||
|
||||
### 5.11 Input / action maps
|
||||
|
||||
**Have:** Xbox + keyboard, Skill Stick gestures, rumble on hit.
|
||||
|
||||
**Need:**
|
||||
- Action set per sport (`move`, `sprint`, `primary`, `secondary`, `skillAxis`, …)
|
||||
- Gesture recognizers as plugins (Skill Stick shoot is one plugin)
|
||||
- Rebind + dual-input last-wins (keep current behavior)
|
||||
|
||||
### 5.12 Studio, reference sheets, training harness
|
||||
|
||||
This is the differentiator you called out. Today it is hockey-shaped but the **loop**
|
||||
is correct.
|
||||
|
||||
**Have:**
|
||||
- Live studio with pose/view catalogs
|
||||
- CLI shot sheet (`img2mesh`)
|
||||
- Puck machine drill for goalie
|
||||
- Headless tests + `capture` screenshots
|
||||
- `hitprobe` for contact
|
||||
|
||||
**Need for framework-grade training harness:**
|
||||
|
||||
| Capability | Purpose |
|
||||
|------------|---------|
|
||||
| **Subject registry** | any athlete role + loadout, not only player/goalie |
|
||||
| **Pose/view catalogs as data** | sport packs register entries |
|
||||
| **Reference slots** | `ref/<sport>/<subject>/<pose>_<view>.png` side-by-side |
|
||||
| **Diff mode** | flip / onion-skin / histogram vs previous capture |
|
||||
| **Drill factory** | spawn scenario (1v1, shooting gallery, tackle pad, PK) |
|
||||
| **Metric probes** | blade height, foot plant error, reach error, joint limits, timing |
|
||||
| **Scenario packs** | headless scripts asserting metrics, not only “no NaN” |
|
||||
| **Optional photo-guided authoring** | import ref image as camera-aligned overlay (not auto-mesh) |
|
||||
| **Later: mesh-from-image assist** | silhouette / part labels → loft section hints (research; not blocking) |
|
||||
|
||||
**Important scope note:** true **image → production mesh** (full photogrammetry /
|
||||
generative retopo) is a product of its own. The framework should treat **reference
|
||||
photos and sheets as the iteration contract**, with procedural gear remaining the
|
||||
authoritative runtime asset until a mesh pipeline earns its keep.
|
||||
|
||||
**Left to build (practical order):**
|
||||
1. Registry + data-driven catalogs (so new sports don’t edit `img2mesh.mjs` internals)
|
||||
2. Side-by-side ref overlay in studio + CLI compare report
|
||||
3. Metric HUD (contact points, IK targets, capsule overlays — debug already half there)
|
||||
4. Drill API used by shootout machine, then tackle/shot drills for other packs
|
||||
5. Golden metric tests (blade height style) per sport pack
|
||||
6. Optional: capture matrix in CI on PR (you already have the capture tool)
|
||||
|
||||
---
|
||||
|
||||
## 6. Sport packs — what each still needs on top of the framework
|
||||
|
||||
Once contracts exist, each sport is mostly **content + rules + AI policy**, not a new engine.
|
||||
|
||||
### 6.1 Ice hockey (first pack — mostly present)
|
||||
**Done enough:** skate loco, rink, stick, puck, checks, shootout, basic AI, goalie MVP.
|
||||
**Pack backlog:** see ROADMAP (full 5v5 rules, goalie depth, positional AI, possession feel).
|
||||
|
||||
### 6.2 Fighting / combat (highest reuse from Ludus + impact core)
|
||||
- Strike / block / grab action layers
|
||||
- Ring/cage arena
|
||||
- Stamina and limb disable via `REGION`
|
||||
- Existing fighting system port (ROADMAP already flags this)
|
||||
|
||||
### 6.3 Soccer
|
||||
- Run plant locomotion + ball foot/chest/head contacts
|
||||
- Large pitch arena, goals, out/throw-in/corner rules
|
||||
- No (or soft) limb impact; shoulder challenge profile
|
||||
- AI: formations, offside line fact, keeper dive (shuffle + dive loco)
|
||||
|
||||
### 6.4 Basketball
|
||||
- Run + jump + plant, ball carry/dribble magnetism variant
|
||||
- Court, hoop trigger, shot arc from release
|
||||
- Screen / box-out contact (low severity impact profile)
|
||||
- AI: pick-and-roll roles, spacing
|
||||
|
||||
### 6.5 American football / rugby
|
||||
- Run + explosive cut; tackle as grapple-to-limp pipeline
|
||||
- Field, downs/ruck rules plugin
|
||||
- Heavy impact profile; pile-up stability critical
|
||||
- AI: playbooks as scripted formations + read trees
|
||||
|
||||
### 6.6 Basketball-adjacent / volleyball / handball
|
||||
- Shared run + jump + catch/throw object model
|
||||
- Different arenas and score targets
|
||||
|
||||
### 6.7 Non-goals for v1 framework
|
||||
- Full vehicle sports, water sports, golf swing fidelity, licensed broadcast packages
|
||||
- Complete mocap library (architecture must allow it; content is separate)
|
||||
|
||||
---
|
||||
|
||||
## 7. Gap list — prioritized build order
|
||||
|
||||
Phased so each phase ships a **usable contract** and keeps hockey working as the
|
||||
proving pack (strangler pattern: extract behind interfaces, re-home hockey).
|
||||
|
||||
### Phase 0 — Inventory & seams (days)
|
||||
- [ ] Draw import graph: mark `shared/*` vs sport-coupled modules
|
||||
- [ ] Freeze contracts in a short `docs/contracts.md` (or this file §5 as source)
|
||||
- [ ] Prove Box3D determinism (ROADMAP) — gates multiplayer *and* harness replay
|
||||
- [ ] Decide monorepo layout (`sports/hockey` vs stay single package with folders)
|
||||
|
||||
### Phase 1 — Athlete + gear core (1–2 weeks)
|
||||
- [ ] `createAthlete` + loadout list; skater/goalie become configs
|
||||
- [ ] EquipmentDef schema; move stick/pads to data-ish modules
|
||||
- [ ] Physique-driven sizing API documented
|
||||
- [ ] Studio subject registry reads loadouts
|
||||
|
||||
### Phase 2 — Locomotion interface (1–2 weeks)
|
||||
- [ ] Extract `ILocomotion` from `skaterSim`
|
||||
- [ ] Keep skate model as implementation #1
|
||||
- [ ] Stub `runPlant` model good enough for a mannequin jog (even ugly)
|
||||
- [ ] Foot policy switch (glide vs plant) wired to animator
|
||||
|
||||
### Phase 3 — Anim / IK platform (2–3 weeks)
|
||||
- [ ] Shared IK solvers module
|
||||
- [ ] Layer stack API (locomotion / action / reaction / getup)
|
||||
- [ ] Reaction/stagger as layers driven by impact system
|
||||
- [ ] Clip adapter interface (null implementation OK)
|
||||
|
||||
### Phase 4 — Impact + object cores (2–3 weeks)
|
||||
- [ ] Impact profiles + rules callbacks
|
||||
- [ ] Generic play object + possession magnetism
|
||||
- [ ] Tool release sampling
|
||||
- [ ] Contested capture v1
|
||||
|
||||
### Phase 5 — Arena + match shell (1–2 weeks)
|
||||
- [ ] ArenaDef; rink becomes hockey arena pack
|
||||
- [ ] Phase machine + event log
|
||||
- [ ] Score/clock/HUD adapters
|
||||
|
||||
### Phase 6 — Brain shell (2+ weeks, ongoing content)
|
||||
- [ ] Facts blackboard + role policy
|
||||
- [ ] Formation helpers
|
||||
- [ ] Keeper role using shared pieces
|
||||
- [ ] Scenario harness for AI regressions
|
||||
|
||||
### Phase 7 — Studio / training harness productize (parallel after Phase 1)
|
||||
- [ ] Data-driven pose/view catalogs
|
||||
- [ ] Reference overlay + capture matrix
|
||||
- [ ] Metric probes + golden tests
|
||||
- [ ] Drill factory (shooting, tackling, 1v1)
|
||||
- [ ] Optional ref-image camera plate
|
||||
|
||||
### Phase 8 — Second sport pack (proof)
|
||||
Pick **one** of:
|
||||
- **Fighting** (max reuse of impact + Ludus), or
|
||||
- **Soccer prototype** (max pressure on run loco + ball object)
|
||||
|
||||
Success criterion: second sport does **not** fork `skeleton`, `ragdoll`, `gearMesh`,
|
||||
`hits` core, or studio capture — only pack content + profiles.
|
||||
|
||||
---
|
||||
|
||||
## 8. What “done” looks like for the framework (not for a sport)
|
||||
|
||||
You can claim a sports framework when **all** of these are true:
|
||||
|
||||
1. **New athlete** = skeleton + bodyStyle + loadout + loco profile + anim profile
|
||||
2. **New equipment piece** = sections/sockets (+ optional collider) + studio views
|
||||
3. **New contact rule** = impact profile + rules callback, no hit-system fork
|
||||
4. **New ball sport** = PlayObject + possession params + arena goals + AI facts
|
||||
5. **New locomotion** = one module implementing `ILocomotion` + foot policy
|
||||
6. **New sport AI** = roles writing intents/actions into the same seam as the pad
|
||||
7. **Regression** = headless metrics + shot sheets vs reference photos for that pack
|
||||
8. **Hockey still runs** as a pack on top of the same cores
|
||||
|
||||
Not required for “framework done”: full NHL parity, licensing, netcode, franchise modes
|
||||
(those are product; see ROADMAP).
|
||||
|
||||
---
|
||||
|
||||
## 9. Risks & non-goals
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Over-abstract before second sport | Extract only when hockey + one other pack demand the seam |
|
||||
| Run gait looks like skating forever | Foot plant policy is a hard gate for sport #2 |
|
||||
| Proxy pile-ups | Dedicated multi-body scenarios before rugby/football |
|
||||
| Mocap FOMO | Keep procedural + layer API; add clips when content exists |
|
||||
| img2mesh becomes “AI will make the gear” | Refs guide humans/tools; runtime assets stay authored procedural/glTF |
|
||||
| Determinism ignored | Prove early; harness replays depend on it |
|
||||
| God-object `match.js` | Event log + rules plugin from the start of Phase 5 |
|
||||
|
||||
**Non-goals:** replacing Unity/Unreal; full photogrammetry pipeline; every Olympic sport
|
||||
in year one; network-complete framework before single-player packs feel good.
|
||||
|
||||
---
|
||||
|
||||
## 10. Suggested near-term decisions
|
||||
|
||||
1. **Keep hockey playable on main** while extracting — no big-bang rewrite.
|
||||
2. **Name the framework** (e.g. still `tilt` core + `sports/hockey`, or promote Ludus-lineage
|
||||
body stack to a shared package both Ludus and tilt consume).
|
||||
3. **Second pack choice** determines Phase 2–4 emphasis:
|
||||
- Fighting → impact, reaction layers, stamina
|
||||
- Soccer → run plant, ball object, large arena
|
||||
4. **Studio first among tools** — equipment and poses improve only as fast as the
|
||||
ref-sheet loop; that loop is already the right shape.
|
||||
5. **Do not wait for mocap** to generalize animation runtime; wait for mocap to *fill* it.
|
||||
|
||||
---
|
||||
|
||||
## 11. One-page checklist — “left to expand”
|
||||
|
||||
**Core extractions**
|
||||
- [ ] Locomotion interface + run/plant model
|
||||
- [ ] Foot / arm / look IK module
|
||||
- [ ] Anim layer stack + clip adapter
|
||||
- [ ] Athlete factory + data loadouts
|
||||
- [ ] EquipmentDef / ToolDef schema
|
||||
- [ ] Impact profiles + rules hooks
|
||||
- [ ] PlayObject + generic possession
|
||||
- [ ] ArenaDef + surfaces
|
||||
- [ ] Brain blackboard + roles
|
||||
- [ ] Match phase machine + events
|
||||
- [ ] Action-map input
|
||||
|
||||
**Harness / content pipeline**
|
||||
- [ ] Sport-registered studio catalogs
|
||||
- [ ] Reference photo overlay + capture matrix
|
||||
- [ ] Metric probes + golden pose/contact tests
|
||||
- [ ] Drill factory for training scenarios
|
||||
|
||||
**Proof**
|
||||
- [ ] Hockey re-homed as pack
|
||||
- [ ] Second sport pack without core forks
|
||||
- [ ] Determinism + replay of harness scenarios
|
||||
|
||||
**Explicitly still sport content (never “framework only”)**
|
||||
- Poses, gear shapes, AI tactics, rules edge cases, audio, broadcast, modes, licensing
|
||||
|
||||
---
|
||||
|
||||
## 12. Bottom line
|
||||
|
||||
You are closer than a greenfield sports engine because the **hard abstractions are
|
||||
already proven in anger**:
|
||||
|
||||
- intent-driven locomotion
|
||||
- animator subordinate to physics
|
||||
- limb-level contact from posed ragdolls
|
||||
- limp ↔ driven handoff without teleports
|
||||
- tool-in-hand dependency order
|
||||
- possession as a dial
|
||||
- pure sim + headless tests + reference shot sheets
|
||||
|
||||
What remains is not “invent sports tech.” It is **peeling hockey off the type system**,
|
||||
turning each proven spike into a **contract + pack content**, and making the
|
||||
**studio/harness** the way every new sport earns visual and mechanical correctness
|
||||
from reference photos and scenario metrics.
|
||||
|
||||
Hockey ROADMAP remains the depth plan for pack #1. This document is the breadth plan
|
||||
for the chassis underneath packs #1…N.
|
||||
Reference in New Issue
Block a user