aboutsummaryrefslogtreecommitdiff
path: root/engine.scm
diff options
context:
space:
mode:
authorGene Pasquet <dev@etenil.net>2026-04-05 17:04:03 +0100
committerGene Pasquet <dev@etenil.net>2026-04-05 17:04:03 +0100
commitad8103fef0a43ec63323ea1902a647fb76dda670 (patch)
tree38d4c3e2eea2b8bd9f6e2e8227b4abf78ae476fa /engine.scm
parent1a9b07beea46e610801c7b2e0f2db188b3c4bdf1 (diff)
feat: implement game-run! — SDL2 init, lifecycle hooks, frame loop
Diffstat (limited to 'engine.scm')
-rw-r--r--engine.scm64
1 files changed, 62 insertions, 2 deletions
diff --git a/engine.scm b/engine.scm
index f6c9db7..73e88f0 100644
--- a/engine.scm
+++ b/engine.scm
@@ -71,9 +71,69 @@
(asset-set! (game-assets game) key value))
;; ── game-run! ──────────────────────────────────────────────────────────────
-;; Stub — implemented in Task 4
+;; Main event loop and lifecycle orchestration
(define (game-run! game)
- (error "game-run! not yet implemented"))
+ ;; 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
+ (game-window-set! game
+ (sdl2:create-window! (game-title game) 'centered 'centered
+ (game-width game) (game-height game) '()))
+ (game-renderer-set! game
+ (sdl2:create-renderer! (game-window game) -1 '(accelerated vsync)))
+
+ ;; 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))
+
+ ;; 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)
+ ;; update: hook — user game logic
+ (when (game-update-hook game)
+ ((game-update-hook game) game dt))
+ ;; render: engine draws world, then user overlay
+ (sdl2:render-clear! (game-renderer game))
+ (when (game-scene game)
+ (render-scene! (game-renderer game) (game-scene game)))
+ (when (game-render-hook game)
+ ((game-render-hook game) game))
+ (sdl2:render-present! (game-renderer game))
+ (sdl2:delay! (game-frame-delay game))
+ (loop now)))))
+
+ ;; 6. Cleanup
+ (sdl2:destroy-window! (game-window game))
+ (sdl2:quit!))
) ;; end module