aboutsummaryrefslogtreecommitdiff
path: root/engine.scm
diff options
context:
space:
mode:
Diffstat (limited to 'engine.scm')
-rw-r--r--engine.scm112
1 files changed, 54 insertions, 58 deletions
diff --git a/engine.scm b/engine.scm
index d88a94b..1d2c14f 100644
--- a/engine.scm
+++ b/engine.scm
@@ -115,25 +115,59 @@
(set! (sdl2:render-draw-color renderer) (sdl2:make-color r g b a)))
(set! (sdl2:render-draw-color renderer) (sdl2:make-color 0 0 0 255)))))
+;; ── game-run! helpers ─────────────────────────────────────────────────────
+
+(define (collect-sdl-events)
+ (sdl2:pump-events!)
+ (let collect ((lst '()))
+ (if (not (sdl2:has-events?))
+ (reverse lst)
+ (let ((e (sdl2:make-event)))
+ (sdl2:poll-event! e)
+ (collect (cons e lst))))))
+
+(define (resolve-hooks game)
+ (let* ((active (game-active-state game))
+ (state (and active
+ (hash-table-ref/default (game-states game) active #f))))
+ (values (or (and state (state-hook state #:update)) (game-update-hook game))
+ (or (and state (state-hook state #:render)) (game-render-hook game)))))
+
+(define (update-camera-follow! game)
+ (when (game-scene game)
+ (let ((target-tag (scene-camera-target (game-scene game))))
+ (when target-tag
+ (let ((target (scene-find-tagged (game-scene game) target-tag)))
+ (when target
+ (camera-follow! (scene-camera (game-scene game))
+ target
+ (game-width game)
+ (game-height game))))))))
+
+(define (game-render! game render-fn)
+ (renderer-set-clear-color! (game-renderer game) (game-scene game))
+ (sdl2:render-clear! (game-renderer game))
+ (when (game-scene game)
+ (render-scene! (game-renderer game) (game-scene game)))
+ (when (and (game-debug? game) (game-scene game))
+ (render-debug-scene! (game-renderer game) (game-scene game)))
+ (when render-fn (render-fn game))
+ (sdl2:render-present! (game-renderer game)))
+
;; ── game-run! ──────────────────────────────────────────────────────────────
-;; Main event loop and lifecycle orchestration
(define (game-run! game)
- ;; 1. SDL2 init (audio excluded — mixer.scm not yet extracted;
- ;; user calls init-audio! in their preload: hook)
(sdl2:set-main-ready!)
(sdl2:init! '(video joystick game-controller))
(ttf:init!)
(img:init! '(png))
- ;; Open any already-connected game controllers
(let init-controllers ((i 0))
(when (< i (sdl2:num-joysticks))
(when (sdl2:is-game-controller? i)
(sdl2:game-controller-open! i))
(init-controllers (+ i 1))))
- ;; 2. Create window + renderer (window size = logical size × scale)
(let ((scale (game-scale game)))
(game-window-set! game
(sdl2:create-window! (game-title game) 'centered 'centered
@@ -146,61 +180,23 @@
(game-renderer game)
(list (game-width game) (game-height game)))))
- ;; 3. preload: hook — user loads assets here
- (when (game-preload-hook game)
- ((game-preload-hook game) game))
-
- ;; 4. create: hook — user builds initial scene here
- (when (game-create-hook game)
- ((game-create-hook game) game))
+ (when (game-preload-hook game) ((game-preload-hook game) game))
+ (when (game-create-hook game) ((game-create-hook game) game))
- ;; 5. Frame loop
(let loop ((last-ticks (sdl2:get-ticks)))
- (let* ((now (sdl2:get-ticks))
- (dt (- now last-ticks)))
- ;; Collect all pending SDL2 events
- (sdl2:pump-events!)
- (let* ((events (let collect ((lst '()))
- (if (not (sdl2:has-events?))
- (reverse lst)
- (let ((e (sdl2:make-event)))
- (sdl2:poll-event! e)
- (collect (cons e lst))))))
- (input (input-state-update (game-input game) events
- (game-input-config game))))
- (game-input-set! game input)
- (unless (input-held? input 'quit)
- ;; Dispatch to active state hooks, or fall back to game's own hooks
- (let* ((active (game-active-state game))
- (state (and active
- (hash-table-ref/default (game-states game) active #f)))
- (update-fn (or (and state (state-hook state #:update))
- (game-update-hook game)))
- (render-fn (or (and state (state-hook state #:render))
- (game-render-hook game))))
- (when update-fn (update-fn game dt))
- ;; Auto camera-follow: if scene has a camera-target tag, follow it
- (when (game-scene game)
- (let ((target-tag (scene-camera-target (game-scene game))))
- (when target-tag
- (let ((target (scene-find-tagged (game-scene game) target-tag)))
- (when target
- (camera-follow! (scene-camera (game-scene game))
- target
- (game-width game)
- (game-height game)))))))
- (renderer-set-clear-color! (game-renderer game) (game-scene game))
- (sdl2:render-clear! (game-renderer game))
- (when (game-scene game)
- (render-scene! (game-renderer game) (game-scene game)))
- (when (and (game-debug? game) (game-scene game))
- (render-debug-scene! (game-renderer game) (game-scene game)))
- (when render-fn (render-fn game)))
- (sdl2:render-present! (game-renderer game))
- (sdl2:delay! (game-frame-delay game))
- (loop now)))))
-
- ;; 6. Cleanup
+ (let* ((now (sdl2:get-ticks))
+ (dt (- now last-ticks))
+ (input (input-state-update (game-input game) (collect-sdl-events)
+ (game-input-config game))))
+ (game-input-set! game input)
+ (unless (input-held? input 'quit)
+ (receive (update-fn render-fn) (resolve-hooks game)
+ (when update-fn (update-fn game dt))
+ (update-camera-follow! game)
+ (game-render! game render-fn))
+ (sdl2:delay! (game-frame-delay game))
+ (loop now))))
+
(sdl2:destroy-window! (game-window game))
(sdl2:quit!))