cocos2d-xとLuaでゲームが出来るかな?

cocos2d-xとLuaを覚え書き

Luaでのモーダルレイヤー

先日待望のCococs2d-xの日本語の書籍が発売されました。

その中でモーダルレイヤーの作り方が書いてあり、本のままLuaでやろうとしてちょっと悩んだので書いておきます。

モーダルレイヤー

ゲーム画面の上に確認画面等を表示したとき、確認画面のボタンやタッチだけ反応して、ゲーム画面は反応してほしくない! とうことがよくあると思います。

cocos2d-xでどやってそれを実装するかですが、

  1. ゲーム画面のボタンやタッチの反応をON/OFFする。
  2. ゲーム画面にボタンやタッチのイベントを通知しない。

等があると思います。
1.は簡単に思いつく方法でメニューボタンやタッチをEnabled(false)するだけでOKですが、メニューの数だけ用意する必要があり大変です。
2.は"タッチの優先度"を利用した方法です。メニューよりもタッチ優先度の高いレイヤーを用意して全てのタッチイベントを拾い、それ以下にはタッチ処理をさせないようにします。

いままで1.の方法でやっていたのですが、2.の方法を本で知ったので試してみました。

Luaでのモーダルレイヤーの作り方

まず、本で紹介されているC++での実装方法
CCLayerを継承したModalLayerクラス内のinit()で優先度を設定し、ccTouchBeganでtrueを返すことで、それ以下へタッチイベントを渡さないようにしています。

//kCCMenuHandlerPriority = -128 CCMenuのデフォルトの優先度

bool ModalLayer::init()
{
    ~省略~

    this->setTouchPriority( kCCMenuHandlerPriority - 1)   //優先度をCCMenuより高く
    this->setTouchEnabled(true);                          //タッチを有効化
    this->setTouchMode(kCCTouchesOneByOne);               //シングルタッチで拾う

    ~~~~
}
bool ModalLayer::ccTouchBegan( CCTouch* touch, CCEvent* event)
{
    //モーダルレイヤーですべてのタッチイベントを拾う
    return true;
}


これをLuaでも作ってみますが注意点が2点。
LuaからもCCLayer:setTouchPriority()を使用できますが、これは動作しません!?
setTouchPriority() で優先度を設定しても実際に反映されず、デフォルトの優先度0になってしまいます。
ついでにsetTouchMode()ですが、これも動作しません!?


では、どうするかというと、
CCLayer:registerScriptTouchHandler(nHandler, bIsMultiTouches, nPriority, bSwallowsTouches)
を使用します。

Luaでのモーダルレイヤーは以下のようになります。

function ModalLayer:init()
    ~省略~

    self:registerScriptTouchHandler( 
                    function(...) return self:onTouch(...) end, --タッチイベントハンドラーを指定
                    false,                               --シングルタッチで拾う
                    kCCMenuHandlerPriority -1,           --優先度をCCMenuより高く
                    true                                 --タッチイベントを止めるか
                    )

    ~~~~
end

function ModalLayer:onTouch( eventType, x, y)
    --モーダルレイヤーですべてのタッチイベントを拾う
    return true
end

Luaではハンドラーを登録すると共に、シングルorマルチタッチ、タッチの優先度、イベントを止めるかの設定をします。
注意するのは、4番目の引数 SwallowsTouches = trueにしただけでは、イベントを止められないというところです。C++と同じようにタッチイベントを処理するonTouch内で return trueをする必要があります。