ステップ5 - 入力メッセージに反応する

このステップでは、Luaスクリプトでメッセージハンドラを使用する方法を学びます。

最初にメッセージハンドラーを宣言し、その後、メッセージハンドラーにピースを移動する機能を追加します。

メッセージハンドラを宣言する

メッセージハンドラを宣言するには:

  1. Kanzi Studio プロジェクトで定義されている MovePieceMessage メッセージタイプを使用します。

    スクリプト内で、他の変数の隣に変数を初期化します。

    プレビュー で Piece プレハブをクリックすると、ボタン 2D (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
    

スクリプトを保存し、プレビュー で リスタート (Restart) をクリックしてから任意のピースをクリックすると、スクリプトはクリックしたピースのインデックスと Grid ノード内でのその座標を Log に出力します。

../../_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