diff options
| author | Gene Pasquet <dev@etenil.net> | 2026-04-05 17:04:03 +0100 |
|---|---|---|
| committer | Gene Pasquet <dev@etenil.net> | 2026-04-05 17:04:03 +0100 |
| commit | ad8103fef0a43ec63323ea1902a647fb76dda670 (patch) | |
| tree | 38d4c3e2eea2b8bd9f6e2e8227b4abf78ae476fa | |
| parent | 1a9b07beea46e610801c7b2e0f2db188b3c4bdf1 (diff) | |
feat: implement game-run! — SDL2 init, lifecycle hooks, frame loop
| -rw-r--r-- | engine.scm | 64 | ||||
| -rw-r--r-- | tests/engine-test.scm | 6 |
2 files changed, 67 insertions, 3 deletions
@@ -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 diff --git a/tests/engine-test.scm b/tests/engine-test.scm index b026ce4..2c443cc 100644 --- a/tests/engine-test.scm +++ b/tests/engine-test.scm @@ -64,7 +64,11 @@ controller-axis-bindings: '((left-x right left) (left-y down up)) deadzone: 8000)) (define (create-input-state config) - (make-input-state '() '()))) + (make-input-state '() '())) + (define (input-state-update state events config) + state) + (define (input-held? state action) + #f)) (import downstroke/input) ;; --- World module (mock) --- |
