2013-05-10 11 views
7

Sono al punto nel mio Traveler Sto cercando di gestire gli aggiornamenti indipendenti dal giocatore allo stato del gioco. Per riferimento, il progetto è here (il ramo di sviluppo è quello pertinente per questa domanda).Functional Banana Traveler - Eventi indipendenti dal timer e dal giocatore

Libraries/Universe/GameState.hs ha una funzione, updateGS che gestisce tutti gli aggiornamenti dei giocatori allo stato del gioco. Il EventNetwork sembra proprio ora.

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 

Il problema nell'attuazione della presente timer è che tutti gli esempi che ho guardato hanno un caso d'uso diversa dalla mia, la simulazione fisica. Non c'è fisica coinvolta in questo gioco. Sto cercando di utilizzare un timer per valutare lo stato del gioco indipendentemente dalle azioni del giocatore. Per ora, l'unica cosa che voglio gestire è viaggiare nell'iperspazio. Una volta implementato completamente, lo spostamento da un pianeta all'altro modificherà lo location a Right Hyperspace. Ciò che deve accadere ora, è che quando si verifica un tick, incrementi di distanceTraversed di uno. Quindi se distanceTraversed corrisponde alla posizione totalDistanceAgent diventa Left Planet.

Quindi che aspetto avrebbe questo dal punto di vista di EventNetwork?

let bHyperspace = accumB initialGS $ foo <$> eTick 

ora di combinare comportamenti

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

E 'questa la strada giusta?

risposta

2

La domanda è alquanto vaga e non facile da rispondere, ma farò del mio meglio.

Innanzitutto, osservando il tuo codice, trovo strano che tu abbia "esternalizzato" l'effettiva logica di gioco al tipo monolitico GameState e alla funzione updateGS. Ora, questa non è una brutta cosa da fare, è solo che non c'è alcun vantaggio nell'usare FRP in questo stile. È possibile rimuovere completamente la funzione makeNetworkDescription e registrare un numero addirittura pari a addCommandEvent a mano.

Il vantaggio di FRP è che è possibile modellare lo stato del gioco come una rete di comportamenti ed eventi. Se lo stato è abbastanza modulare, allora questo semplificherà significativamente il codice.


In secondo luogo, riguardo alla tua domanda sulla modellazione del viaggio nell'iperspazio.

Ecco un modo per farlo:

-- 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 

Probabilmente si desidera ripetere questo processo più volte in un gioco, però. Sfortunatamente, la banana reattiva al momento non offre una sorta di astrazione. C'è un cambio di evento dinamico, ma potrebbe essere un po 'ingombrante.

+0

Mi ero reso conto che l'updateGS sarebbe stato un problema, ma stavo salvando quella domanda per un altro giorno. –

Problemi correlati