Stars - a simple reactive simulation with an alternative Reactive implementation

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

Jules Bean wrote:
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 Stars are nice, but very complex. As I am new to haskell (and reactive), I found that myreactive.hs was just what I needed for playing with reactive - a single working piece of program, that I can slowly modify. Many thanks for that.
Martin
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 _______________________________________________ Reactive mailing list Reactive@haskell.org http://www.haskell.org/mailman/listinfo/reactive
participants (2)
-
Jules Bean
-
Trin