[Haskell-cafe] Animated line art

Andrew Coppin andrewcoppin at btinternet.com
Fri Dec 5 15:01:43 EST 2008


Today I sat down and had a think about this problem. After reading about 
various FRP systems (Yampa et al) I had a few ideas in my head.

The main idea is that I want to be able to draw lines and curves and so 
forth, and I want to add them to and remove them from the display at 
various times, and move them around, change their colour and opacity, 
etc. I also want to be able to run one piece of animation, and then 
another, and then another. So I want some sort of sequencing primitives.

I had a go at writing what I thought the interface might look like. 
(Fortunately, I made no attempt to *implement* it - otherwise I would 
doubtless have wasted huge amounts of time implementing something that 
isn't designed right yet!) Unfortunately Haskell doesn't really provide 
a way to write an "interface", and then write the implementation behind 
it seperately somewhere else. So the "code" I wrote wasn't actually 
compilable at all, but it was useful to sketch something out.

My initial idea was that I could have some kind of monad for controlling 
adding and removing stuff. The monad could provide an "add" action that 
adds a visual object to the frame and returns a unique ID. Then you 
could have a "remove" action that removes the specified ID again. And a 
"wait" action that makes the display stay the same for so many seconds. 
(But the visual objects may internally be animated.)

Then I hit upon the idea that maybe one thread of control could "spawn" 
a second one - so that for example one thread could generate a bunch of 
snowflakes raining down the screen while a seperate thread rotates a 
geometric figure in the center. Or something. Of course, these "threads" 
have no need (or use) for actually running concurrently - they are only 
"concurrent" in the sence that they both affect the same frame, rather 
than their actions happening one after another on consecutive frames.

Next I got to thinking that maybe these threads of control might need to 
communicate for synchronisation. E.g., when a rotating line reaches 90° 
with another line, a signal is sent to another thread, which then adds 
another visual element or stops the animation or something. The parent 
thread *could* algebraicly _compute_ what time this will happen, but 
sending a signal is much simpler. (E.g., if you change the speed of an 
animation, the threads still stay synchronised without you having to 
remember to adjust parameters in your calculations all over the place...)

There's still one little problem though. The "threads of control" are 
for sequencing stuff. They are inherantly discrete; *add* this thing, 
*remove* this other thing, *send* this signal, *wait* to receive a 
signal, etc. But something like, say, rotating a line, is inherantly 
continuous. So there's a discrete system for sequencing stuff - which I 
seem to have worked out fairly well - and there also needs to be a 
continuous system for doing all the things with are smooth functions of 
time.

So maybe the continuous stuff should just be a type alias to a regular 
Haskell function? Ah, but wait... I said I might want to send a signal 
when an animation reaches a specific stage, right? So these "functions" 
need to do more than just map time to some other variable; they need to 
be able to send signals. And hey, actually, what are the chances of a 
time sample exactly lining up with the instant that the notable event 
occurs? How do I want to handle that?

...and at this point, it was time to go home! :-D



More information about the Haskell-Cafe mailing list