2013-05-10 33 views
7

我在我的旅行者處我正試圖處理與遊戲狀態無關的玩家獨立更新。作爲參考,該項目是here(devel分支是這個問題的相關問題)。功能性香蕉旅行者 - 計時器和玩家獨立活動

Libraries/Universe/GameState.hs有一個功能,updateGS處理所有玩家更新的遊戲狀態。 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 

實現此計時器的問題是,我所看到的所有示例都有一個不同於我的物理模擬的用例。這場比賽沒有物理參與。我正在嘗試使用計時器來獨立於玩家動作來評估遊戲狀態。目前,我想管理的唯一事情就是超空間旅行。當完全實現時,從一個星球移動到另一個星球會將Agentlocation更改爲Right Hyperspace。現在需要發生的是,當tick發生時,distanceTraversed遞增1。然後如果distanceTraversed等於totalDistanceAgent的位置變成Left Planet

那麼EventNetwork的觀點會是什麼樣子呢?

let bHyperspace = accumB initialGS $ foo <$> eTick 

現在的行爲

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

這是在正確的軌道相結合?

回答

2

這個問題有些模糊,不容易回答,但我會盡我所能。首先,看着你的代碼,我覺得很奇怪,你已經將實際的遊戲邏輯「外包」到了單塊的GameState類型和updateGS函數。現在,這不是一件壞事,只是在這種風格中使用FRP沒有任何好處。您可以完全刪除makeNetworkDescription函數,而是用手代替addCommandEvent註冊一個。

FRP的好處是您可以將遊戲狀態建模爲行爲和事件的網絡。如果狀態足夠模塊化,那麼這將顯着簡化代碼。


其次,關於你的建模超空間旅行的問題。

下面是做到這一點的一種方法:

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

你可能要多次重複這個過程在一場比賽中,雖然。不幸的是,反應香蕉目前不提供「先做這件事,然後再做」這種抽象。有動態的事件切換,但它可能有點笨拙。

+0

我已經意識到updateGS會成爲一個問題,但我將這個問題保存了一天。 – 2013-05-19 17:06:51