
Nathan Hüsken wrote:
Heinrich Apfelmus wrote:
Personally, I would recommend is a complete change in perspective.
The main idea of FRP is that it is a method to describe the evolution of values in time. What is a game? It's just a picture that evolves in time. The user can exert influence on the evolution by clicking certain buttons on a mechanical device, but in the end, all he sees is a picture that moves. [..]
That perspective certainly make sense. But couldn't one also describe a game as a set of entities (spaceships) that react to the clicking of buttons?
Of course, generally speaking, you can describe it any way you like, FRP is just a perspective, not a dictatorial doctrine. But you probably mean that you want to describe spaceships within the FRP perspective, though independent of how they are displayed. That's a good point, which I missed. (The guideline of working backwards from the very final result has served me very well when developing in FRP style, though, hence my insistence on it.) In the FRP perspective, I would use a slightly different language, though. Namely, I would not say that spaceships are "entities that react to button clicks", but rather that they are "represented by time-varying positions that depend on past button clicks". The change is subtle but important: you invert the direction of control. Instead of having a button click do something to the spaceship ("push"), you have a spaceship whose present position depends on past button clicks ("pull"). The FRP perspective is also more "holistic": you can think of a spaceship and other time-varying values as if you knew their values for all points in time, as if you were given graphical plots. (I have drawn a few pretty pictures in the slides linked to here http://apfelmus.nfshost.com/blog/2012/07/15-frp-tutorial-slides.html)
If I take for example the breakout game from here [1]. It outputs an object "scene" of type Picture. But this picture is calculated from the objects "ballPos" and "paddlePos". So first a game state (ballPos, paddlePos) is created and than transformed to something renderable.
I believe all examples I have seen for games with FRP follow this pattern, and I would I want to do is seperate the steps of calculating the game state and calculating the renderable from it.
In that light, the separation seems straightforward to me. Given the time-varying values that represent game objects, bSpaceShipPosition :: Behavior Position bAsteroidPositions :: Behavior [Position] bTime :: Behavior Time you can transform and combine them into a graphic, for instance like this bSpaceShipPicture :: Behavior Graphic bSpaceShipPicture = blinkenLights <$> bTime <*> bSpaceShipPosition bAsteroidPictures = map drawAsteroid <$> bAsteroidPositions bPicture = overlay <$> ((:) <$> bSpaceShipPicture <*> bAsteroidPictures) In other words, you just combine old time-varying values into new ones, much like you would combine combine graphical plots. Also note that you can add animation a posteriori; it doesn't have to be part of the values representing a space ship. Of course, one important question is whether to represent asteroid positions as a time-varying collection Behavior [Position] or as a collection of time-varying values [Behavior Position] . The latter form tends to require dynamic event switching, while the former form tends towards a monolithic GameState value, which would forgo many of the advantages of FRP. I don't have enough practical experience to give a useful recommendation here, but at the moment, I tend towards breaking it up as much as possible, but trying to avoid dynamic event switching. My rule of thumb is to model similar objects (asteroids) as a time-varying collection, while modeling distinct objects (player space ship) as individual behaviors. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com