-1

制作游戏并在调用 main 函数启动游戏时寻找启动音乐的方法(用 Euterpea 用 haskell 制作)。

这段代码的问题是它会播放音乐,但不会启动游戏。如果我把音乐放在 Pure.Game.play 之后,游戏就会开始,但不会播放音乐。

main :: IO ()
main = do
backgroundImage <- background
 let backgrounds = [backgroundImage]
**Euterpea.play $ Euterpea.line [af 4 dqn :=: cf 4 dqn :=: ef 4 dqn]**
Graphics.Gloss.Interface.Pure.Game.play (InWindow "game" (windowwidth, 
windowheight) (0,0)) cyan 300 (drawGame background) inputHandler step

还尝试在自己的函数中拥有音乐melody :: Music Pitch melody = Euterpea.line [af 4 dqn :=: cf 4 dqn]

并绑定它(就像与背景一样):music <- melody 并在 main 中调用它,但也无法让它工作。

任何提示如何做到这一点?

4

2 回答 2

0

我没有安装光泽和euterpea,所以我无法测试,但我敢打赌,将其中一个或另一个分叉到自己的线程中就足够了。我建议分叉euterpea;图形库有时会使用线程局部状态,这会以一种无聊的方式使问题复杂化。所以:

import Control.Concurrent
main = do
    backgroundImage <- background
    forkIO $ Euterpea.play (Euterpea.line [af 4 dqn :=: cf 4 dqn :=: ef 4 dqn])
    Gloss.play (InWindow "game" (windowwidth, windowheight) (0,0)) cyan 300 (drawGame [background]) inputHandler step

一个或另一个可能以一种有趣的方式使用 FFI 调用,所以如果上面的代码片段不足以让事情顺利进行,请考虑编译-threaded以确保 FFI 调用不会相互阻塞。(使用 Haskell 线程不需要 NB -threaded;对其效果的完整讨论比这里合理的要长,但是有一篇很棒的论文有更多的细节。)

于 2019-02-25T17:50:55.350 回答
0

我既没有安装gloss也没有安装euterpea,但我猜这IO两个函数描述的动作都是play无限运行的,所以首先调用的都会执行,而另一个将永远等待而不执行。

为了解决这个问题,您可以使用forkIOfrom在单独的线程中启动音乐Control.Concurrent

musicThreadId <- forkIO $ Euterpea.play $ Euterpea.line [af 4 dqn :=: cf 4 dqn :=: ef 4 dqn]

并在游戏关闭后终止线程:

killThread musicThreadId

只要您的音乐独立于游戏,这就会起作用。如果您想包含取决于游戏中发生的事情的声音(例如声音效果),您需要让您的游戏与播放声音的线程进行线程安全通信。线程之间的通信是一个副作用,必须使用IO. 在这种情况下你应该看一下playIOfrom Graphics.Gloss.Interface.IO.Game,因为play它只支持没有副作用的游戏逻辑。

您可以阅读更多关于 Haskell 中关于 hackage 的并发编程:http: //hackage.haskell.org/package/base-4.12.0.0/docs/Control-Concurrent.html

或在Simon Marlow的《Haskell 中的并行和并发编程》一书中,可在线获取: https ://www.oreilly.com/library/view/parallel-and-concurrent/9781449335939/

于 2019-02-25T18:12:25.277 回答