3

我正在使用reactive-bananasdl2(使用这个胶水库)进行类似游戏的项目。ABehavior是为“绝对鼠标位置”创建的,以及为Behavior“相对鼠标位置”(也就是鼠标移动)创建的。不使用 FRP 时效果很好,但使用 FRP 时,“相对鼠标位置”会成为问题:似乎只有少量数据通过。我怀疑发生这种情况是因为底层的“SDL 事件”(我们用 a 表示Behavior)没有与 tick Events 很好地对齐。

所以我想计算我自己的鼠标移动,只需将当前刻度的鼠标位置与前一个刻度的位置进行比较。我不确定这是否能解决我的问题,但我有很好的希望:)

首先,我不知道如何处理它:Statemonad,或 an IORef,还是reactive-banana提供另一种方法?

我将摘录我目前拥有的代码:

makeNetwork :: GraphicsData -> SDLEventSource -> MomentIO ()
makeNetwork gd sdlEventSource = mdo
  tickE          <- tickEvent sdlEventSource
  mouseMovementB <- fromPoll SDL.getRelativeMouseLocation
  mousePositionB <- fromPoll SDL.getAbsoluteMouseLocation

  let mousePositionE = mousePositionB <@ tickE
      mouseMovementE = mouseMovementB <@ tickE  -- this yields flaky data

  -- ... the rest of the network description left out ...

如上所述,我想mouseMovementEmousePositionBat current tickE(称为mousePositionE)和mousePositionEprevious 的值来表达tickE

任何帮助是极大的赞赏!

4

1 回答 1

2

您正在寻找accumE哪些从事件流中构建事件。我强烈建议阅读文档的递归部分,该部分描述了它是如何用stepper和实现的apply

accumE :: MonadMoment m => a -> Event (a -> a) -> m (Event a)
--        starting value --^           |             |
--  stream of events that modify it  --^             |
--  resulting events                               --^

要计算两点之间的差异,accumE我们需要跟踪前一点。我们还将跟踪当前点。这将保留最近事件的两项历史记录。

  (Point V2 CInt , Point V2 CInt)
-- previous value, current value

edges :: MonadMoment m => a -> Event a -> m (Event (a, a))
edges initial later = accumE (initial, initial) (shift <$> later)
    where
        shift x2 (x0, x1) = (x1, x2)

为了得到差异,我们将从当前的减去前一个。这将提供一个完整的网络

makeNetwork :: GraphicsData -> SDLEventSource -> MomentIO ()
makeNetwork gd sdlEventSource = mdo
  tickE          <- tickEvent sdlEventSource
  mousePositionB <- fromPoll SDL.getAbsoluteMouseLocation

  let mousePositionE = mousePositionB <@ tickE

  mouseHistoryE <- edges zero mousePositionE

  let mouseMovementE = (\(x0, x1) -> x1 ^-^ x0) <$> mouseHistoryE

  -- ...

zero并且^-^来自Linear.Vector

于 2016-02-08T17:19:02.207 回答