aboutsummaryrefslogtreecommitdiff
path: root/engine.scm
diff options
context:
space:
mode:
authorGene Pasquet <dev@etenil.net>2026-04-05 19:47:05 +0100
committerGene Pasquet <dev@etenil.net>2026-04-05 19:47:05 +0100
commit027053b11a3a5d861ed2fa2db245388bd95ac246 (patch)
tree84dfd90642bb6d8eb4e0e3fa3a9d651ba29b41e8 /engine.scm
parent927f37639a3d5a0d881a5c8709f2cf577aadb15e (diff)
Progress
Diffstat (limited to 'engine.scm')
-rw-r--r--engine.scm54
1 files changed, 42 insertions, 12 deletions
diff --git a/engine.scm b/engine.scm
index 73e88f0..553dddf 100644
--- a/engine.scm
+++ b/engine.scm
@@ -6,6 +6,7 @@
(prefix sdl2 "sdl2:")
(prefix sdl2-ttf "ttf:")
(prefix sdl2-image "img:")
+ (srfi 69)
defstruct
downstroke/world
downstroke/input
@@ -26,7 +27,9 @@
create-hook ;; (lambda (game) ...)
update-hook ;; (lambda (game dt) ...)
render-hook ;; (lambda (game) ...) — post-render overlay
- scene) ;; current scene struct; #f until create: runs
+ scene ;; current scene struct; #f until create: runs
+ states ;; hash-table of name → state-plist
+ active-state) ;; symbol or #f — currently active state name
;; Store the auto-generated constructor as make-game*
(define make-game* make-game)
@@ -54,7 +57,9 @@
preload-hook: preload
create-hook: create
update-hook: update
- render-hook: render))
+ render-hook: render
+ states: (make-hash-table)
+ active-state: #f))
;; ── Convenience accessors ──────────────────────────────────────────────────
@@ -70,6 +75,27 @@
(define (game-asset-set! game key value)
(asset-set! (game-assets game) key value))
+;; ── Named scene states ────────────────────────────────────────────────────
+
+;; Construct a state plist with lifecycle hooks.
+(define (make-game-state #!key (create #f) (update #f) (render #f))
+ (list #:create create #:update update #:render render))
+
+;; Retrieve a value from a state plist.
+(define (state-hook state key)
+ (get-keyword key state (lambda () #f)))
+
+;; Register a named state. name is a symbol; state is a make-game-state plist.
+(define (game-add-state! game name state)
+ (hash-table-set! (game-states game) name state))
+
+;; Transition to a named state. Calls the state's create: hook if present.
+(define (game-start-state! game name)
+ (game-active-state-set! game name)
+ (let* ((state (hash-table-ref (game-states game) name))
+ (create (state-hook state #:create)))
+ (when create (create game))))
+
;; ── game-run! ──────────────────────────────────────────────────────────────
;; Main event loop and lifecycle orchestration
@@ -93,7 +119,7 @@
(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)))
+ (sdl2:create-renderer! (game-window game) -1 '(accelerated)))
;; 3. preload: hook — user loads assets here
(when (game-preload-hook game)
@@ -119,15 +145,19 @@
(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))
+ ;; 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))
+ (sdl2:render-clear! (game-renderer game))
+ (when (game-scene game)
+ (render-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)))))