On Feb 1, 2011, at 9:27 PM, Yaron Minsky wrote:

> I am trying to teach my scratch-addicted son a bit about racket, and I'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'm wondering if this is just the way the world is right now, or if 
> somehow I'm approaching this the wrong way.
> 
> I was trying to put together a simple animation using the universe and image 
> teachpacks where:
> 
> - there is a "sprite" which switches between two images periodically
> - the sprite is always pointing at the mouse

When I run this code, the sprite points at the mouse as long as the mouse is to 
the right of the sprite; once I move to its left, the sprite rotates in the 
wrong direction.

And there are some minor inefficiencies that have nothing to do with the 
graphics-and-animation library.

As it happens, one can address both of these at the same time: replace
       (hyp (posn-mag delta))
       (angle-in-radians (if (= hyp 0) 0 (asin (/ (posn-y delta) hyp))))
with
       (angle-in-radians (if (= (posn-x delta) (posn-y delta) 0)
                             0
                             (atan (posn-y delta) (posn-x delta))))
which requires not only less computation (you can drop the "hyp" function 
entirely) but less knowledge of trig.



There are a number of other things that would simplify the code, some of which 
would also make things (slightly) more efficient.

Your sprite switches between its two images every 10 clock-ticks, where a 
clock-tick defaults to 1/28 second.  Instead, just set the tick interval to 
what you want, and skip the 0.1 and the rounding.

(big-bang ...
      (on-tick tick (/ 1 2.8))   ; or (on-tick tick 1/3) or (on-tick tick .382) 
or whatever
      ... )

And since there are only two possible images in the world, I would probably use 
a boolean or a pair of symbols or strings to choose between them:

(define WIDTH 400)
(define HEIGHT 400)
(define BACKGROUND (empty-scene WIDTH HEIGHT))
(define CENTER (make-posn (/ WIDTH 2) (/ HEIGHT 2)))
(define-struct world (pos mouse-pos sprite))
(define initial-world (make-world CENTER CENTER "fred"))
...
(define (next-sprite current)
   (cond [(string=? current "fred") "george"]
              [(string=? current "george") "fred"]))
(define (sprite-image current)
   (cond [(string=? current "fred") pic1]
              [(string=? current "george") pic2]))
(define (draw w)
   (place-image
      (rotate (angle-between (world-pos w) (world-mouse-pos w))
                  (sprite-image (world-sprite w)))
      (posn-x (world-pos w))
      (posn-y (world-pos w))
      BACKGROUND))

(Symbols or booleans would be slightly more efficient, but I introduce strings 
much earlier in my course than symbols or booleans.)

> Another thing I'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't have field names makes them more error 
> prone.  None of this is well suited towards building complex worlds with lots 
> of components.

I'm not sure what you mean by "structs don't have field names", but the issue 
of updating individual fields of a struct is under discussion; in a version 
Fairly Soon the student languages will probably have functions that produce a 
copy of a given struct with a single field replaced.


Stephen Bloch
[email protected]


_________________________________________________
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/users

Reply via email to