Skip to content
August 20, 2011 / cdsmith

Animations Added to Web-Based Haskell/Gloss

The Feature

I’ve added animations to the web-based Gloss/Haskell environment at http://dac4.designacourse.com:8000/anim.  You should export a symbol

animation :: Float -> Picture

and you’ll see it in modern web browsers.  By “modern” we mean:

  • Firefox 6.0 or higher (yes, the one released just a couple days ago)
  • Chrome, Safari, or Opera, any recent version
  • The iOS browser should work (untested).
  • Internet Explorer and the built-in Android browser are known not to work.  On both operating systems, Firefox 6 is available and does work.

The feature we need is called “server sent events”, an HTML 5 extension that makes “comet” style web applications work without a whole tool shed of browser-specific kludges.  So, if you are curious about another browser, see if it implements server-sent events.  Or just try it.

Edit: As of Sunday, you can now do “simulations” as well.  The URL for simulations is http://dac4.designacourse.com:8000/sim.  These are a little more involved.  You need to define three symbols sharing a common data type of your choosing:

initial :: StdGen -> a
step :: ViewPort -> Float -> a -> a
draw :: a -> Picture

Here, initial returns the starting value of your chosen data type.  (Its parameter is a pseudo-random number generator, in case you want random numbers.)  The step function is responsible for “advancing” the simulation by some amount of time.  Finally, the draw function is reponsible for converting the current simulation to a picture to draw on the screen.  The difference between simulations and animations is that animations calculate the picture from scratch each time: you give it a time since the start, and get back a picture.  Simulations, on the other hand, play out incrementally: each new state depends only on the most recent state and the amount of time that’s passed since then.  You can always turn an animation into a simulation by defining initial = 0 and step = const (+) where the type “a” is Float.  But not all simulations can be efficiently written as animations.

Under the Hood

The previous version of the application (which still works just fine) displayed only static pictures, and did so by loading some JSON directly into the document and then having JavaScript draw it on a canvas.  This new animation mode is a little different.  The steps are:

  1. You submit your function.
  2. The server compiles your code (using SafeHaskell, of course), and stores your function along with the start time in a lookup table.
  3. The animation page loads, and has a key to that lookup table.
  4. The animation page connects back to the server using the JavaScript EventSource object (that’s the server-sent events feature).
  5. The server then streams newly updated pictures as JSON along that connection.

Incidentally, if you’re thinking of implementing a “comet”-style web application with Snap, you might be interested in the code at https://github.com/cdsmith/gloss-web/blob/master/src/EventStream.hs which implements the server side of the event stream format.  It’s a generic module that you can transplant into your own code.  In the future, I’ll look at the best way to get it packaged either as part of a snap package or as a stand-alone library.  As short as it is, though, I hope to avoid adding that dependency weight.

Anyway, that’s animations for you.  Have fun!

Examples

The following program draws the solar system, representing the distances of all the planets from the sun, their orbital periods, their relative sizes.  The one thing that’s not accurate is the relationship between the sizes of the planets and their distance from the sun… something had to give, since a completely to-scale representation of the solar system would just look empty!  Also, I didn’t bother representing the eccentricities of orbits.

import Graphics.Gloss

animation t = pictures [
    color black (rectangleSolid 500 500),
    sun,
    rotate (60 * t /   0.24) (translate   4 0 mercury),
    rotate (60 * t /   0.62) (translate   7 0 venus),
    rotate (60 * t /   1.00) (translate   9 0 earth),
    rotate (60 * t /   1.88) (translate  14 0 mars),
    rotate (60 * t /  11.86) (translate  48 0 jupiter),
    rotate (60 * t /  29.46) (translate  89 0 saturn),
    rotate (60 * t /  84.32) (translate 178 0 uranus),
    rotate (60 * t / 164.80) (translate 279 0 neptune)
    ]

sun     = color orange         (circle 69)
mercury = color (dark white)   (circle 0.25)
venus   = color (light yellow) (circle 0.6)
earth   = color (light blue)   (circle 0.63)
mars    = color (dark orange)  (circle 0.34)
jupiter = color (light orange) (circle 7.1)
saturn  = color (light yellow) (circle 6.0)
uranus  = color azure          (circle 2.6)
neptune = color blue           (circle 2.5)

Here’s the tree example from the the gloss-examples package.  Unfortunately, it pegs the server’s CPU at 50%… so I’ll have to work on what’s making it run so slowly.

import Graphics.Gloss

animation :: Float -> Picture
animation time
	= Scale 0.8 0.8 $ Translate 0 (-300)
	$ tree 4 time (dim $ dim brown)

-- Basic stump shape
stump :: Color -> Picture
stump color
	= Color color
	$ Polygon [(30,0), (15,300), (-15,300), (-30,0)]

-- Make a tree fractal.
tree 	:: Int 		-- Fractal degree
	-> Float	-- time
	-> Color 	-- Color for the stump
	-> Picture

tree 0 time color = stump color
tree n time color
 = let	smallTree
		= Rotate (sin time)
		$ Scale 0.5 0.5
		$ tree (n-1) (- time) (greener color)
   in	Pictures
		[ stump color
		, Translate 0 300 $ smallTree
		, Translate 0 240 $ Rotate 20	 smallTree
		, Translate 0 180 $ Rotate (-20) smallTree
		, Translate 0 120 $ Rotate 40 	 smallTree
		, Translate 0  60 $ Rotate (-40) smallTree ]

-- A starting colour for the stump
brown :: Color
brown =  makeColor8 139 100 35  255

-- Make this color a little greener
greener :: Color -> Color
greener c = mixColors 1 10 green c
About these ads

3 Comments

Leave a Comment
  1. Ivan / Aug 23 2011 4:54 am

    Dear Chris

    This sounds very impressive! I’ll be interested in looking at how Haskell does comet (I’m currently developing a comet server in erlang).

    However the two urls (anim & sim) are both returning 404s at the moment.

    Best wishes

    Ivan

    • Ivan / Aug 23 2011 5:00 am

      Scrub that. I found the pages (removed the “.html”)

      Best

      Ivan

  2. Alfredo Di Napoli / Nov 14 2011 12:14 pm

    On my iPad it worked like a charm :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 62 other followers

%d bloggers like this: