我正处于旅行者的这一点我正试图处理与游戏状态无关的玩家更新。作为参考,项目是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
实现此计时器的问题在于,我所看到的所有示例都有一个与我的物理模拟不同的用例。这场比赛没有物理参与。我正在尝试使用计时器来评估独立于玩家行为的游戏状态。目前,我唯一想管理的是超空间旅行。完全实施后,从一个星球移动到另一个星球会将Agent
的{{1}}更改为location
。现在需要做的是,当Right Hyperspace
发生时,tick
递增1。如果distanceTraversed
等于distanceTraversed
totalDistance
的位置变为Agent
。
那么从Left Planet
的角度来看会是什么样的呢?
EventNetwork
现在要结合行为
let bHyperspace = accumB initialGS $ foo <$> eTick
这是正确的轨道吗?
答案 0 :(得分:2)
这个问题有点模糊,不容易回答,但我会尽我所能。
首先,看看你的代码,我发现很奇怪你将实际的游戏玩法逻辑“外包”到整体GameState
类型和updateGS
函数。现在,这不是一件坏事,只是在这种风格中使用FRP没有任何好处。您可以完全删除makeNetworkDescription
功能,然后手动注册偶数thandler 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
你可能想在游戏中多次重复这个过程。不幸的是,反应性香蕉目前不提供“先做这个,然后做那种”的抽象。有动态事件切换,但可能有点笨拙。