aboutsummaryrefslogtreecommitdiff
path: root/physics.scm
diff options
context:
space:
mode:
authorGene Pasquet <dev@etenil.net>2026-04-07 23:42:08 +0100
committerGene Pasquet <dev@etenil.net>2026-04-07 23:42:08 +0100
commitcfddc2f180552afdb080968f847018c5a223b41a (patch)
tree61f982e5ab20dc10c732c135d6e335531abface1 /physics.scm
parent19a5db8606a82830a5ccd0ed46d8e0cf3c95db0a (diff)
Use entities as platforms
Diffstat (limited to 'physics.scm')
-rw-r--r--physics.scm34
1 files changed, 23 insertions, 11 deletions
diff --git a/physics.scm b/physics.scm
index 979eb4b..083046d 100644
--- a/physics.scm
+++ b/physics.scm
@@ -257,20 +257,32 @@
;; Move ~m~ out of ~s~ along the shallow penetration axis; ~s~ is unchanged.
;; Used when ~s~ has #:immovable? #t.
+ ;;
+ ;; When ~m~ is falling onto ~s~ from above, the minimum-penetration axis can be
+ ;; horizontal (narrow overlap in X but deeper in Y), which shoves the mover
+ ;; sideways instead of resting it on the platform. Prefer vertical separation
+ ;; whenever ~m~'s center is still above ~s~'s center (landing contact).
(define (separate-movable-from-static m s)
(let* ((ovx (aabb-overlap-on-axis #:x m s))
- (ovy (aabb-overlap-on-axis #:y m s)))
- (if (<= ovx ovy)
- (let* ((mc (entity-center-on-axis m #:x))
- (sc (entity-center-on-axis s #:x))
- (dir (if (< mc sc) -1 1))
- (mx (entity-ref m #:x 0)))
- (entity-set (entity-set m #:x (+ mx (* dir ovx))) #:vx 0))
- (let* ((mc (entity-center-on-axis m #:y))
- (sc (entity-center-on-axis s #:y))
- (dir (if (< mc sc) -1 1))
+ (ovy (aabb-overlap-on-axis #:y m s))
+ (m-cy (entity-center-on-axis m #:y))
+ (s-cy (entity-center-on-axis s #:y))
+ (land-on-top? (and (< m-cy s-cy) (> ovy 0))))
+ (if land-on-top?
+ (let* ((dir (if (< m-cy s-cy) -1 1))
(my (entity-ref m #:y 0)))
- (entity-set (entity-set m #:y (+ my (* dir ovy))) #:vy 0)))))
+ (entity-set (entity-set m #:y (+ my (* dir ovy))) #:vy 0))
+ (if (<= ovx ovy)
+ (let* ((mc (entity-center-on-axis m #:x))
+ (sc (entity-center-on-axis s #:x))
+ (dir (if (< mc sc) -1 1))
+ (mx (entity-ref m #:x 0)))
+ (entity-set (entity-set m #:x (+ mx (* dir ovx))) #:vx 0))
+ (let* ((mc (entity-center-on-axis m #:y))
+ (sc (entity-center-on-axis s #:y))
+ (dir (if (< mc sc) -1 1))
+ (my (entity-ref m #:y 0)))
+ (entity-set (entity-set m #:y (+ my (* dir ovy))) #:vy 0))))))
;; Check if two axis-aligned bounding boxes overlap.
;; Returns #t if they overlap, #f if they don't (including edge-touching).