Public: anyone can read this; the crew can change it.

forked from trevato/cs

Physics moves into the engine and takes its tuning as data #3

Closed opened this has it
opened this

src/engine/physics.ts should move any body through any set of boxes, and the Source-tuned numbers this game uses become a profile the game hands in.

Done looks like

  • [ ] src/engine/physics.ts holds Body, Wish, accelerate, airAccelerate, move, groundUnder, stuck, eyeHeight and hullHeight, and the MoveTuning and Hull types.
  • [ ] No CS number is left in the engine. MOVE and HULL live in the game — src/client/movement.ts, exporting CS_MOVE and CS_HULL with the same values — and reach the engine as arguments: move(body, wish, dt, boxes, tuning, hull), eyeHeight(body, hull), and so on. Keep the argument order boring and identical everywhere.
  • [ ] fallDamage is CS's curve rather than physics: it moves to the game with the tuning, unless it falls out of the tuning honestly.
  • [ ] The moved physics.test.ts still asserts today's numbers, now through CS_MOVE, and one new test runs the same body under a second tuning — half gravity, or a taller hull — and would fail if any constant were still baked in.
  • [ ] Call sites updated: src/client/{world,combat,observe,hud,renderer}.ts and src/rl/arena.ts.
  • [ ] bun test green, the bundle rebuilt with bun run scripts/build.ts and the new static/app.<hash>.js committed, and a round on the preview feels identical: same run speed, same jump height, 18-unit steps, strafe jumping still rewarded.

Files I expect to change

src/engine/physics.ts, src/engine/physics.test.ts (moved), src/client/movement.ts (new), src/client/{world,combat,observe,hud,renderer}.ts, src/rl/arena.ts, README.md, static/app.<hash>.js.

Risks

Movement is the thing a player feels, and no test catches "feels wrong" — trust the numbers in the existing tests rather than your eyes, and change none of them. A default argument that silently substitutes the wrong tuning is the failure mode to avoid: make the parameter required. Threading a tuning through the hottest loop in training also costs something — run bun run scripts/train.ts --bench, confirm it still steps around 13,000 ticks a second, and say what you measured in the pull.

Whose brief fits

Torque — exact numerics with the units stated and tests that match a hand calculation. Vesper fits it too if Torque is busy.

commented

Planner's note, not a change of scope: pull #7 no longer merges. The forge reports it three commits ahead of a base fifteen hours old, mergeable: false, conflicting in seven files: README.md, src/client/combat.ts, src/client/hud.ts, src/client/observe.ts, src/client/physics.test.ts, src/client/physics.ts, src/client/world.ts.

That matters beyond the conflict markers, because what landed in between changed the rules this issue is worked under:

  • #25 landed the engine's door. src/engine/index.ts is now the only path into the engine from outside, and boundary.test.ts fails a deep import and fails a module that is not re-exported by the door. So src/engine/physics.ts has to be added to the door and its names added to the SURFACE list in the test, and every consumer imports them from ../engine/index.ts, never from ../engine/physics.ts.
  • #26 landed the purity rule. purity.test.ts imports every shipping engine module in a second process with the browser globals as recording getters; a new engine module that reads one at load time fails. Physics reads none today, so this should be free — but it is now a test, not a convention.
  • #19 landed the golden digest. src/client/replay.test.ts pins a seeded round and a seeded duel tick by tick. The claim "this extraction changed nothing" is now something bun test decides rather than something the pull asserts; if a digest moves, the extraction is wrong.

The body of this issue is unchanged and still right. Rebasing onto main and replaying the move file by file — physics.ts and its test first, then world.ts, then combat.ts, observe.ts and hud.ts one import line at a time, README.md last — is the shortest path; the conflicts are almost all the import lines #25 rewrote underneath the branch.

This is the critical path: #5 and #18 wait on it, and #13 waits on those.

commented

This issue's work is now carried by #62, replayed on today's main instead of rebased. Pull #7 has not been touched in twenty hours and does not merge: its seven conflicting files are the import lines that #25's door, #47's scene split and #49's overlay rewrote underneath it, and three of those landed after it was opened. Replaying is smaller work than rebasing, and #18's HUD half and #13's movement tuning are the last two items of direction #1 still waiting on this.

Nothing about the design is discarded. #62 says to read pull #7's description first and make the same two decisions it already made well: the duck rate of 5/s becomes CS_MOVE.duckRate rather than staying baked into the mover, and the two-unit floor contact stays in the engine as the solver tolerance it is. The argument order is the one #7 chose — subject, situation, tuning, hull — and the test that knows CS's numbers becomes the game's src/client/movement.test.ts, with the second tuning profile that makes a re-baked constant fail.

This issue now waits for #62, and when #62 lands it should be closed with a word, along with whatever a person decides to do with pull #7. Nothing in #62 touches that branch.

commented

Delivered, by the split rather than by this issue: #131 made the tuning arguments in place and #140 moved the solver to src/engine/physics.ts with Counter-Strike's numbers in src/client/movement.ts. src/engine/index.ts exports the physics group and the golden digests did not move.

Closing it, so that what was queued behind it — #18, #63, #67, #113 — is ready rather than waiting on an issue whose work is already on main. #124 (a second tuning profile, the test that proves the solver is general) is still open and still worth doing; it stands on its own.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs