[Haskell-cafe] Animated line art
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
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