I am trying to teach my scratch-addicted son a bit about racket, and I&#39;m finding it to be rather tough going, mostly because a lot of things that are really easy in scratch seem surprisingly hard in racket.  Also, even when I can get things done, the performance of the graphics leaves something to be desired.  I&#39;m wondering if this is just the way the world is right now, or if somehow I&#39;m approaching this the wrong way.<div>
<br></div><div>I was trying to put together a simple animation using the universe and image teachpacks where:</div><div><br></div><div>- there is a &quot;sprite&quot; which switches between two images periodically</div><div>
- the sprite is always pointing at the mouse</div><div><br></div><div>I wrote some code for doing this.  One problem is that getting this to work required some actual trigonometry, which my 9 year old isn&#39;t quite ready for.  But that I could fix by writing a simple helper function.  But the other problem is that the resulting code is horribly slow.  As soon as you rotate the image, the rendering performance falls through the floor, and you see a ton of flickering.  </div>
<div><br></div><div>I&#39;ve attached the code below.  I can imagine some ways of optimizing this (for example, doing the rotations only on mouse moves, and storing the resulting rotated images in the world-struct), but I want to keep the coding style pretty simple, and I think these kinds of optimizations get in the way of comprehensibility.</div>
<div><br></div><div>Another thing I&#39;d be interested in suggestions with is how to deal with updating a struct in a clean way.  Right now, you need to explicitly wrote set-world-X functions for each field in your struct, which is pretty ugly.  Also, the fact that structs don&#39;t have field names makes them more error prone.  None of this is well suited towards building complex worlds with lots of components.  I&#39;m wondering if there is a better way of approaching this that doesn&#39;t require quadratic boilerplate, and that is suitable for teaching to a kid.</div>
<div><br></div><div>Anyway, here&#39;s the code.  Thanks in advance!</div><div><br></div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">;; the images here are actual PNG images, which don&#39;t show up nicely in ascii...</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define pic1 .)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define pic2 .)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br>
</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define (posn-diff a b)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (make-posn</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (- (posn-x a) (posn-x b))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (- (posn-y a) (posn-y b))))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define (posn-mag p)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (sqrt (+ (sqr (posn-x p)) (sqr (posn-y p)))))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define (angle-between pos1 pos2)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (let*</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">      ((delta (posn-diff pos2 pos1))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">       (hyp (posn-mag delta))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">       (angle-in-radians (if (= hyp 0) 0 (asin (/ (posn-y delta) hyp))))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">       )</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    (-(* angle-in-radians (/ 180 pi)))))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    </font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define-struct world (pos mouse-pos time))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define initial-world (make-world (make-posn 200 200) (make-posn 200 200) 0))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define (draw w)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (place-image</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (rotate (angle-between (world-pos w) (world-mouse-pos w))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">           (if (is-even (round (world-time w))) pic1 pic2))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (posn-x (world-pos w))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (posn-y (world-pos w))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (empty-scene 400 400)))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define (tick w)</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (make-world </font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (world-pos w)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (world-mouse-pos w)</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (+ 0.1 (world-time w))))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define (mouse w x y event)</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (make-world</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (world-pos w)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (make-posn x y)</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   (world-time w)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">   ))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br>
</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(big-bang</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"> initial-world</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"> (on-draw draw)</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"> (on-tick tick)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"> (on-mouse mouse)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"> )</font></div>
</div>