我想在选择时突出显示一个按钮(浅蓝色背景)。为此,我编写了以下代码:
players : Input Int
players = input 1
playerSelection : Element
playerSelection = flow right [
color (buttonPressed 1) (button players.handle 1 "Solo")
, color (buttonPressed 2) (button players.handle 2 "2P")
, color (buttonPressed 3) (button players.handle 3 "3P")
, color (buttonPressed 4) (button players.handle 4 "4P")
]
buttonPressed : Int -> Color
buttonPressed p = if players.signal == p then lightBlue else white
当我沿着我的其余代码运行它时,我收到这个错误消息:
if | players.signal == p -> lightBlue
| True -> white
Expected Type: Int
Actual Type: Signal.Signal Int
问题是 player.signal 是一个 Signal Int。如果我将其替换为正常数字,我的程序将正常工作。但是,我需要一个按钮在选择时变为浅蓝色,在选择另一个按钮时再次变为白色。有没有办法将信号转换为普通整数以进行比较?我已经尝试创建一个外部比较方法并将信号提升到该方法,但是这种方法的结果将是一个我无法使用的 Signal Bool。为了说明我做了什么:
buttonPressed : Int -> Color
buttonPressed p = if equals p <~ players.signal then lightBlue else white
equals : Int -> Int -> Bool
equals a b = a == b
更新
我试图将信号“更高”移动到调用函数,但问题仍然存在。我不妨展示所有的代码(它并不多,我应该首先这样做)。
heartbeat = every (second/50)
data Player = One | Two | Three | Four
-- STARTING SCREEN
players : Input Int
players = input 1
beginState : Int -> Element
beginState ps = collage 600 600 [
move (0,270) (toForm (playerSelection ps))
]
playerSelection : Int -> Element
playerSelection ps = flow right [
color (buttonPressed 1 ps) (button players.handle 1 "Solo")
, color (buttonPressed 2 ps) (button players.handle 2 "2P")
, color (buttonPressed 3 ps) (button players.handle 3 "3P")
, color (buttonPressed 4 ps) (button players.handle 4 "4P")
]
buttonPressed : Int -> Int -> Color
buttonPressed p ps = if p == ps then lightBlue else white
playState : Element
playState = draw
draw : Element
draw = collage 1024 768 [
filled black (rect 1024 768)
]
endState : String -> Element
endState p = plainText (show p ++ " has won!")
startGame : Signal Element
startGame = foldp (\_ _ -> draw) (beginState <~ players.signal) Keyboard.space
main : Signal Element
main = startGame
我将首先解释我的最终目标是什么。游戏在开始屏幕 (beginState) 中开始。在此屏幕中,玩家可以自定义:
- 昵称(返回字符串的文本字段)
- 控件(wasd、箭头键、用户定义的任何方向键)
- 玩家数量
输入空格键后,游戏开始,这些参数不能再更改。这可以在startGame中看到。实际游戏的运作方式与本主题无关,但重要的是要知道我希望将开始屏幕的自定义选项转移到游戏机制中。因此,每个玩家的某些操作的输入键必须与控件文本字段中选择的字符一致。选择的玩家数量将决定在游戏中创建哪些对象。此游戏的 playState 目前已替换为 holder draw
。
关于问题:
我正在慢慢地了解到,我不能简单地通过调用来询问玩家的数量,players.signal
因为我会得到一个 Signal Int 而不是 Int。这意味着我将无法调用,例如controls.signal
,检索要放入的字符Keyboard.directions
(因为我将得到一个信号字符而不是字符)。问题基本上是,我如何像使用其他编程语言中的变量一样存储和传递来自信号的信息?
我在这段代码上工作得越多,我就越意识到我不明白信号是如何工作的。在您的示例(Apanatshka)中,我看到您将信号提升到 playerSelection,它需要一个 Int 作为参数而不是 Signal Int。当我尝试应用它时(请参阅此更新部分中的代码),我收到以下错误:
Type error on line 76, column 35 to 63:
beginState <~ players.signal
Expected Type: Signal.Signal Graphics.Element.Element
Actual Type: Graphics.Element.Element
我大致了解可能出了什么问题。一个函数正在发送两个信号,它只需要一个信号。老实说,我更愿意看到信号传播到更相关的位置,比如在 beginState 中:
beginState : Element
beginState = collage 600 600 [
move (0,270) (toForm (playerSelection <~ players.signal))
]
但是随后 toForm 得到了一个 Signal Element 参数而不是 Element,这又带来了问题。从技术上讲,我可以将信号一直放在 main 中,但我对此感觉非常糟糕,因为players.signal
一旦游戏开始并且信号作为 Int 参数传递就不再需要它了。
我希望我很清楚我想要完成什么。并快速总结我的问题:
- 如果不将players.signal
我的所有信号都支撑到主信号,我的代码在哪里适合?
- 我将如何存储和传递来自信号的信息?