[Cocos 2 d-x v 3.x公式文書]イベントの配布メカニズム

45998 ワード

泰然ネット http://www.tairan.com/archives/6280 
イベント配布メカニズム
新たなイベント配信の仕組み:2.xバージョンのイベント処理では、トリガとなるイベントをプロキシ(delegate)に渡して処理し、プロキシ内のontouchBeganなどの方法でイベントを受信し、最後にイベントの応答を完了します.新しいイベント配信機構では、イベントモニターを作成することにより、各種トリガ後の論理を実現し、イベント配信器に追加するだけでよい.eventDisplatchは、すべてのイベントモニターがこのディストリビュータによって統一的に管理され、イベント応答が完了します.
イベントモニターには以下の種類があります.
イベントタッチキーボード応答イベント(EventListenerKeyboard)マウス応答イベント(EventListenerMouse)カスタムイベント(EventListenerCustom)加速レコードイベント_.event Displatchの仕事は三つの部分から構成されています.
イベント配布器EventDisplatch イベントタイプはEventTouch、Event Keyboardなどです.
イベントモニターEventListenerTouch、EventListenerKeyboardなどモニターは、イベントのタイプを適切な時にイベント配信器によって配信し、その後、対応するタイプのモニターを呼び出して、様々なトリガ後のロジックを実現する.
ユーザ入力イベント
事件に触れる
タッチイベントを扱う時に、3つの方法ontouchBegan、ontouch MovedとontouchEdedを書き換えることができます.また、Lamda表現によって直接に応答ロジックを完成することもできます.
2.xバージョンでは、マルチタッチをオンにするには、AppController.mmの中のaplication didFinish Launching WithOptions:launchOptionsに[u][gl View set Multiplication TouchEnballed:YES]を追加する必要があります.また、5つの関数を再ロードします.
virtual void register WithTouch Displatch(void);virtual void cctTouches Began(cococococos 2 d:CCSet pTouches、cocococos 2 d:CCEvent pEvent;virtual void cctTouches Moved(cococococos 2 d:CCSet pTouches、cocococos 2 d:CCEvent pEvent;virtual void cctTouches Eded(cococococos 2 d:CCSet pTouches、cocococos 2 d:CCEvent pEvent;virtual void cctTouches Call led(cocococococos 2 d:CCSet pTouches、cocococos 2 d:CCEvent pEvent;3.0では、マルチタッチイベントモニタを作成し、イベント配信器に追加すればいいです.
次のコードは一つのインターフェースに三つのボタンを追加し、三つのボタンが互いに遮蔽され、いずれもタッチイベントをトリガすることができる.
    //       
    auto sprite1 = Sprite::create("Images/CyanSquare.png");
    sprite1->setPosition(origin+Point(size.width/2, size.height/2) + Point(-80, 80));
    addChild(sprite1, 10);
    // sprite2
    ...
    // sprite3
    ...
ボタンの精霊を作成したら、ワンポイントタッチイベントモニターを作成して、対応する論理処理を完成します.
    //              OneByOne      
    auto listener1 = EventListenerTouchOneByOne::create();
    //         ,  onTouchBegan      true    
    listener1->setSwallowTouches(true);

    //    lambda    onTouchBegan       
    listener1->onTouchBegan = [](Touch* touch, Event* event) -> bool {
        //          target 
        auto target = static_cast<Sprite*>(event->getCurrentTarget());

        //                   
        Point locationInNode = target->convertToNodeSpace(touch->getLocation());
        Size s = target->getContentSize();
        Rect rect = Rect(0, 0, s.width, s.height);

        //         
        if (rect.containsPoint(locationInNode))
        {
            log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
            target->setOpacity(180);
            return true;
        }
        return false;
        };

    //        
    listener1->onTouchMoved = [](Touch* touch, Event* event){...};

    //         
    listener1->onTouchEnded = [=](Touch* touch, Event* event){...};
最後にイベントモニターをイベントディストリビュータに追加する必要があります.
    //      
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
以上のコードの中_eventDisplatchはNodeの属性であり、現在のノード(シーン、レイヤー、精霊など)の全てのイベントの配信を管理しています.しかし、それ自体は単一の例のモード値の参照であり、Nodeの構造関数では、Director:getInstance()->getEvent Dispactch();この属性があれば、事件を処理しやすくなります.
注意:listener 1を再利用する場合、新しいクローンを作成するためには、addEventListenerWithScenese Gream PriorityまたはaddEventListenerWithFixedition方法を使用する必要があります.また、非常に重要な点があります.FixedPriority listenerを追加した後は手動でremoveが必要です.SceneGreapph Priority listenerはNodeと結合しています.Nodeのコンフィギュレーション関数から削除されます.具体的な使い方の例はエンジンが持つtestsを参照してください.
追加されたモニターを以下の方法で除去することができます.
_.eventDisplatch->removeEventListener;
現在のイベント分配器のすべてのモニターを除去するために、以下の方法を用いることもできる.
_.eventDisplatch->removeAllEvent Listeners();
removeAllを使用すると、このノードのすべての傍受は削除され、指定された削除方式を使用することを推奨する.removeAll後もメニューが応答しません.タッチイベントを受ける必要があるからです.
キーボード応答イベント
キーボード応答イベントとタッチイベントの処理は同じ方法で行われています.コードのデモはキーボード応答イベントをどうやって処理しますか?
    //       
    auto listener = EventListenerKeyboard::create();
    listener->onKeyPressed = CC_CALLBACK_2(KeyboardTest::onKeyPressed, this);
    listener->onKeyReleased = CC_CALLBACK_2(KeyboardTest::onKeyReleased, this);

    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

    //         
    void KeyboardTest::onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event)
    {
        log("Key with keycode %d pressed", keyCode);
    }

    void KeyboardTest::onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event)
    {
        log("Key with keycode %d released", keyCode);
    }
マウス応答イベント
3.0では、マウスキャプチャイベントの配布が多くなりました.これは様々なプラットフォームで、私たちのゲームのユーザー体験を豊かにすることができます.
以下のコードはマウス応答イベントの実現ステップを実行します.
    //      
    _mouseListener = EventListenerMouse::create();

    //       
    _mouseListener->onMouseMove = [=](Event *event){
    EventMouse* e = (EventMouse*)event;
    string str = "Mouse Down detected, Key: ";
    str += tostr(e->getMouseButton());
    // ...
};
    _mouseListener->onMouseUp = [=](Event *event){...};
    _mouseListener->onMouseDown = [=](Event *event){...};
    _mouseListener->onMouseScroll = [=](Event *event){...};
    //         
    _eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this);
イベントをカスタマイズ
以上はシステムが持っているイベントの種類で、イベントはシステム内部で自動的に触発され、タッチスクリーン、キーボード応答などの他に、カスタムイベントが提供されています.簡単に言えば、システムが自動的に触発するのではなく、人為的な干渉です.
    _listener = EventListenerCustom::create("game_custom_event1", [=](EventCustom* event){
        std::string str("Custom event 1 received, ");
        char* buf = static_cast<char*>(event->getUserData());
        str += buf;
        str += " times";
        statusLabel->setString(str.c_str());
    });

    _eventDispatcher->addEventListenerWithFixedPriority(_listener, 1);
以上で「カスタムイベントモニター」を定義し、関連ロジックを実現し、イベント配信器に追加しました.上のカスタムイベントは以下のコードでトリガされます.
    static int count = 0;
    ++count;
    char* buf = new char[10];
    sprintf(buf, "%d", count);
    EventCustom event("game_custom_event1");
    event.setUserData(buf);
    if(...)
    {
        _eventDispatcher->dispatchEvent(&event);
    }
    CC_SAFE_DELETE_ARRAY(buf);
Event Customを定義し、UserDataデータを設定し、手動で_を通過します.event Dispactch->dispatch Event(&event);このイベントを配布して、以前に実現されたロジックをトリガします.
加速度計事件
タッチに加えて、モバイルデバイスの重要な入力源は、デバイスの方向ですので、ほとんどのデバイスは、デバイスが静止しているときや均等速度の動きを測定するための加速度計を備えています.
重力誘導は移動装置からの加速度計で、通常はX,Y,Zの3方向の加速度誘導をサポートしているので、三方向加速度計とも呼ばれています.実用的な応用では、3方向の強度の大きさに応じて携帯電話の傾きの角度や方向を計算することができる.
3.0において、新しいイベントメカニズムの下で、加速度計モニタEventListenerAccellerationを作成することによって、その静的create方法にはAccellerationのパラメータが必要です.Accellerationは、加速度計で得られた3方向の加速度を含むクラスです.関連コードは以下の通りです.
class Acceleration
{
public:
    double x;
    double y;
    double z;

    double timestamp;

    Acceleration(): x(0), y(0), z(0), timestamp(0) {}
};
このクラスの各方向の加速度の大きさはすべて重力加速度の大きさです.
加速度計イベントモニターを使用する前に、このハードウェアデバイスを有効にする必要があります.
Device:setAccellerererEnable(true);
その後、対応するモニターを作成し、コールバック関数を作成する際に、lamda表現を使って匿名関数を作成することができます.既存の関数論理を結びつけることもできます.
    auto listener = EventListenerAcceleration::create([=](Acceleration* acc, Event* event){
        //     
    });
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);