How to implement a game loop in reactive-banana?

﹥>﹥吖頭↗ 提交于 2019-11-29 21:01:39

For this discussion, the part I'm most interested in is arranging so that the call to the physics engine (the call to integrate) is always stepped by dt. Does reactive-banana allow the user to write this style loop?

Yes, reactive-banana can do that.

The idea is that you write a custom event loop and hook reactive-banana into that. The library doesn't make any assumptions as to where you get your events from, it "only" solves the problem of neatly describing new events in terms of existing ones. In particular, you can use the newAddHandler function to create two callback functions that are called in the appropriate places in the event loop. Essentially, reactive-banana is just a mind-boggling method to write ordinary callback functions that maintain state. When and how you call these functions is up to you.

Here a general outline:

-- set up callback functions
(renderEvent, render) <- newAddHandler
(stateUpdateEvent, stateUpdate) <- newAddHandler

-- make the callback functions do something interesting
let networkDescription = do
    eRender      <- fromAddHandler renderEvent
    eStateUpdate <- fromAddHandler stateUpdateEvent
    ...
    -- functionality here

actuate =<< compile networkDescription

-- event loop
while (! quit)
{
    ...
    while (accumulator >= dt)
    {
        stateUpdate (t,dt)      -- call one callback
        t += dt
        accumulator -= dt
    }
    ...
    render ()                   -- call another callback
}

In fact, I have written a game loop example in this style for an older version of reactive-banana, but haven't gotten around to polishing and publishing it on hackage. The important things that I would like to see completed are:

  • Pick a graphics engine that is easy to install and works in GHCi. The concept uses SDL, but this is really quite awkward as it cannot be used from GHCi. Something like OpenGL + GLFW would be nice.
  • Offer a small abstraction to make it easier to write the interpolation phase. Probably just two things: an event eTimer :: Event t () that represents the regular physics updates and a behavior bSinceLastTimer :: Behavior t TimeDiff that measures the time since the last physics updates, which can be used for doing the interpolation. (It's a behavior instead of an event, so the internal "draw this!" updates are transparent.)

Andreas Bernstein's blackout clone using reactive-banana may be an excellent example to implement in this style.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!