diff options
| author | Gene Pasquet <dev@etenil.net> | 2026-04-08 01:05:50 +0100 |
|---|---|---|
| committer | Gene Pasquet <dev@etenil.net> | 2026-04-08 01:05:50 +0100 |
| commit | 995342fb74fdd1ba5aeaa172a428538e7dd0dcdc (patch) | |
| tree | 82a60034eaa097191d360fe07e4ef3a52dae9c2a /engine.scm | |
| parent | 0c3a700aa94a0256c5e5b1a14819f10b3d3e869b (diff) | |
Code cleanup
Diffstat (limited to 'engine.scm')
| -rw-r--r-- | engine.scm | 112 |
1 files changed, 54 insertions, 58 deletions
@@ -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!)) |
