aboutsummaryrefslogtreecommitdiff
path: root/docs/physics.org
diff options
context:
space:
mode:
authorGene Pasquet <dev@etenil.net>2026-04-08 01:57:20 +0100
committerGene Pasquet <dev@etenil.net>2026-04-08 01:57:20 +0100
commit9e8b75f9949259ef01942cd3717b79b044efddf7 (patch)
treec6b71291ade57f0560a9bbf0db9f5b66bab65cb3 /docs/physics.org
parent84840ede6646ed793b61cdd889d3f57ab05e9311 (diff)
Refactor update pipelines
Diffstat (limited to 'docs/physics.org')
-rw-r--r--docs/physics.org38
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)