步骤 5 - 响应输入消息

在此步骤中,您将学习如何在 Lua 脚本中使用消息处理程序。

您首先声明一个消息处理程序,然后向消息处理程序添加功能以移动这些部分。

声明一个消息处理程序

要声明消息处理程序:

  1. 使用在 Kanzi Studio 项目中定义的 MovePieceMessage 消息类型。

    在脚本中,将变量初始化在其他变量旁边。

    在 Preview 中,当您点击一个 Piece 预设时,Button 2D 节点将此消息发送给自身。

    ../../_images/library-movepiecemessage.png
    -- Find the "fifteen_puzzle.MovePieceMessage" custom message type.
    local MovePieceMessage = MessageType:new("fifteen_puzzle.MovePieceMessage")
    
  2. 在定义 createArray 函数之前,定义 MovePieceMessage 的消息处理函数。

    -- Declare a message handler function for the "MovePieceMessage".
    local function movePieceMessageHandler(args)
        -- Read the message argument that contains the index of the clicked piece.
        local index = args:getArgument(PieceIndexProperty)
    
        -- Find the clicked node.
        local piece = grid:getChild(index - 1)
    
        -- Read the property values of the clicked node.
        local row = piece:getProperty(GridLayout2D.RowProperty)
        local column = piece:getProperty(GridLayout2D.ColumnProperty)
    
        print(string.format("Clicked node %d at (%d,%d)", index, row, column))
    end
    
  3. 要使 movePieceMessageHandler 函数执行某些操作,您必须将其添加到一个节点中。在创建每个部分时,请使用 addMessageHandler 函数执行此操作,但在将其添加到网格之前。

    -- Create the grid child nodes.
    for i = 1,PieceCount do
    
        ...
    
        -- Add a message handler for the MovePieceMessage.
        piece:addMessageHandler(MovePieceMessage, movePieceMessageHandler)
    
        -- Add the new node to the grid.
        grid:addChild(piece)
    end
    

当您保存脚本并在 Preview 中点击 重新启动 (Restart),然后点击任意棋子时,脚本会在 Log 中打印出被点击棋子的索引及其在 Grid 节点中的坐标。

../../_images/log-message-handler.png

单击时移动拼图块

请注意,消息处理程序在脚本退出后仍然存在,即使您进一步编辑脚本也是如此。此脚本始终删除所有使用 grid:removeAllChildren() 创建的节点,这也会删除消息处理程序。

要在点击时移动拼图块:

  1. 声明变量以跟踪网格中的空槽。

    在脚本中,将变量初始化在其他变量旁边。

    -- Keep track of the empty slot in the grid.
    -- Initially the empty slot is at the bottom right of the grid.
    local freeSlotRow = RowCount - 1
    local freeSlotColumn = ColumnCount - 1
    
  2. 修改 movePieceMessageHandler 消息处理程序,使其不仅仅打印到 Log,而是移动被点击的棋子并将移动记录到 Log。

    -- Declare a message handler function for the "MovePiece" message.
    local function movePieceMessageHandler(args)
        -- Read the message argument that contains the index of the clicked piece.
        local index = args:getArgument(PieceIndexProperty)
    
        -- Find the node that was clicked.
        local piece = grid:getChild(index - 1)
    
        -- Read the property values of the clicked node.
        local row = piece:getProperty(GridLayout2D.RowProperty)
        local column = piece:getProperty(GridLayout2D.ColumnProperty)
    
        -- Check whether the piece can be moved.
        local dy = math.abs(row - freeSlotRow)
        local dx = math.abs(column - freeSlotColumn)
        if dx + dy == 1 then
           print(string.format("Moved piece %d from (%d,%d) to (%d,%d)", index, row, column, freeSlotRow, freeSlotColumn))
    
           -- Move the piece.
           piece:setProperty(GridLayout2D.RowProperty, freeSlotRow)
           piece:setProperty(GridLayout2D.ColumnProperty, freeSlotColumn)
           freeSlotRow = row
           freeSlotColumn = column
        end
    end
    

当您保存脚本并在 预览 中点击 重新启动 (Restart),然后点击空槽旁边的任何棋子时,脚本:

  1. 移动该棋子。

  2. 将点击的棋子索引及其在网格中先前和当前位置的坐标打印到 Log。

../../_images/step5-result.gif