如何创建一个事件,其中包含当前tick的值与前一个tick处的值之间的差异?

时间:2016-02-08 14:58:44

标签: haskell frp reactive-banana

我正在使用reactive-bananasdl2(使用this glue library)进行类似游戏的项目。为“绝对鼠标位置”创建Behavior,为“相对鼠标位置”(例如鼠标移动)创建Behavior。当不使用FRP时,这很有效,但是对于FRP,“相对鼠标位置”成为一个问题:似乎只有少量数据通过。我怀疑这种情况发生是因为潜在的“SDL事件”(我们用Behavior表示)与tick Event没有很好的排列。

所以我想通过简单地比较当前刻度的鼠标位置和前一刻度的位置来计算我自己的鼠标移动。我不确定这是否能解决我的问题,但我有很好的希望:)

首先,我迷失了如何接近它:State monad,IORefreactive-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 ...

如上所述,我想根据当前mouseMovementE mousePositionB(称为tickE)和mousePositionE值来表达mousePositionE在之前的tickE

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

您正在寻找从事件流构建事件的accumE。我强烈建议您阅读文档的递归部分,该部分描述了如何根据stepperapply实现它。

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