Welcome back to the Hooray! series — in this episode, which is right on the heels of the previous one, we actually cover three patches: numbers 5, 6, and 7. Up until now, the patches have had a uniform additive flavor — lots of adjacent “+” in the left-hand column — that indicate self-contained subsections not requiring much integration w/ the rest of the code. Today, we venture into new territory: (a) Patch 5, in addition to adding functionality, modifies functionality of existing code as well. (b) Patches 6 and 7 do the same, but with even more vigor and purpose! All in all, this should be a fun 10 minutes. Let's get started...
1 commit 08d8fe55c21d7db8e2f4491970f682fb8d2fe805 2 Author: Thien-Thi Nguyen <ttn@gnuvola.org> 3 Date: 2022-01-23 01:12:34 -0500 4 5 Add scenery 6 7 * hooray.scm (FAR): New data structure. 8 (refresh-scenery!): New proc. 9 (smokin): Call ‘refresh-scenery!
’. 10 --- 11 hooray.scm | 31 +++++++++++++++++++++++++++++++ 12 1 file changed, 31 insertions(+) 13 14 diff --git a/hooray.scm b/hooray.scm 15 index 0f8f0bd..b10c834 100644 16 --- a/hooray.scm 17 +++ b/hooray.scm 18 @@ -73,6 +73,35 @@ (SDL:set-video-mode (* 5 TILE-EDGE-LENGTH) 19 (* 5 TILE-EDGE-LENGTH) 20 32) 21 22 +(define FAR #2((window window window window window) 23 + (window cell cell cell window) 24 + (window cell cell cell window) 25 + (window cell cell cell window) 26 + (window window window window window))) 27 + 28 +(define refresh-scenery! 29 + (let ((rect (apply make-array #f (array-shape FAR)))) 30 + 31 + (define (place-tile! name rect) 32 + (SDL:blit-surface (hashq-ref HT name) #f #f rect) 33 + rect) 34 + 35 + ;; initialize ‘rect
’ 36 + (array-index-map! rect (lambda (r c) 37 + ;; note order change: r c => c r => x y 38 + (SDL:make-rect 39 + (* TILE-EDGE-LENGTH c) 40 + (* TILE-EDGE-LENGTH r) 41 + TILE-EDGE-LENGTH 42 + TILE-EDGE-LENGTH))) 43 + 44 + ;; refresh-scenery! 45 + (lambda () 46 + ;; far ground 47 + (array-map! rect place-tile! FAR rect) 48 + ;; mid ground 49 + (place-tile! 'rec-1 (array-ref rect 2 2))))) 50 + 51 (define smokin 52 (let ((keys (list->vector (hash-fold (lambda (k v acc) 53 (cons k acc)) 54 @@ -94,6 +123,8 @@ (define smokin 55 (lambda (millisecs) 56 (do ((i 0 (1+ i))) 57 ((= 420 i)) 58 + (and (zero? (modulo i 42)) 59 + (refresh-scenery!)) 60 (let ((tile (random-tile))) 61 (SDL:rect:set-x! rect (random-coord)) 62 (SDL:rect:set-y! rect (random-coord))
For this project, we define “scenery” as “stuff that goes behind the animation”, and divide it into the far ground and the mid ground.
Patch 5 starts by laying out, quite graphically, the far ground (lines 22-26).
That ‘#2(...)
’ is syntax for a two-dimensional array, in this case, of symbols.
The symbols are the names of tiles (see ‘load-theme
’).
We only use ‘window
’ and ‘cell
’ for now.
The main new stuff is procedure ‘refresh-scenery!
’ (starts at line 28).
It has internal procedure ‘place-tile!
’ (lines 31-33) which is responsible for blitting one tile.
Lines 29 and 36-42 set up an array (of the same shape as ‘FAR
’) of rectangles for the blit, to be configured once and then never changed again.
The body of ‘refresh-scenery!
’ is line 47, which handles the far ground, and line 49, which handles the mid ground (currently, just one tile — ‘rec-1
’ — in the center).
Remember “modifies functionality of existing code” in the lead paragraph?
Well, that's what the second hunk of patch 5 (lines 54-62) does.
It adds a call to ‘refresh-scenery!
’ to ‘smokin
’.
The effect is to periodically (every 42 iterations) refresh the scenery.
Here's what I see when I run “guile -s hooray.scm Linux.png”:
1 commit 6b4537afb60b479b7b91f5bb306f92d474591656 2 Author: Thien-Thi Nguyen <ttn@gnuvola.org> 3 Date: 2022-01-23 01:21:51 -0500 4 5 Add abstraction: surf 6 7 * hooray.scm (surf): New proc. 8 (refresh-scenery! place-tile!): Use ‘surf
’. 9 (smokin random-tile): Likewise. 10 --- 11 hooray.scm | 7 +++++-- 12 1 file changed, 5 insertions(+), 2 deletions(-) 13 14 diff --git a/hooray.scm b/hooray.scm 15 index b10c834..7b7c24f 100644 16 --- a/hooray.scm 17 +++ b/hooray.scm 18 @@ -69,6 +69,9 @@ (define (load-theme filename) ; => hash table 19 20 (define HT (load-theme (cadr (command-line)))) 21 22 +(define (surf name) 23 + (hashq-ref HT name)) 24 + 25 (SDL:set-video-mode (* 5 TILE-EDGE-LENGTH) 26 (* 5 TILE-EDGE-LENGTH) 27 32) 28 @@ -83,7 +86,7 @@ (define refresh-scenery! 29 (let ((rect (apply make-array #f (array-shape FAR)))) 30 31 (define (place-tile! name rect) 32 - (SDL:blit-surface (hashq-ref HT name) #f #f rect) 33 + (SDL:blit-surface (surf name) #f #f rect) 34 rect) 35 36 ;; initialize ‘rect
’ 37 @@ -117,7 +120,7 @@ (define smokin 38 (let ((name (vector-ref keys (random (vector-length keys))))) 39 (display " ") 40 (display name) 41 - (hashq-ref HT name))) 42 + (surf name))) 43 44 ;; smokin 45 (lambda (millisecs)
In contrast to previous patches, patch 6 has very little additive nature, and what it does add is not a user-visible feature, but an “abstraction”.
In fact, the only real addition is procedure ‘surf
’ (lines 22-23) in hunk 1.
Hunks 2 and 3 simply show ‘surf
’ being used to replace existing code in two other places.
This is the first time we see “-” in the left-hand column, but it won't be the last.
1 commit a2dd73f5ab85c7de1b60d1d95549d66785ddeef1 2 Author: Thien-Thi Nguyen <ttn@gnuvola.org> 3 Date: 2022-01-23 01:29:31 -0500 4 5 Add abstraction: make-tile-rect 6 7 * hooray.scm (make-tile-rect): New proc. 8 (load-theme): Use ‘make-tile-rect
’. 9 (refresh-scenery!): Likewise. 10 (smokin): Likewise. 11 --- 12 hooray.scm | 23 ++++++++++------------- 13 1 file changed, 10 insertions(+), 13 deletions(-) 14 15 diff --git a/hooray.scm b/hooray.scm 16 index 7b7c24f..ef226b2 100644 17 --- a/hooray.scm 18 +++ b/hooray.scm 19 @@ -37,6 +37,13 @@ (let-values (((cap mem fmt) (SDL:video-cmf))) 20 21 (define TILE-EDGE-LENGTH 64) 22 23 +(define (make-tile-rect r c) 24 + ;; note order change: r c => c r => x y 25 + (SDL:make-rect (* TILE-EDGE-LENGTH c) 26 + (* TILE-EDGE-LENGTH r) 27 + TILE-EDGE-LENGTH 28 + TILE-EDGE-LENGTH)) 29 + 30 (define (load-theme filename) ; => hash table 31 32 (define (proper surface) 33 @@ -47,9 +54,7 @@ (define (load-theme filename) ; => hash table 34 35 (let* ((theme (proper (SDL:load-image filename))) 36 (ht (make-hash-table)) 37 - (rect (SDL:make-rect 0 0 38 - TILE-EDGE-LENGTH 39 - TILE-EDGE-LENGTH))) 40 + (rect (make-tile-rect 0 0))) 41 42 (define (read-row! row tile-names) 43 (SDL:rect:set-y! rect (* TILE-EDGE-LENGTH row)) 44 @@ -90,13 +95,7 @@ (define refresh-scenery! 45 rect) 46 47 ;; initialize ‘rect
’ 48 - (array-index-map! rect (lambda (r c) 49 - ;; note order change: r c => c r => x y 50 - (SDL:make-rect 51 - (* TILE-EDGE-LENGTH c) 52 - (* TILE-EDGE-LENGTH r) 53 - TILE-EDGE-LENGTH 54 - TILE-EDGE-LENGTH))) 55 + (array-index-map! rect make-tile-rect) 56 57 ;; refresh-scenery! 58 (lambda () 59 @@ -109,9 +108,7 @@ (define smokin 60 (let ((keys (list->vector (hash-fold (lambda (k v acc) 61 (cons k acc)) 62 '() HT))) 63 - (rect (SDL:make-rect 0 0 64 - TILE-EDGE-LENGTH 65 - TILE-EDGE-LENGTH))) 66 + (rect (make-tile-rect 0 0))) 67 68 (define (random-coord) 69 (* TILE-EDGE-LENGTH (random 5)))
Like patch 6, patch 7 adds an abstraction.
This time, it's the procedure ‘make-tile-rect
’ (lines 23-28), which is then used in three other places (hunks 2, 3, 4).
The result is a very satisfying negative delta — 10 insertions and 13 deletions (line 13) means the net change is 3 deletions — the code is smaller!
OK, see you next time.
Copyright (C) 2022 Thien-Thi Nguyen