diff options
| author | Gene Pasquet <dev@etenil.net> | 2026-04-08 01:57:20 +0100 |
|---|---|---|
| committer | Gene Pasquet <dev@etenil.net> | 2026-04-08 01:57:20 +0100 |
| commit | 9e8b75f9949259ef01942cd3717b79b044efddf7 (patch) | |
| tree | c6b71291ade57f0560a9bbf0db9f5b66bab65cb3 /docs/physics.org | |
| parent | 84840ede6646ed793b61cdd889d3f57ab05e9311 (diff) | |
Refactor update pipelines
Diffstat (limited to 'docs/physics.org')
| -rw-r--r-- | docs/physics.org | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/docs/physics.org b/docs/physics.org index 8401a38..e5b3749 100644 --- a/docs/physics.org +++ b/docs/physics.org @@ -76,7 +76,7 @@ Helper: ~(entity-skips-pipeline? entity step-symbol)~ (from ~downstroke-entity~) ** ~define-pipeline~ (~downstroke-entity~) -Physics steps are defined with ~(define-pipeline (procedure-name skip-symbol) (formals ...) body ...)~ from the entity module. The first formal must be the entity. The procedure name and skip symbol are separate (e.g. ~detect-on-solid~ vs ~on-solid~). ~apply-velocity~ is still written by hand because it consults ~velocity-x~ and ~velocity-y~ independently. +Physics steps are defined with ~(define-pipeline (procedure-name skip-symbol) (formals ...) body ...)~ from the entity module, optionally with ~guard: expr~ before ~body ...~: when the guard is false, the entity is returned unchanged before the body runs. The first formal must be the entity. The procedure name and skip symbol are separate (e.g. ~detect-on-solid~ vs ~on-solid~). ~apply-velocity~ is still written by hand because it consults ~velocity-x~ and ~velocity-y~ independently. The renderer and other subsystems do **not** use ~#:skip-pipelines~ today; they run after your ~update:~ hook. If you add render-phase or animation-phase skips later, reuse the same plist key and helpers from ~downstroke-entity~ and document the new symbols alongside physics. @@ -225,13 +225,15 @@ Entities without =#:solid?= or with =#:solid? #f= are skipped. Returns a new ent This is relatively expensive: O(n²) for n entities. Use only when entity count is low (< 100) or for game objects where push-apart is desired. -** scene-resolve-collisions +** Using =resolve-entity-collisions= on a scene + +Apply the pure list function via =scene-transform-entities= (from =downstroke-world=): #+begin_src scheme -(scene-resolve-collisions scene) +(scene-transform-entities scene resolve-entity-collisions) #+end_src -**Description**: Convenience wrapper. Extracts all entities from the scene, passes them to =resolve-entity-collisions=, and updates the scene in place. Modifies the scene. +Returns a new scene with the updated entity list; the original scene is not modified. ** aabb-overlap? @@ -397,27 +399,27 @@ Multiple entities falling and colliding with each other: update: (lambda (game dt) (let* ((scene (game-scene game)) (tm (scene-tilemap scene))) - ;; Apply physics to all entities in one pass - (scene-update-entities scene - apply-gravity - apply-velocity-x - (lambda (e) (resolve-tile-collisions-x e tm)) - apply-velocity-y - (lambda (e) (resolve-tile-collisions-y e tm)) - (lambda (e) (detect-on-solid e tm))) - ;; Then resolve entity-entity collisions - (scene-resolve-collisions scene))) + ;; Apply physics to all entities in one pass, then resolve entity-entity collisions + (scene-transform-entities + (scene-map-entities scene + apply-gravity + apply-velocity-x + (lambda (e) (resolve-tile-collisions-x e tm)) + apply-velocity-y + (lambda (e) (resolve-tile-collisions-y e tm)) + (lambda (e) (detect-on-solid e tm))) + resolve-entity-collisions))) #+end_src ** step-by-step -1. **scene-update-entities**: applies each step to all entities in order +1. **scene-map-entities**: applies each step to all entities in order - =apply-gravity= (all entities fall) - =apply-velocity-x=, =resolve-tile-collisions-x= (move and collide on x-axis) - =apply-velocity-y=, =resolve-tile-collisions-y= (move and collide on y-axis) - =detect-on-solid= (set #:on-ground? for next frame) -2. **scene-resolve-collisions**: after all entities are moved and collided with tiles, resolve entity-entity overlaps (boxes pushing apart) +2. **scene-transform-entities** with **resolve-entity-collisions**: after all entities are moved and collided with tiles, resolve entity-entity overlaps (boxes pushing apart) This pattern is efficient for sandbox simulations: apply the same pipeline to all entities, then resolve inter-entity collisions once. @@ -429,7 +431,7 @@ Notice that =resolve-tile-collisions-x= needs the tilemap argument, so it's wrap (lambda (e) (resolve-tile-collisions-x e tm)) #+end_src -Same for other functions that take tilemap. The =scene-update-entities= macro applies each function to all entities, so you wrap single-argument functions in a lambda to capture the tilemap. +Same for other functions that take tilemap. The =scene-map-entities= macro applies each function to all entities, so you wrap single-argument functions in a lambda to capture the tilemap. * Common Patterns @@ -514,7 +516,7 @@ For large games, consider spatial partitioning (grid, quadtree) to cull entity p ** Entities Get Stuck Overlapping -- Use =scene-resolve-collisions= after all physics steps +- Use =(scene-transform-entities scene resolve-entity-collisions)= after all physics steps - Verify both entities have =#:solid? #t= - Reduce =*gravity*= or max velocity if entities are moving too fast (can cause multi-frame overlap) |
