作为榆树的学习范例,我想用榆树建筑创造一个简单的蛇游戏。
到目前为止,这是完整的代码: https://gist.github.com/DanEEStar/b11509514d72eaafb640378fc7c93b44
程序的一部分是UpdateWorld
消息,它通过按钮单击和updateWorld
函数生成,该函数在用户按空格键时调用。
这导致以下编译和工作代码(代码片段形成完整代码):
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UpdateWorld ->
( updateWorld model, Cmd.none )
KeyPress keyCode ->
( handleInput keyCode model, Cmd.none )
handleInput : Int -> Model -> Model
handleInput keyCode model =
case Char.fromCode keyCode of
' ' ->
updateWorld model
_ ->
model
updateWorld : Model -> Model
updateWorld model =
{ model | snake = updateSnake model.snake }
subscriptions : Model -> Sub Msg
subscriptions model =
Keyboard.presses KeyPress
view : Model -> Html Msg
view model =
div []
-- here I can simply tell `onClick` to generate the `UpdateWorld` command
[ button [ onClick UpdateWorld ] [ text "tick" ]
]
在此代码段中,很明显onClick
事件会生成UpdateWorld
命令。
但是在handleInput
函数中,我必须“手动”调用updateWorld
函数。
我宁愿做的是从我的UpdateWorld
函数“生成”一个新的handleInput
命令。我认为这将澄清代码。类似的东西:
handleInput keyCode =
case Char.fromCode keyCode of
' ' ->
-- how can I generate this command in my code
UpdateWorld
我怎么能这样做?
这是一个好主意,还是一个更好的模式?
答案 0 :(得分:4)
回想一下update
只是一个函数,这意味着你可以递归地调用它。
考虑更改handleInput
的签名以返回(Model, Cmd Msg)
,就像update
函数一样:
handleInput : Int -> Model -> (Model, Cmd Msg)
handleInput keyCode model =
case Char.fromCode keyCode of
' ' ->
update UpdateWorld model
'a' ->
{ model | snake = changeSnakeDirection model.snake West } ! []
...
您可以删除updateWorld
函数并将该代码移动到UpdateWorld
消息处理程序:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UpdateWorld ->
( { model | snake = updateSnake model.snake }, Cmd.none )
ChangeDirection newDirection ->
( { model | snake = changeSnakeDirection model.snake newDirection }, Cmd.none )
KeyPress keyCode ->
handleInput keyCode model