
Hey, When writing games in other (imperative) languages, I like to separate the game logic from the rendering. For this I use something similar to the observer pattern. With rendering I mean anything only related to how objects are drawn to the screen. Animation state for example. On my journey of exploring game programming with haskell (and FRP), I wonder what a good way of archiving something similar would be. If the rendering has no internal state, one can just write a function draw :: GameLogicState -> IO () But when the rendering of an object has an internal state (e.g. animation frame) than this is not possible. Now I could write a Wire/Signal (whatever FRP implementation I use) that translates to a RenderingState: render :: Signal GameLogicState RenderingState draw :: RenderingState -> IO () which is fine, except when my game is made of many objects. Than I need to associate the state of one object in GameLogicState with a sub-signal in render. That could be done by giving every object an ID and letting GameLogicState contain a map from IDs to ObjectLogicState. I fear that when I really have a lot of objects, assembling and decomposing the map could become a major bottleneck. So I am wondering: Is there (or can someone think of) a different pattern by which this could be archived? Or asked different: How would you do it? Thanks! Nathan

Not sure, but maybe you can define a Drawable class with a method in converting inner state to something draw func could use, so it would be like this: draw :: Drawable a => a -> IO () вторник, 27 ноября 2012 г. пользователь Nathan Hüsken писал:
Hey,
When writing games in other (imperative) languages, I like to separate the game logic from the rendering. For this I use something similar to the observer pattern.
With rendering I mean anything only related to how objects are drawn to the screen. Animation state for example.
On my journey of exploring game programming with haskell (and FRP), I wonder what a good way of archiving something similar would be.
If the rendering has no internal state, one can just write a function
draw :: GameLogicState -> IO ()
But when the rendering of an object has an internal state (e.g. animation frame) than this is not possible.
Now I could write a Wire/Signal (whatever FRP implementation I use) that translates to a RenderingState:
render :: Signal GameLogicState RenderingState draw :: RenderingState -> IO ()
which is fine, except when my game is made of many objects. Than I need to associate the state of one object in GameLogicState with a sub-signal in render. That could be done by giving every object an ID and letting GameLogicState contain a map from IDs to ObjectLogicState.
I fear that when I really have a lot of objects, assembling and decomposing the map could become a major bottleneck.
So I am wondering: Is there (or can someone think of) a different pattern by which this could be archived? Or asked different: How would you do it?
Thanks! Nathan
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org javascript:; http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Best Timur DeTeam Amirov Moscow, Russia

Nathan Hüsken
When writing games in other (imperative) languages, I like to separate the game logic from the rendering. For this I use something similar to the observer pattern.
[...]
So I am wondering: Is there (or can someone think of) a different pattern by which this could be archived? Or asked different: How would you do it?
That really depends on the FRP framework you are using. A framework can be as simple as to model only the behaviors and events like the original Fran, in which case often a design pattern such as the observer pattern is not even available. One way out of this dilemma is that the main behavior actually gives enough information to draw the scene. In more versatile frameworks, which includes basically any modern framework like Elerea, Netwire and reactive-banana, typically you would model your entire application including the rendering as part of the main behavior. In Netwire you can go as far as having something like this: myApp :: WireM IO a () However, I do not recommend this. As far as possible you should use a stateless monad, ideally simply Identity or a reader: type MyWire = WireM ((->) AppConfig) myApp :: MyWire a GameFrame This is only the first part of the story. The second part is the rendering itself. You certainly want a way to make use of various OpenGL extensions like vertex buffers, which are inherently stateful. One sensible way I see is not to output the game's state, but rather a state delta: myApp :: MyWire a GameDelta That way you can do the imperative stateful plumbing outside of the application's wire and get the full power of FRP without giving up efficient rendering. GameDelta itself would essentially be a type for game state commands. In fact it could be a (free) monad: myApp :: MyWire a (GameDelta ()) someDelta :: GameDelta () someDelta = do randomPos <- liftA2 (,) getRandom getRandom replicateM_ 4 (addCreature randomPos) getPlayerPos >>= centerCamOver Then you could perform that monadic action as part of the rendering process. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.

On 11/27/2012 07:12 AM, Ertugrul Söylemez wrote:
Nathan Hüsken
wrote: When writing games in other (imperative) languages, I like to separate the game logic from the rendering. For this I use something similar to the observer pattern.
[...]
So I am wondering: Is there (or can someone think of) a different pattern by which this could be archived? Or asked different: How would you do it?
[...] As far as possible you should use a stateless monad, ideally simply Identity or a reader:
type MyWire = WireM ((->) AppConfig)
myApp :: MyWire a GameFrame
This is only the first part of the story. The second part is the rendering itself. You certainly want a way to make use of various OpenGL extensions like vertex buffers, which are inherently stateful. One sensible way I see is not to output the game's state, but rather a state delta:
myApp :: MyWire a GameDelta
That way you can do the imperative stateful plumbing outside of the application's wire and get the full power of FRP without giving up efficient rendering. GameDelta itself would essentially be a type for game state commands. In fact it could be a (free) monad:
myApp :: MyWire a (GameDelta ())
someDelta :: GameDelta () someDelta = do randomPos <- liftA2 (,) getRandom getRandom replicateM_ 4 (addCreature randomPos) getPlayerPos >>= centerCamOver
Then you could perform that monadic action as part of the rendering process.
That sound like a good Idea. But I still have the problem of connection "game logic" objects with "rendering" objects, or am I missing something? Implementing "addCreature" is fine, but when I want a "removeCreature", it has to remove the correct creature from a potentially very large list/set of creatures. How can I efficiently build this connections (which corresponds to a pointer in other languages, I guess)? Thanks! Nathan

Nathan Hüsken
In fact it could be a (free) monad:
myApp :: MyWire a (GameDelta ())
someDelta :: GameDelta () someDelta = do randomPos <- liftA2 (,) getRandom getRandom replicateM_ 4 (addCreature randomPos) getPlayerPos >>= centerCamOver
Then you could perform that monadic action as part of the rendering process.
That sound like a good Idea. But I still have the problem of connection "game logic" objects with "rendering" objects, or am I missing something? Implementing "addCreature" is fine, but when I want a "removeCreature", it has to remove the correct creature from a potentially very large list/set of creatures. How can I efficiently build this connections (which corresponds to a pointer in other languages, I guess)?
That was a simplified example. In the real world it depends on what generates your creatures. If they can be generated all over the code then you need some form of identifier generation. This can be done by the wire's underlying monad: type Identifier = Int type Game = WireM (StateT Identifier ((->) AppConfig)) A creature then may look something like this: creature :: Game World (Creature, GameDelta ()) The wire produces a creating action at the first instant, then switches to the creature's regular wire. The various GameDelta actions form at least a monoid under (>>), and depending on your design even a group: rec (creature1, gd1) <- creature -< w (creature2, gd2) <- creature -< w (creature3, gd3) <- creature -< w w <- delay (World []) -< World [c1, c2, c3] id -< (gd1 >> gd2 >> gd3) That's the basic idea. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.

Nathan Hüsken wrote:
Hey,
When writing games in other (imperative) languages, I like to separate the game logic from the rendering. For this I use something similar to the observer pattern.
With rendering I mean anything only related to how objects are drawn to the screen. Animation state for example.
On my journey of exploring game programming with haskell (and FRP), I wonder what a good way of archiving something similar would be.
[..]
So I am wondering: Is there (or can someone think of) a different pattern by which this could be archived? Or asked different: How would you do it?
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. How to describe picture that moves? Your large picture is probably made from smaller pictures, for instance a small picture in the shape of something we often call a "spaceship". So, you can implement a game by describing the evolution of smaller pictures, and then combine these into the description of a larger picture. Now, the smaller pictures tend to have "hidden state", which means that their future evolution depends a lot on the past evolution of the other small pictures. In my experience with programming in FRP, it is very useful to describe the individual pictures in terms of tiny state machines and then connect these state machines via appropriate events and behaviors to each other. The essence here is to decouple the individual state machines from each other as much as possible and only then to use the FRP abstractions to connect and combine them into a "large emergent state machine". (However, it is important to keep in mind that the fundamental abstraction is not a state machine, but a time evolution that remembers the past. This helps with embracing the new perspective and not accidentally fall back to previous ways of thinking. Whether that ends up with good code is up to you to find out, but if you decide to apply a new perspective, it's best to do it in an extremist way to gain the maximum benefit -- this benefit might certainly turn out to be zero, but you will never find out if you wet your feet only a little bit.) Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

On 11/27/2012 04:18 PM, Heinrich Apfelmus wrote:
Nathan Hüsken wrote:
Hey,
When writing games in other (imperative) languages, I like to separate the game logic from the rendering. For this I use something similar to the observer pattern.
With rendering I mean anything only related to how objects are drawn to the screen. Animation state for example.
On my journey of exploring game programming with haskell (and FRP), I wonder what a good way of archiving something similar would be.
[..]
So I am wondering: Is there (or can someone think of) a different pattern by which this could be archived? Or asked different: How would you do it?
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.
How to describe picture that moves? Your large picture is probably made from smaller pictures, for instance a small picture in the shape of something we often call a "spaceship". So, you can implement a game by describing the evolution of smaller pictures, and then combine these into the description of a larger picture.
Now, the smaller pictures tend to have "hidden state", which means that their future evolution depends a lot on the past evolution of the other small pictures. In my experience with programming in FRP, it is very useful to describe the individual pictures in terms of tiny state machines and then connect these state machines via appropriate events and behaviors to each other. The essence here is to decouple the individual state machines from each other as much as possible and only then to use the FRP abstractions to connect and combine them into a "large emergent state machine".
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? 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.
(However, it is important to keep in mind that the fundamental abstraction is not a state machine, but a time evolution that remembers the past. This helps with embracing the new perspective and not accidentally fall back to previous ways of thinking. Whether that ends up with good code is up to you to find out, but if you decide to apply a new perspective, it's best to do it in an extremist way to gain the maximum benefit -- this benefit might certainly turn out to be zero, but you will never find out if you wet your feet only a little bit.)
That certainly makes sense, and it is also very difficult for me to stick to the "FRP perspective". But I do not see that seperating rendering and game logic code goes against the FRP perspective. Best Regards, Nathan [1] https://github.com/bernstein/breakout/blob/master/src/Main.hs

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

Sorry for the late reply, I somehow missed this eMail ... On 11/29/2012 06:28 PM, Heinrich Apfelmus wrote:
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.
Yes, but these examples are extremely simple. The animation has no internal "state". What if every Asteroid also has a animation state (which I would want to add a posteriori) and can be destroyed. Than the connection between the asteroids "game logic" value, and "rendering" value needs some kind of bookkeeping to be maintained.
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.
Thank you for your input! Regards, Nathan

Nathan Hüsken wrote:
Heinrich Apfelmus wrote:
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.
Yes, but these examples are extremely simple. The animation has no internal "state". What if every Asteroid also has a animation state (which I would want to add a posteriori) and can be destroyed. Than the connection between the asteroids "game logic" value, and "rendering" value needs some kind of bookkeeping to be maintained.
Fair enough, but I don't see how this can be fitted into a general pattern. If the animation "state" is coupled tightly to the game logic "state", then the question whether the animation is part of the game logic or not does not have a clear answer anymore. Hm. You mentioned that in an imperative setting, you would use something similar to the observer pattern. Judging from the wikipedia page http://en.wikipedia.org/wiki/Observer_pattern, it seems to me that this is just the Event type, though, so I don't understand how this helps with the problem at hand. Maybe discussing a concrete example could be very helpful. Could you give a minimal example that still contains the key difficulties? Maybe a collection of asteroids that float in space, can be added or removed with a button click and who are animated as rotating rocks, all starting in a certain position when they are created? How would you use the observer pattern in this case? Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

On 12/08/2012 10:32 AM, Heinrich Apfelmus wrote:
Nathan Hüsken wrote:
Heinrich Apfelmus wrote:
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.
Yes, but these examples are extremely simple. The animation has no internal "state". What if every Asteroid also has a animation state (which I would want to add a posteriori) and can be destroyed. Than the connection between the asteroids "game logic" value, and "rendering" value needs some kind of bookkeeping to be maintained.
Fair enough, but I don't see how this can be fitted into a general pattern. If the animation "state" is coupled tightly to the game logic "state", then the question whether the animation is part of the game logic or not does not have a clear answer anymore. Hm.
I see it like this: The "logic state" may not depend on the "rendering state". If for example the animation of an asteroid changes how or when objects collide with it, than the animation is part of the logic. If however the physics of the game treat the asteroid as a object whose shape does not change depending in the animation, than the animation is part of the "rendering state". So the coupling may only be logic->rendering.
You mentioned that in an imperative setting, you would use something similar to the observer pattern. Judging from the wikipedia page http://en.wikipedia.org/wiki/Observer_pattern, it seems to me that this is just the Event type, though, so I don't understand how this helps with the problem at hand.
Yes, you are right. The problem at hand is something one has to deal with when using the observer pattern. Only in C++ I do not find it hard to do.
Maybe discussing a concrete example could be very helpful. Could you give a minimal example that still contains the key difficulties? Maybe a collection of asteroids that float in space, can be added or removed with a button click and who are animated as rotating rocks, all starting in a certain position when they are created? How would you use the observer pattern in this case?
I put a pseudo C++ example below the mail. I use the terms "model" and "view" for the game logic and rendering respectively. The example is a little different. Asteroids explode when they collide. The moment asteroids explode, they are removed from the model (the game logic) while in the view (rendering) they still exist until the explosion animation is over. As you said, this basically is sending messages from the Model (in the observer pattern called Observable) to the view (Observer). The main difficulty I have is how to send the messages from the correct model to the correct view. In C++ this is done by keeping pointers. Simply assigning IDs would work, but than I would have to always pass a map from the model to the view, and I feel like (also I have little experience with this), that this approach is not very scalable. Best Regards, Nathan =========== The C++ example, its not complete, but I believe it captures the idea. class GalaxyModel { GalaxyView* view; list<AsteroidModel> asteroids; void addAsteroid(Position pos) { asteroids.push(AsteroidModel(pos)); view->onNewAsteroid(asteroids.back()); } void update() { for (a in asteroids) { a.update(); } for(a in asteroids) { for (b in asteroids) { if (collide(a,b)) { a.explode(); b.explode(); asteroids.remove(a); asteroids.remove(b); } } } } }; class AsteroidModel { AsteroidView* view; Position pos; update() { updatePosition(); view->onNewPos(pos); } explode() { view->onExplode(); } }; class GalaxyView { list<AstroidView> asteroids; void onNewAsteroid(AsteroidModel* model) { asteroids.push(AsteroidView(model)); } void update() { for (a in asteroids) { a.update(); if (a.dead) asteroids.remove(a); } } } class AsteroidView { float rotation; bool dead = false; void onExplode() { setExplodeAnimation(); } void onNewPos() { //Store position} void update() { rotation += 1.0; if (explodeAnimationOver()) { m_dead = true; } } }

Nathan Hüsken
I put a pseudo C++ example below the mail. I use the terms "model" and "view" for the game logic and rendering respectively. The example is a little different. Asteroids explode when they collide. The moment asteroids explode, they are removed from the model (the game logic) while in the view (rendering) they still exist until the explosion animation is over.
As you said, this basically is sending messages from the Model (in the observer pattern called Observable) to the view (Observer). The main difficulty I have is how to send the messages from the correct model to the correct view. In C++ this is done by keeping pointers. Simply assigning IDs would work, but than I would have to always pass a map from the model to the view, and I feel like (also I have little experience with this), that this approach is not very scalable.
Actually it is very scalable, as the same map is passed to every object. It can even live in the underlying monad, which means that you could even use a mutable vector, if you wish; however, I don't recommend that. Remember that a map is immutable and shared, so passing the same map to multiple objects is in fact the same as passing a pointer in C++. Lookups in and updates to the map are of logarithmic complexity, so this scales well. Only doubling the number of nodes actually adds one full step to lookups and updates. If you're dealing with millions of objects you may want to use the vector solution mentioned earlier. This requires an imperative underlying monad, but you would get about the same speed as in C++. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.

Am 10.12.2012 16:56, schrieb Ertugrul Söylemez:
Nathan Hüsken
wrote: I put a pseudo C++ example below the mail. I use the terms "model" and "view" for the game logic and rendering respectively. The example is a little different. Asteroids explode when they collide. The moment asteroids explode, they are removed from the model (the game logic) while in the view (rendering) they still exist until the explosion animation is over.
As you said, this basically is sending messages from the Model (in the observer pattern called Observable) to the view (Observer). The main difficulty I have is how to send the messages from the correct model to the correct view. In C++ this is done by keeping pointers. Simply assigning IDs would work, but than I would have to always pass a map from the model to the view, and I feel like (also I have little experience with this), that this approach is not very scalable. Actually it is very scalable, as the same map is passed to every object. It can even live in the underlying monad, which means that you could even use a mutable vector, if you wish; however, I don't recommend that.
Remember that a map is immutable and shared, so passing the same map to multiple objects is in fact the same as passing a pointer in C++. Lookups in and updates to the map are of logarithmic complexity, so this scales well. Only doubling the number of nodes actually adds one full step to lookups and updates.
If you're dealing with millions of objects you may want to use the vector solution mentioned earlier. This requires an imperative underlying monad, but you would get about the same speed as in C++.
I might just not be used enough to functional data structures, "Purely functional data structures" is on my reading list :). I was thinking, in the asteroids example the only reason why the view needs more input than the models output, is that it needs to be informed of creation and destruction of asteroids. So, in the model one could habe a signal asteroidsModel :: Signal Input [Just AsteroidModel] which outputs "Nothing" for asteroids that have been destroyed. Then, in the view this would be taken for as input for asteroidsView :: Signal [Just AsteroidModel] [Picture] asteroidsView would have to do the following: * route the input list to a list of "asteroidView" signals. * When there is a "Nothing" in the input list, the corresponding (now exploding) view is moved to a list of "zombie asteroids" where it remains until its explosion animation is over. * When the input list is longer than the list of current astroidView signals, the list is extended. This would avoid the need for bookkeeping ids. Regards, Nathan

Nathan Hüsken
Actually it is very scalable, as the same map is passed to every object. It can even live in the underlying monad, which means that you could even use a mutable vector, if you wish; however, I don't recommend that.
Remember that a map is immutable and shared, so passing the same map to multiple objects is in fact the same as passing a pointer in C++. Lookups in and updates to the map are of logarithmic complexity, so this scales well. Only doubling the number of nodes actually adds one full step to lookups and updates.
If you're dealing with millions of objects you may want to use the vector solution mentioned earlier. This requires an imperative underlying monad, but you would get about the same speed as in C++.
I might just not be used enough to functional data structures, "Purely functional data structures" is on my reading list :).
I was thinking, in the asteroids example the only reason why the view needs more input than the models output, is that it needs to be informed of creation and destruction of asteroids.
Why would the view need to be informed?
So, in the model one could habe a signal
asteroidsModel :: Signal Input [Just AsteroidModel]
which outputs "Nothing" for asteroids that have been destroyed. Then, in the view this would be taken for as input for
asteroidsView :: Signal [Just AsteroidModel] [Picture]
asteroidsView would have to do the following: * route the input list to a list of "asteroidView" signals. * When there is a "Nothing" in the input list, the corresponding (now exploding) view is moved to a list of "zombie asteroids" where it remains until its explosion animation is over. * When the input list is longer than the list of current astroidView signals, the list is extended.
This would avoid the need for bookkeeping ids.
This is a very complicated way to do it. I would simply regard the "zombie asteroids" as regular objects. That way you don't need a special case in the view. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.

On 12/12/2012 01:26 AM, Ertugrul Söylemez wrote:
Nathan Hüsken
wrote: Actually it is very scalable, as the same map is passed to every object. It can even live in the underlying monad, which means that you could even use a mutable vector, if you wish; however, I don't recommend that.
Remember that a map is immutable and shared, so passing the same map to multiple objects is in fact the same as passing a pointer in C++. Lookups in and updates to the map are of logarithmic complexity, so this scales well. Only doubling the number of nodes actually adds one full step to lookups and updates.
If you're dealing with millions of objects you may want to use the vector solution mentioned earlier. This requires an imperative underlying monad, but you would get about the same speed as in C++.
I might just not be used enough to functional data structures, "Purely functional data structures" is on my reading list :).
I was thinking, in the asteroids example the only reason why the view needs more input than the models output, is that it needs to be informed of creation and destruction of asteroids.
Why would the view need to be informed?
So that the coresponding view objects can be removed (imidiatly or at some later point).
So, in the model one could habe a signal
asteroidsModel :: Signal Input [Just AsteroidModel]
which outputs "Nothing" for asteroids that have been destroyed. Then, in the view this would be taken for as input for
asteroidsView :: Signal [Just AsteroidModel] [Picture]
asteroidsView would have to do the following: * route the input list to a list of "asteroidView" signals. * When there is a "Nothing" in the input list, the corresponding (now exploding) view is moved to a list of "zombie asteroids" where it remains until its explosion animation is over. * When the input list is longer than the list of current astroidView signals, the list is extended.
This would avoid the need for bookkeeping ids.
This is a very complicated way to do it. I would simply regard the "zombie asteroids" as regular objects. That way you don't need a special case in the view.
I was thinking by doing it this way I could completely avoid the need for ids by this the bookkeeping of ids. On the other hand, I might need the ids anyway for other things and than my approach would just add complexity, as you said. Regards, Nathan

Nathan Hüsken wrote:
On 12/08/2012 10:32 AM, Heinrich Apfelmus wrote:
Fair enough, but I don't see how this can be fitted into a general pattern. If the animation "state" is coupled tightly to the game logic "state", then the question whether the animation is part of the game logic or not does not have a clear answer anymore. Hm.
I see it like this: The "logic state" may not depend on the "rendering state". If for example the animation of an asteroid changes how or when objects collide with it, than the animation is part of the logic. If however the physics of the game treat the asteroid as a object whose shape does not change depending in the animation, than the animation is part of the "rendering state". So the coupling may only be logic->rendering.
Maybe discussing a concrete example could be very helpful. Could you give a minimal example that still contains the key difficulties?
I put a pseudo C++ example below the mail. I use the terms "model" and "view" for the game logic and rendering respectively. The example is a little different. Asteroids explode when they collide. The moment asteroids explode, they are removed from the model (the game logic) while in the view (rendering) they still exist until the explosion animation is over.
(Sorry for the late reply.) I see, that's a nice example. Indeed, if you try to model this situation with dynamic collections galaxyModel :: Behavior [AsteroidModel] galaxyView :: Behavior [AsteroidView] then you have to keep track of IDs in some way, because a change in the collection of asteroid models needs to be reflected in a corresponding change in the collection of asteroid views. identifier :: AsteroidModel -> ID eCollisions :: Event [ID] eCollisions = collisions <$> galaxyModel <@ eTick where collisions asteroids = [identifier a | a <- asteroids, b <- asteroids, a `collides` b] galaxyModel = accumB initialAsteroidModels $ removeFromList <$> eCollisions galaxyView = accumB initialAsteroidViews $ startExplosions <$> eCollisions That said, do note that any significant use of pointers in an imperative program translates to the use of identifiers in the purely functional variant. This is very much *independent* of FRP! In other words, if you find that giving certain game objects an "identity" is a good way to structure your code, then you need to use identifiers, regardless of whether you use FRP or not. Of course, as you note in another message, there are other ways to structure this code. For instance, the second idea would be to use a data type type Asteroid = (Maybe AsteroidModel, AsteroidView) which represents live asteroids as (Just positionEtc, view) and dead asteroids as (Nothing, explosionView) . Then again, one unsatisfactory point about this approach is that an exploding asteroid is now represented explicitly in the game logic as a Nothing value. A third approach would be to keep an explicit list of explosions. data AsteroidModel = AsteroidModel { view :: AsteroidView, pos :: Position } data AsteroidView = AsteroidView { rotation :: Angle } data Explosion = Explosion { posExp :: Position } galaxyView :: Behavior ([AsteroidView], [Explosion]) galaxyView = (,) <$> (map view <$> galaxyModel) <$> explosions explosions = accumB [] $ startExplosions <$> eCollisions You do need an event to communicate which asteroids have exploded, but an exploding asteroid will not appear in galaxyModel anymore. Instead, it will be added as an "anonymous" explosion to the rendering logic. (In a sense, the asteroid views with the state variables dead = false and dead = true have been split into different types.) I find the third approach to be quite satisfactory. What is your opinion? The more I think about this example, the more I think that the underlying difficulty is not FRP, but the use of pointers / identities. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

On 12/18/2012 10:52 PM, Heinrich Apfelmus wrote:
Nathan Hüsken wrote:
On 12/08/2012 10:32 AM, Heinrich Apfelmus wrote:
Fair enough, but I don't see how this can be fitted into a general pattern. If the animation "state" is coupled tightly to the game logic "state", then the question whether the animation is part of the game logic or not does not have a clear answer anymore. Hm.
I see it like this: The "logic state" may not depend on the "rendering state". If for example the animation of an asteroid changes how or when objects collide with it, than the animation is part of the logic. If however the physics of the game treat the asteroid as a object whose shape does not change depending in the animation, than the animation is part of the "rendering state". So the coupling may only be logic->rendering.
Maybe discussing a concrete example could be very helpful. Could you give a minimal example that still contains the key difficulties?
I put a pseudo C++ example below the mail. I use the terms "model" and "view" for the game logic and rendering respectively. The example is a little different. Asteroids explode when they collide. The moment asteroids explode, they are removed from the model (the game logic) while in the view (rendering) they still exist until the explosion animation is over.
(Sorry for the late reply.)
I see, that's a nice example.
Indeed, if you try to model this situation with dynamic collections
galaxyModel :: Behavior [AsteroidModel] galaxyView :: Behavior [AsteroidView]
then you have to keep track of IDs in some way, because a change in the collection of asteroid models needs to be reflected in a corresponding change in the collection of asteroid views.
identifier :: AsteroidModel -> ID
eCollisions :: Event [ID] eCollisions = collisions <$> galaxyModel <@ eTick where collisions asteroids = [identifier a | a <- asteroids, b <- asteroids, a `collides` b]
galaxyModel = accumB initialAsteroidModels $ removeFromList <$> eCollisions
galaxyView = accumB initialAsteroidViews $ startExplosions <$> eCollisions
That said, do note that any significant use of pointers in an imperative program translates to the use of identifiers in the purely functional variant. This is very much *independent* of FRP! In other words, if you find that giving certain game objects an "identity" is a good way to structure your code, then you need to use identifiers, regardless of whether you use FRP or not.
Well, direct translation of imperative structures are probably often not a smart way to go. Instead a functional approach with the same benefits is more desirable. I just find it very hard to think in new directions for a problem I already know a solution in an imperative style :).
Of course, as you note in another message, there are other ways to structure this code. For instance, the second idea would be to use a data type
type Asteroid = (Maybe AsteroidModel, AsteroidView)
which represents live asteroids as (Just positionEtc, view) and dead asteroids as (Nothing, explosionView) . Then again, one unsatisfactory point about this approach is that an exploding asteroid is now represented explicitly in the game logic as a Nothing value.
A third approach would be to keep an explicit list of explosions.
data AsteroidModel = AsteroidModel { view :: AsteroidView, pos :: Position } data AsteroidView = AsteroidView { rotation :: Angle } data Explosion = Explosion { posExp :: Position }
galaxyView :: Behavior ([AsteroidView], [Explosion]) galaxyView = (,) <$> (map view <$> galaxyModel) <$> explosions
explosions = accumB [] $ startExplosions <$> eCollisions
You do need an event to communicate which asteroids have exploded, but an exploding asteroid will not appear in galaxyModel anymore. Instead, it will be added as an "anonymous" explosion to the rendering logic. (In a sense, the asteroid views with the state variables dead = false and dead = true have been split into different types.)
I find the third approach to be quite satisfactory. What is your opinion?
I agree, I like it!
The more I think about this example, the more I think that the underlying difficulty is not FRP, but the use of pointers / identities. I think the original question where I was asking for replacement pattern for observers in FRP is the wrong way to go. The goal was to separate game logic and rendering logic, and the solutions you mention provide this. Other Problems that are solved with the Observer Pattern probably should have a completely different approach in function programming or FRP.
I am very happy with all he replies I got in this thread and I will see where it gets me. Thanks! Nathan

hey all, i've been lurking in this thread for a bit & i just found this interesting article from chris granger (yeah, the light table guy). he just completed the node knockout they had recently & decided to make a game. he did it all in clojurescript & he discusses some aspects of programming a game in a functional language. so maybe this will give you some ideas on how to write games in haskell. anyway, linkage: http://www.chris-granger.com/2012/12/11/anatomy-of-a-knockout/ serialhex -- * If God had a beard, he'd be a UNIX programmer. * Some people pray for more than they are willing to work for. * This is Linux. Distro is a proper subset of Settings. --TwilightXaos on slashdot --- CFO: “What happens if we train people and they leave?” CTO: “What if we don’t and they stay?”
participants (5)
-
Ertugrul Söylemez
-
Heinrich Apfelmus
-
Nathan Hüsken
-
serialhex
-
Тимур Амиров