制作游戏并寻找一种方法来调用主函数来启动游戏时(用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
还尝试将音乐发挥自己的作用 旋律::音乐音调 旋律= Euterpea.line [af 4 dqn:=:cf 4 dqn]
并将其绑定(如背景): 音乐<-旋律 并在main中调用它,但也不能使它正常工作。
有什么秘诀吗?
答案 0 :(得分:0)
我没有安装光泽剂和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调用不会t互相阻挡。 (使用Haskell线程不需要-threaded
;关于其影响的完整讨论要比在这里进行的合理讨论要长,但是there is an excellent paper有更多详细信息。)
答案 1 :(得分:0)
我既没有安装光泽纸,也没有安装紫咖啡,但是我猜两个express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
var randomInt = require('random-int');
const URL = 'url';
var randomNumber = randomInt(11);
var dataTitle;
axios.get(URL + randomNumber)
.then(function (response) {
dataTitle = response.data.question;
console.log(dataTitle)
})
.catch(function (error) {
console.log(error);
});
函数描述的IO
动作是无限运行的,因此无论哪个被执行,都会先执行,而另一个将永远等待而不会被蜂鸣被执行。
为解决此问题,您可以使用play
中的forkIO
在单独的线程中播放音乐:
Control.Concurrent
在游戏关闭后杀死线程:
musicThreadId <- forkIO $ Euterpea.play $ Euterpea.line [af 4 dqn :=: cf 4 dqn :=: ef 4 dqn]
只要您的音乐与游戏无关,它就起作用。如果要包含依赖于游戏中发生的事件的声音(例如声音效果),则需要使游戏与播放声音的线程进行线程安全通信。线程之间的通信是一种副作用,必须使用killThread musicThreadId
处理。在这种情况下,您应该看看IO
中的playIO
,因为Graphics.Gloss.Interface.IO.Game
仅支持游戏逻辑,没有副作用。
您可以阅读有关Haskell中关于并发编程的更多信息: http://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Concurrent.html
或西蒙·马洛(Simon Marlow)的《