[reactive] A pong and integrate

Limestraël limestrael at gmail.com
Sat May 15 07:19:10 EDT 2010


Hello,

As a newbie with reactive, I'm trying to make a simple example, namely a
pong.
But I'm stuck with the paddle animation. Here is a how I proceed :
A paddle:
data Paddle = Paddle {
    paddleCol :: Double,
    paddleCenter :: Behavior Double }

The paddle moves along a column, so only it's Y coordinate changes.
paddleCenter is the Y coordinate of its center.

This is how I create a paddle:
data Direction = PaddleUp | PaddleDown | PaddleStill
  deriving (Eq, Show)

newPaddle :: Behavior Direction -> Double -> Paddle
newPaddle direction column =
  let
      position = fmap ((initY ^+^)) $ integral *beat* $
                   fmap ((speed *) . factor) direction
      factor PaddleUp   = -1
      factor PaddleDown = 1
      factor _          = 0
      speed = 50  -- pixels per second
      initY = 400    -- suppose we have a 800x600 window: paddle is right at
the middle
      *beat = atTimes [0, 0.01..]*
  in Paddle column position

Basically, a paddle is driven by a behavior which tells him to go up, down
or to stand still.
My problem is with the tuning of the beat, a ticker event which is used for
the integration.
How do I have to think ?
- My speed is in pixels/second, so it has to tick every second? (atTime [0,
1..])
- My app will run at 60fps, so it has to tick 60 times per second? (atTime
[0, 1/60..])

The main program (I'm not using any graphics library, just getting keys ('u'
for up, 'd' for down) and displaying the current paddle pos)

makeKeyboardEvent = do
  hSetBuffering stdin NoBuffering
  hSetBuffering stdout NoBuffering
  (buttonPressedSink, event) <- makeEvent =<< makeClock
  forkIO . forever $
    getChar >>= buttonPressedSink
  return event

main = do
  keyEvt <- makeKeyboardEvent
  let
      dirEvt = fmap key2dir keyEvt
      paddle = newPaddle (stepper PaddleStill dirEvt) 50
  adaptE $ fmap print $ snapshot_ (paddleCenter paddle) $ atTimes [0,
0.01..]

key2dir k = maybe PaddleStill snd $
              find (($ k) . fst) [((== 'u'), PaddleUp),
                                  ((== 'd'), PaddleDown)]

When I launch the program, I hit 'u' or 'd' and I see the position
increase/decrease.
If the beat ticks every second, I see the position being increased by 50
every second, which is normal, but it's a too low refresh rate for an app
that is to run at 60fps.
But when I set my beat to tick every 60 times per second, the position is
well updated, but I clearly see that the display dramatically slows down
after a few seconds of execution. Too heavy rate for integrate?

That's why I'm asking: how should I use integrate?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/reactive/attachments/20100515/7f146ae5/attachment.html


More information about the Reactive mailing list