Functional Banana Traveler - Timer and Player Independent Events

I am at the point of my Traveler. I am trying to handle player-independent updates to the game state. For reference, the project is here (the devel branch is relevant for this question).

Libraries/Universe/GameState.hs has an updateGS function that handles all player updates in game state. EventNetwork looks like this right now.

 makeNetworkDescription :: AddHandler PlayerCommand -> AddHandler () -> TChan GameState -> IO EventNetwork makeNetworkDescription addCommandEvent tickHandler gsChannel = compile $ do eInput <- fromAddHandler addCommandEvent eTick <- fromAddHandler tickHandler let bGameState = accumB initialGS $ updateGS <$> eInput eGameState <- changes bGameState reactimate $ (\n -> (atomically $ writeTChan gsChannel n)) <$> eGameState 

The problem with the implementation of this timer is that all the examples that I examined have a use case different from mine, physical modeling. There is no physics in this game. I am trying to use a timer to evaluate the state of a game regardless of a player’s actions. So far, the only thing I want is hyperspace. When fully implemented, moving from one planet to another will change the Agent location to Right Hyperspace . What should happen now is that when a tick occurs, distanceTraversed incremented by one. Then, if distanceTraversed is equal to totalDistance Agent , the location becomes Left Planet .

So, what would it look like in terms of EventNetwork ?

 let bHyperspace = accumB initialGS $ foo <$> eTick 

now to combine behavior

 let bBaz = (++) <$> bGameState <*> bHyperspace 

Is this the right track?

+7
source share
1 answer

The question is somewhat vague and not easy to answer, but I will try my best.

Firstly, looking at your code, it seemed strange to you that you "passed the third-party" logic of the game process to the monolithic type GameState and the updateGS function. Now this is not bad, but there is simply no benefit in using FRP in this style. You can completely remove the makeNetworkDescription function and instead register an even thandler with addCommandEvent .

The advantage of FRP is that you can model the state of a game as a network of behavior and events. If the state is sufficiently modular, this will greatly simplify the code.


Secondly, regarding your question about hyperspace modeling.

Here is one way to do this:

 -- indicates whether hyperspace travel is currently happening bTravelling :: Behavior t Bool -- increment travel distance, but only when travelling bTravelDistance :: Behavior t Distance bTravelDistance = accumB 0 $ (+1) <$> whenE bTravelling eTick -- calculate player location from travel distance bPlayerLocation :: Behavior t Location bPlayerLocation = (\distance -> if distance > total then Left Planet else Right HyperSpace) <$> bTravelDistance 

You probably want to repeat this process several times in the game. Unfortunately, reactive banana does not currently suggest β€œdoing it first and then doing it” as an abstraction. There is dynamic event switching, but this can be a bit cumbersome.

+2
source

All Articles