trip logs / gnuvola


Trip Log 2022-02-05 h06 -- Hooray! Part 9

We're now officially in the tail end of the Hooray! series, as there are no more parts predicted after part 12.  In this Trip Log, we look at two patches: patch 26 adds growth (in the fg sprite), and patch 27 adds rotation.  But before we look at those relatively simple patches, remember all the infelicities we fixed in part 8?  I forgot to post the word count stats for those collective changes.  Here they are: 

$ wc hooray.scm.{WAS,NOW}
  332  1043  9536 hooray.scm.WAS
  325  1028  9396 hooray.scm.NOW
  657  2071 18932 totale

Look at that!  Reduction not only in words, but in lines and characters, as well.  Light makes right, like they say... 

patch 26

     1  commit 321eccc7bbb90ce9182d3e1f4b1ddaab71ef7a52
     2  Author: Thien-Thi Nguyen <ttn@gnuvola.org>
     3  Date:   2022-02-05 00:15:20 -0500
     4  
     5      Add growth
     6      
     7      * hooray.scm: Import ‘(sdl misc-utils) rect<-surface’.
     8      Import ‘(sdl gfx) zoom-surface’.
     9      (hooray! fg-step size!): New proc.
    10      (hooray! fg-step): Resize the surface before dimming.
    11      (hooray!): Convert ‘dst’ to use ‘svec’;
    12      initialize it based on ‘fg’ dimensions;
    13      adjust per-iteration access and updates accordingly.
    14  ---
    15   hooray.scm | 14 ++++++++++----
    16   1 file changed, 10 insertions(+), 4 deletions(-)
    17  
    18  diff --git a/hooray.scm b/hooray.scm
    19  index 75c0520..164f7a6 100644
    20  --- a/hooray.scm
    21  +++ b/hooray.scm
    22  @@ -30,8 +30,10 @@ (use-modules
    23    ((srfi srfi-1) #:select (car+cdr))
    24    ((srfi srfi-11) #:select (let-values))
    25    ((sdl misc-utils) #:select (copy-surface
    26  +                             rect<-surface
    27                                exact-truncate))
    28    ((sdl gfx) #:select (blit-rgba
    29  +                      zoom-surface
    30                         imfi-sub-c))
    31    ((sdl sdl) #:prefix SDL:))
    32   
    33  @@ -196,6 +198,9 @@ (define hooray!
    34   
    35       (define (fg-step put fraction)
    36   
    37  +      (define (size! surface)
    38  +        (zoom-surface surface (* 4.20 fraction) #f #t))
    39  +
    40         (define (dim! surface)
    41           (let ((c (exact-truncate (* 256 fraction))))
    42             ;; Ideally we would operate only on the alpha channel
    43  @@ -206,7 +211,7 @@ (define hooray!
    44             (imfi-sub-c surface surface c)
    45             surface))
    46   
    47  -      (dim! put))
    48  +      (dim! (size! put)))
    49   
    50       (define (/2 n)
    51         (ash n -1))
    52  @@ -254,13 +259,14 @@ (define hooray!
    53             (vx (tvec))                   ; velocity
    54             (vy (tvec))
    55             (gravity (tvec))
    56  -          (dst (make-fg-rect)))
    57  +          (dst (svec)))
    58   
    59         (array-index-map! fg (lambda (i)
    60                                (fg-step (make-put (surf 'win))
    61                                         (/ i step-count))))
    62         (array-map! w/2 (half SDL:surface:w) fg)
    63         (array-map! h/2 (half SDL:surface:h) fg)
    64  +      (array-map! dst rect<-surface fg)
    65   
    66         ;; hooray!
    67         (lambda ()
    68  @@ -270,7 +276,7 @@ (define hooray!
    69           (array-map! vy (random-v (random -4.20)))
    70           (array-map! gravity random-gravity)
    71           (array-for-each
    72  -         (lambda (fg w/2 h/2)
    73  +         (lambda (fg w/2 h/2 dst)
    74              (refresh-scenery!)
    75              (bump! x vx)
    76              (bump! y vy)
    77  @@ -278,7 +284,7 @@ (define hooray!
    78              (array-for-each (place-fg! fg w/2 h/2 dst)
    79                              x y)
    80              (show! 42))
    81  -         fg w/2 h/2)))))
    82  +         fg w/2 h/2 dst)))))
    83   
    84   (define (change-scenery-slightly!)
    85   

Let's really pick this apart, since it seems so sparse compared to the great swaths of adjacent left-hand-column “+” we've seen in previous patches.  First off, the imports (lines 7-8, 26, 29).  The strategy behind adding growth is to precompute the fg images, as before, but this time vary their size (or in SDL terms, their “zoom factor”) along w/ their transparency.  Since each fg has a different dimension (now), this means each will need its own destination rectangle.  Convenience proc ‘rect<-surface’ helps w/ that.  As for ‘zoom-surface’, we'll get to that next. 

Zooming is done by the new internal proc ‘size!’ (lines 9, 37-38).  There, we specify that the surface should grow from 0.00 up to 4.20 times its original dimension.  We only specify the zoom factor for the horizontal dimension; 3rd arg ‘#f’ means use the same factor for the vertical dimension.  Lastly, 4th arg ‘#t’ means to smooth the edges, which is prettier.  All this is wrapped up in the fg image creation “pipeline” (line 48), first the sizing, then the transparency. 

The next hunk shows that instead of one destination rectangle, we now have a svec of them (lines 56-57), and that they are initialized based on the corresponding fg surface (line 64).  The last hunk adds ‘dst’ to the outer loop (which executes ‘step-size’ times), so that in the inner loop (which executes ‘throng’ times), the appropriate destination rectangle is used for placement.  That's it! 

patch 27

     1  commit 5cdc38990769e0b49163ea52f3301861e0d3ff08
     2  Author: Thien-Thi Nguyen <ttn@gnuvola.org>
     3  Date:   2022-02-05 00:21:17 -0500
     4  
     5      Add rotation
     6      
     7      * hooray.scm: Don't import ‘(sdl gfx) zoom-surface’;
     8      instead, import ‘(sdl gfx) roto-zoom-surface’.
     9      (hooray! fg-step size!): Delete proc.
    10      (hooray! fg-step size/rotate!): New proc.
    11      (hooray! fg-step): Use ‘size/rotate!’.
    12  ---
    13   hooray.scm | 13 ++++++++-----
    14   1 file changed, 8 insertions(+), 5 deletions(-)
    15  
    16  diff --git a/hooray.scm b/hooray.scm
    17  index 164f7a6..e4a8ae8 100644
    18  --- a/hooray.scm
    19  +++ b/hooray.scm
    20  @@ -33,7 +33,7 @@ (use-modules
    21                                rect<-surface
    22                                exact-truncate))
    23    ((sdl gfx) #:select (blit-rgba
    24  -                      zoom-surface
    25  +                      roto-zoom-surface
    26                         imfi-sub-c))
    27    ((sdl sdl) #:prefix SDL:))
    28   
    29  @@ -198,9 +198,6 @@ (define hooray!
    30   
    31       (define (fg-step put fraction)
    32   
    33  -      (define (size! surface)
    34  -        (zoom-surface surface (* 4.20 fraction) #f #t))
    35  -
    36         (define (dim! surface)
    37           (let ((c (exact-truncate (* 256 fraction))))
    38             ;; Ideally we would operate only on the alpha channel
    39  @@ -211,7 +208,13 @@ (define hooray!
    40             (imfi-sub-c surface surface c)
    41             surface))
    42   
    43  -      (dim! (size! put)))
    44  +      (define (size/rotate! surface)
    45  +        (roto-zoom-surface surface
    46  +                           (+ 21.5 (* -42.0 fraction))
    47  +                           (* 4.20 fraction)
    48  +                           #t))
    49  +
    50  +      (dim! (size/rotate! put)))
    51   
    52       (define (/2 n)
    53         (ash n -1))

This patch is very simple in comparison to patch 26.  We simply swap out ‘zoom-surface’ for ‘roto-zoom-surface’ (lines 7-8), and construct a completely new internal procedure ‘size/rotate!’ that does both sizing and rotation (lines 44-48).  Now that we have ‘size/rotate!’ in the pipeline (line 50), we can get rid of ‘size!’ (lines 33-35). 

In ‘size/rotate!’, note that the sizing portion (line 47) is the same as before.  The rotation portion (line 46) makes for a slight clockwise rotation.  We use 21.5 instead of plain 21.0 to avoid a glitch in the animation apparently surrounding rotation angle 0.0 (no rotation).  The no-work optimization in SDL_gfx is not quite continuous, unfortunately. 

Here's what I see when I run “guile -s hooray.scm Simple.png”: 

So let's look at the checklist now: 

* PipeWalker fg behavior (to reproduce if possible)
  - [X] starts near top of center tile
  - [x] mostly upward velocity
  - [X] rotates clockwise slightly
  - [X] starts smaller than 32x32
  - [x] grows quickly
  - [ ] non synchronized (all aspects)
  - [x] fades to transparent

We got “rotates clockwise slightly” and “starts smaller than 32x32” perfectly.  The “grows quickly” gets a small “x” because the growth is not so exciting (even though that is very similar to the PipeWalker behavior).  We can probably do better.  OK, see you next time! 


Copyright (C) 2022 Thien-Thi Nguyen