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


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to