サイトのトップへ戻る

Cocos2d-x ドキュメント 日本語訳

サイト内検索

イベントディスパッチャー



イベントディスパッチメカニズムとは何ですか?

イベントディスパッチ とはユーザーイベントに応答するためのメカニズムです。

基本原理:

  • イベントリスナー内にイベント処理コードを記述する。
  • イベントディスパッチャーがユーザーイベントのリスナーに通知する。
  • Event オブジェクトにはイベントに関する情報が保持されている。


五つの種類のイベントリスナー

EventListenerTouch - タッチイベントに応答する

EventListenerKeyboard - キーボードイベントに応答する

EventListenerAcceleration - 加速度センサーのイベントに応答する

EventListenMouse - マウスイベントに応答する

EventListenerCustom - カスタムイベントに応答する



FixedPriority vs SceneGraphPriority

イベントディスパッチャー は優先順位を基にしてどのリスナーに最初にイベントを通知するかを決定します。

固定優先度 は整数値です。優先度値の低いイベントリスナーは、優先度値の高いイベントリスナーよりも前に処理イベントを取得します。

Scene Graph PriorityNodeへのポインターです。 高いz-order 値の Nodes(前面に表示されるノード)を持つイベントリスナーは、引くz-order 値の Nodes(広報に表示されるノード)を持つイベントリスナーよりも前にイベントを受け取ります。 これにより、あなたの期待通り、例えばタッチイベントが前から後ろの順番でイベントを取得することが保証されます。

第2章を覚えていますか? Where we talked about the scene graph and we talked about this diagram?

Well, when use Scene Graph Priority you are actually walking this above tree backwards... I, H, G, F, E, D, C, B, A. If an event is triggered, H would take a look and either swallow it (more on this below) or let is pass through to _I. Same thing, I will either consume it or let is pass through to G and so on until the event either swallowed__ it or does not get answered.



タッチイベント

タッチイベント は携帯ゲームにおいて最も重要なイベントです。 簡単に使用できて多くの機能を提供します。 それでは、タッチイベントがどういったものなのか良く知ることにしましょう。 あなたが携帯端末の画面をタッチした時、タッチイベントはタッチを受け取り、どこをタッチしたのか見て、何がタッチされたのかを判別します。 それからタッチに対して応答します。 It is possible that what you touched might not be the responding object but perhaps something underneath it. 通常はタッチイベントに優先度が割り当てられており、最も優先度の高いイベントが応答します。 以下が、基本的なタッチイベントリスナーを作成する方法です:

//  Create a "one by one" touch event listener
// (processes one touch at a time)
auto listener1 = EventListenerTouchOneByOne::create();

// trigger when you push down
listener1->onTouchBegan = [](Touch* touch, Event* event){
    // your code
    return true; // if you are consuming it
};

// trigger when moving touch
listener1->onTouchMoved = [](Touch* touch, Event* event){
    // your code
};

// trigger when you let up
listener1->onTouchEnded = [=](Touch* touch, Event* event){
    // your code
};

// Add listener
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);

ご覧のように、タッチイベントリスナーを使用する時に操作できるイベントは三つあります。 これらのイベントはそれぞれ呼び出されるタイミングが異なります。

onTouchBegan は指が押された時に発生します。

onTouchMoved は指を押したままオブジェクトを移動させた場合に発生します。

onTouchEnded はタッチした指が離された時に発生します。



イベントを飲み込む

リスナーを用意してオブジェクトにイベントを取得させたい場合、 そのオブジェクトではイベントを飲み込む必要があります。 別の言い方をすれば、優先度の高いオブジェクトで取得したイベントを優先度の低い他のオブジェクトへ渡さないようにするため、 イベントを排他取得します 。 これは簡単に行えます。

// When "swallow touches" is true, then returning 'true' from the
// onTouchBegan method will "swallow" the touch event, preventing
// other listeners from using it.
listener1->setSwallowTouches(true);

// you should also return true in onTouchBegan()

listener1->onTouchBegan = [](Touch* touch, Event* event){
    // your code

    return true;
};


キーボードイベントを作成する

デスクトップゲームの場合、便利なキーボードメカニズムの使い方を知りたいことでしょう。 Cocos2d-x ではキーボードイベントをサポートしています。 前述のタッチイベントのように、キーボードイベントは簡単に作成できます。

// creating a keyboard event listener
auto listener = EventListenerKeyboard::create();
listener->onKeyPressed = CC_CALLBACK_2(KeyboardTest::onKeyPressed, this);
listener->onKeyReleased = CC_CALLBACK_2(KeyboardTest::onKeyReleased, this);

_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

// Implementation of the keyboard event callback function prototype
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);
}


加速度センサーイベントを作成する

いくつかの携帯端末では加速度センサーが搭載されています。 加速度センサーとは、方向の変化だけでなく重力も計測するセンサーです。 A use case would be needing to move your phone back and forth, perhaps to simulate a balancing act. Cocos2d-x ではこれらのイベントもサポートしており、イベントの作成も簡単にできます。 加速度センサーイベントを使用する前に、端末上で加速度センサーを有効にする必要があります。:

Device::setAccelerometerEnabled(true);
// creating an accelerometer event
auto listener = EventListenerAcceleration::create(CC_CALLBACK_2(
AccelerometerTest::onAcceleration, this));

_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

// Implementation of the accelerometer callback function prototype
void AccelerometerTest::onAcceleration(Acceleration* acc, Event* event)
{
    //  Processing logic here
}


マウスイベントを作成する

これまでと同じ様に、 Cocos2d-x はマウスイベントをサポートしています。

_mouseListener = EventListenerMouse::create();
_mouseListener->onMouseMove = CC_CALLBACK_1(MouseTest::onMouseMove, this);
_mouseListener->onMouseUp = CC_CALLBACK_1(MouseTest::onMouseUp, this);
_mouseListener->onMouseDown = CC_CALLBACK_1(MouseTest::onMouseDown, this);
_mouseListener->onMouseScroll = CC_CALLBACK_1(MouseTest::onMouseScroll, this);

_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this);

void MouseTest::onMouseDown(Event *event)
{
    // to illustrate the event....
    EventMouse* e = (EventMouse*)event;
    string str = "Mouse Down detected, Key: ";
    str += tostr(e->getMouseButton());
}

void MouseTest::onMouseUp(Event *event)
{
    // to illustrate the event....
    EventMouse* e = (EventMouse*)event;
    string str = "Mouse Up detected, Key: ";
    str += tostr(e->getMouseButton());
}

void MouseTest::onMouseMove(Event *event)
{
    // to illustrate the event....
    EventMouse* e = (EventMouse*)event;
    string str = "MousePosition X:";
    str = str + tostr(e->getCursorX()) + " Y:" + tostr(e->getCursorY());
}

void MouseTest::onMouseScroll(Event *event)
{
    // to illustrate the event....
    EventMouse* e = (EventMouse*)event;
    string str = "Mouse Scroll detected, X: ";
    str = str + tostr(e->getScrollX()) + " Y: " + tostr(e->getScrollY());
}


カスタムイベントを作成する

前述のタイプのイベントはシステムによって定義されており、それらのイベント (スクリーンタッチ、キーボード応答などのような) はシステムが自動的に発生させます。 それらに加えて、以下のようにして、システムではなくあなたが記述したコードによって発生させる独自のイベントを作成することができます。:

_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[10];
sprintf(buf, "%d", count);

EventCustom event("game_custom_event1");
event.setUserData(buf);

_eventDispatcher->dispatchEvent(&event);

上記の例では EventCustom オブジェクトを作成して、その UserDataを設定しています。 それから_eventDispatcher->dispatchEvent(&event)を使って手動でそれをディスパッチします。 これで以前に定義したイベントハンドラを発生させます。 このハンドラーは即座に呼び出され、ローカルスタック変数は UserDataとして使用できます。



ディスパッチャーを使ってイベントを登録する

イベントディスパッチャーを使ったイベントの登録は簡単にできます。 例として前述のタッチイベントリスナーを使用します。:

// Add listener
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1,
sprite1);

オブジェクトごとに一つのタッチイベントしか登録できないことに注意してください。 同じリスナーを複数のオブジェクトに登録する必要がある場合は、clone()を使う必要があります。

// Add listener
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1,
sprite1);

// Add the same listener to multiple objects.
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(),
 sprite2);

_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(),
 sprite3);


ディスパッチャーからイベントを削除する

追加されたリスナーは以下のメソッドで削除できます:

_eventDispatcher->removeEventListener(listener);

Although they may seem special, built-in Node objects use the event dispatcher in the same way we have talked out. Makes sense, right? 例としてMenu を見てみましょう。 MenuItems の実装された Menuがある場合、あなたがメニュー項目をクリックするとイベントをディスパッチしています。 内蔵 Node オブジェクトのremoveEventListener()を実行してイベントを削除することもできます。.