haskell - 使用 netwire 进行游戏实体建模

标签 haskell frp

我将使用 netwire 和 OpenGL 在 Haskell 中编写一个实时游戏。基本思想是每个对象都由一根线表示,它会获取一些数据作为输入并输出其状态,然后我会将它们全部连接到一根大线中,以获取 GUI 的状态作为输入并输出世界状态,然后我可以将其传递给渲染器以及一些“全局”逻辑,如碰撞检测。

我不确定的一件事是:我想如何输入电线?并非所有实体都有相同的输入;玩家是唯一可以访问键输入状态的实体,寻找导弹需要目标的位置等。

  • 一个想法是让 ObjectInput 类型传递给所有东西,但这对我来说似乎很糟糕,因为我可能会不小心引入我不想要的依赖项。
  • 另一方面,我不知道拥有 SeekerWire、PlayerWire、EnemyWire 等是否是个好主意,因为它们几乎“相同”,因此我必须在它们之间复制功能。

  • 我应该怎么办?

    最佳答案

    抑制幺半群e是抑制异常的类型。这不是电线产生的东西,但与e 的作用大致相同。在 Either e a .换句话说,如果您通过 <|> 组合电线,则输出类型必须相等。

    假设您的 GUI 事件通过输入传递到线路,并且您有一个连续的按键事件。一种建模方法是最直接的:

    keyDown :: (Monad m, Monoid e) => Key -> Wire e m GameState ()
    

    此连线将当前游戏状态作为输入并生成 ()如果键被按住。当键没有被按下时,它只是禁止。大多数应用程序并不真正关心为什么线路禁止,因此大多数线路禁止使用 mempty .

    表达此事件的更方便的方法是使用 reader monad:
    keyDown :: (Monoid e) => Key -> Wire e (Reader GameState) a a
    

    这个变体真正有用的是,现在您不必将游戏状态作为输入传递。相反,当事件发生时,这条线就像身份线一样,当它没有发生时,它会被禁止:
    quitScreen . keyDown Escape <|> mainGame
    

    这个想法是,当按下转义键时,事件线 keyDown Escape暂时消失,因为它就像身份线一样。所以整条线就像 quitScreen假设它不会抑制自己。一旦键被释放,事件线被禁止,所以与 quitScreen 的组合抑制,也是。因此,整根电线的作用类似于 mainGame .

    如果你想限制一条线可以看到的游戏状态,你可以很容易地为此编写一个线组合器:
    trans :: (forall a. m' a -> m a) -> Wire e m' a b -> Wire e m a b
    

    这允许您申请 withReaderT :
    trans (withReaderT fullGameStateToPartialGameState)
    

    关于haskell - 使用 netwire 进行游戏实体建模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14668075/

    相关文章:

    haskell - 与函数实例化显示的奇怪模式匹配

    haskell - 使用列表理解的带有谓词的自定义过滤器函数

    haskell - 尝试时链接错误 "stack install yesod-bin"

    javascript - Promise 是单播还是广播?

    javascript - Bacon.js 是否有一些组合器可以让您收集同时发出的两个事件?

    haskell - 如何映射具有多个参数的函数

    haskell - GHC 如何使用 Num 实例将多态数字文字转换为任意类型?

    java - 将 Observables 收集到列表似乎不会立即发出集合

    ios - 使用 ReactiveCocoa 实现 Pan Gesture 接口(interface)

    javascript - RxJS Promise Composition(传递数据)