packages feed

Moe-0.1: FRP/MoeExample.hs

{-# LANGUAGE NoMonomorphismRestriction, Arrows #-}
import Control.Applicative
import Control.Arrow
import Data.Monoid
import FRP.MoePure
import FRP.MoeGLUT
import Graphics.UI.GLUT

white = Color3 1 1 1 :: Color3 GLfloat

red = Color3 1 0 0

green = Color3 0 1 0

blue = Color3 0 0 1

-- Rate of acceleration.
g = 200

-- X position of the ground.
xGround = 200

-- A ball falling with gravity.
fallingBall (x0, v0) = proc () -> do v <- arr (+ v0) <<< integral -< g
                                     x <- arr (+ x0) <<< integral -< v
                                     returnA -< (x, v)

-- If the ball hits the ground, reverses the velocity to let it bounce.
hit (x, v) = (x, if x >= xGround && v > 0 then Event (x, -v) else NoEvent)

-- Example for the (dswitch) combinator.
bouncingBall xv0 = dswitch (fallingBall xv0 >>> arr hit) bouncingBall

-- Example for the (timedCycle) combinator.
coloredBouncingBall :: (Double, Double) -> SF () (Color3 GLfloat, Double)
coloredBouncingBall xv0 = timedCycle [(interval, green), (interval, red), (interval, blue)] &&&
                                     bouncingBall xv0 where
                                      interval = 0.5

-- Example for the (dkswitch) combinator.
bouncingBall2 xv0 = dkswitch (bouncingBall xv0 >>> arr (\x -> [x]))
                             (arr (\((), (x : _)) -> if x > xGround then Event () else NoEvent))
                             (\sfs _ -> mappend (bouncingBall2 xv0) sfs)

drawPoly ps = renderPrimitive Polygon $ mapM_ vertex ps 

drawBall :: GLdouble -> GLdouble -> GLdouble -> IO ()
drawBall r x0 y0 = mapM_ (\th -> drawPoly [Vertex2 x0 y0, 
                                           Vertex2 (x0 + r * cos th) (y0 + r * sin th),
                                           Vertex2 (x0 + r * cos (th + dth)) (y0 + r * sin (th + dth))]) 
                   $ [0,dth..2*pi] where dth = 0.1*pi
                   
              
output (x, (c, x'), xs) = do color white
                             drawBall 20 100 (300 - realToFrac x)
                             color c
                             drawBall 20 200 (300 - realToFrac x)
                             color white
                             mapM_ (\(i, x) -> drawBall 20 (300 + 20*i) (300 - realToFrac x)) (zip [0,1..] $ reverse xs)

example = liftA3 (,,) 
                 (bouncingBall (0, 0))
                 (coloredBouncingBall (0, 0))
                 (bouncingBall2 (0, 0))

main = start 20 (sfConst () >>> example) (0, (green, 0), [0]) output