[reactive] Stars - a simple reactive simulation with an alternative Reactive implementation

Jules Bean jules at jellybean.co.uk
Tue Dec 16 03:51:24 EST 2008


Hi,

I've just uploaded the results of my tinkering with Reactive-style FRP to

http://roobarb.jellybean.co.uk/~jules/stars.4.tgz

It should compile with ghc 6.8 or 6.6 and presumably also 6.10. I
recommend the command-line:

ghc -threaded -O2 --make stars.hs

It doesn't have any library dependencies outside of extralibs (opengl
et al). It's not very interactive but you can do the following:

* mouseover the planets to see a price list
* mouseover a ship to see what it's carrying
* PgUp/PgDn to zoom in/out
* click on a ship (not the easiest thing in the world with the speed
   they move at) to switch to a view which centers on the ship.

My goals on writing this code were to exhibit various different kinds
of discrete and continuous behaviour as a serious test on how the
framework holds together. All kinds of stuff is displayed around the
edges of the screen so you can see stuff changing or not changing.

The "simulated universe" evolves at fixed rate based on a ticking
timer. Two and a half ticks per second. The frame rate is completely
independent of that, and is capped at around 60fps by virtue of a 16ms
timer, although I make no attempt to keep it smooth. I suspect it's
fairly vicious on your CPU; it runs OK for me on a 2Ghz C2D. The
actual displayed location of the ships is "tweened" between the last
and next 'tick' for smooth movement, the percentage of 'tween' is
shown in the top-left.

MouseMotion events from GLUT update the world-coordinate mouse
position which enables the mouseover code for ships and planets. There
is a known bug that when the camera is constantly moving (i.e. you
click on a ship) the world-coords need constantly updating but they
aren't until next time you move the mouse.

The behaviour which says "camera follows the selected ship if there is
one and stands still if not" requires 'feedback' from one phase to the
next. This would be a classic use of a recursive snapshot, but since I
can't get that working I implemented a non-recursive "switcherFold".

The implementation of Reactive is not conal's, but my own. It takes a
very different approach at the low level: eschewing the notion of a
'blocking pure value' which makes me slightly uncomfortable, I
explicitly mark possibly blocking stuff with IO, giving an explicitly
IO implementation of Future. However, this isn't exposed at the user
level: the user-level combinators follow conal's very closely, with
just a few differences here and there where I didn't see something and
came up with my own alternative.

My main motivation for writing my own implementation was learning, but
now I've done so it's quite interesting to examine the different design
choices.

I had quite a few space leaks to track down, which I did with GHC's
heap profiling. Mostly I found -hT (which doesn't even need profiling
compilation) and -hc useful, but try all of them. One space leak I
couldn't fix properly and had to hack was in shipclicks; in the end I
have added in an artificial ticker to properly progress, more of which
in another email perhaps.

Another spaceleak, in shipclicks'' required "cojoinB", which provides
pre-aged behaviours to use (via snapshot or <*>) in closures; naive
use of a Behaviour in a closure holds onto the head of the Behaviour
forever.

There are still some minor space leaks, but they are very minor in
comparison to the big ones I fixed. I will track them down in due
course. It might be only the "history" leak which is commented.

Oh, I should say the code is really ugly. Sorry about that.

One of the bits of code I have finally uploaded as a result of this is
'FunctionalTexture' which is a setup for two dimensional procedurally
rendered textures in the style of POVray - turbulence, marbles,
layering, that kind of thing. I just use it to make the planets look
slightly more interesting but it's capable of much more.


Jules


More information about the Reactive mailing list