2013-05-10 11 views
7

Jestem na etapie mojego podróżnika Próbuję poradzić sobie z niezależnymi od gracza aktualizacjami stanu gry. Dla odniesienia, projekt jest here (gałąź devel jest odpowiednia dla tego pytania).Funkcjonalny bananowy podróżnik - zdarzenia niezależne od zegara i odtwarzacza

Libraries/Universe/GameState.hs ma funkcję, updateGS, która obsługuje wszystkie aktualizacje odtwarzacza do stanu gry. Teraz wygląda to tak: EventNetwork.

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 

Problemem w realizacji tego czasomierza jest to, że wszystkie przykłady Mam spojrzał na sprawę mają wykorzystywać różne od moich, symulacji fizyki. W tej grze nie ma fizyki. Próbuję użyć timera, aby ocenić stan gry niezależnie od działań gracza. Na razie jedyną rzeczą, którą chcę zarządzać, są podróże nadprzestrzenne. Po całkowitym wdrożeniu przejście z jednej planety na drugą zmieni 's location do Right Hyperspace. To, co musi się teraz stać, to fakt, że gdy tick się dzieje, distanceTraversed zwiększa się o jeden. Następnie, jeśli distanceTraversed jest równa totalDistanceAgent, lokalizacja staje się Left Planet.

Więc jaki byłby to wyglądać z punktu widzenia EventNetwork?

let bHyperspace = accumB initialGS $ foo <$> eTick 

teraz połączyć zachowań

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

Czy to właściwe tory?

Odpowiedz

2

Pytanie jest nieco niejasne i niełatwo odpowiedzieć, ale postaram się jak najlepiej.

Po pierwsze, patrząc na twój kod, wydaje mi się dziwne, że "zleciłeś" rzeczywistą logikę rozgrywki typowi monolitycznemu GameState i funkcji updateGS. Teraz nie jest to nic złego, po prostu nie ma żadnej korzyści z używania FRP w tym stylu. Możesz całkowicie usunąć funkcję makeNetworkDescription, a zamiast tego ręcznie zarejestrujesz przy pomocy addCommandEvent.

Zaletą programu FRP jest modelowanie stanu gry jako sieci zachowań i zdarzeń. Jeśli stan jest wystarczająco modułowy, znacznie uprości to kod.


Po drugie, jeśli chodzi o pytanie dotyczące modelowania podróży w nadprzestrzeni.

Oto jeden ze sposobów, aby to zrobić:

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

Prawdopodobnie chcą powtórzyć ten proces kilka razy w grze, choć. Niestety, reaktywny banan obecnie nie oferuje "najpierw tego, a potem zrób to", rodzaj abstrakcji. Istnieje dynamiczne przełączanie zdarzeń, ale może być nieco niewygodne.

+0

Uświadomiłem sobie, że updateGS będzie stanowić problem, ale zapisywałem to pytanie na inny dzień. –

Powiązane problemy