翻訳者から
良い一日! この記事は、Cocos2d-xエンジンのドキュメントの翻訳です。
前のパートでは、エンジンの主なコンポーネントのほとんどをすでに調べました。
スプライト
アクション
UIコンポーネント
シーンなど
本格的なゲームを作成する余地はほとんどありません。 つまり、ゲームプレイ自体を提供することです。 このため、Cocos2d-xにはイベントディスパッチャーがあります。
イベントディスパッチャ
EventDispatchエンジンとは何ですか? EventDispatchは、ユーザーイベントに応答するためのメカニズムです。
基本 :
- イベントリスナーは、イベント処理コードをカプセル化します。
- イベントマネージャーは、カスタムイベントのリスナーに通知します。
- イベントオブジェクトには、イベントに関する情報が含まれています。
5種類のイベントリスナー
EventListenerTouch-タッチスクリーンのタッチに反応する
EventListenerKeyboard-キーストロークに応答します
EventListenerAcceleration-加速度計イベントに応答します
EventListenMouse-マウスイベントに反応します
EventListenerCustom-カスタムイベントに応答します
FixedPriorityとSceneGraphPriority
EventDispatcherは優先順位を使用して、最初にイベントを受け取るリスナーを決定します。
固定優先順位は整数値を表します。 優先度の低いイベントリスナーは、優先度の高いリスナーよりも早くイベントを受信して処理します。
シーングラフの優先度は、Nodeオブジェクトへのポインターです。 ノードのzオーダー値が高い(上に描かれている)イベントリスナーは、ノードのzオーダー値が低い(下に描かれている)リスナーの前にイベントを受け取ります。 これにより、予想どおり、タッチイベントがフロント要素を確実に取得します。
シーングラフを覚えていますか? このチャートについていつ話しましたか?
Scene Graph Priorityを使用する場合、実際にはこのツリーを反対方向に移動します... I 、 H 、 G 、 F 、 E 、 D 、 C 、 B 、 A イベントが発生した場合、 Hはこれに気づき、それを吸収するか(詳細は以下)、またはIにスキップします。 Iと同じことで、彼はアクションを消費するか、 Gまでさらにスキップします。
タッチイベント
タッチイベントは、モバイルゲームで最も重要なイベントです。 作成が簡単で、柔軟な機能を提供します。 タッチイベントとは何かを明確にしましょう。 モバイルデバイスの画面をタッチすると、タッチを感知し、タッチした場所を見て、クリックしたものを決定します。 次に、答えが得られます。 おそらく、アクティブなオブジェクトではなく、その下の何かに触れたのでしょう。 通常、タッチイベントには優先順位が与えられ、最も優先順位の高いイベントが応答します。
基本的なタッチイベントリスナーを作成する方法:
// "" // ( ) auto listener1 = EventListenerTouchOneByOne::create(); // listener1->onTouchBegan = [](Touch* touch, Event* event){ // return true; // }; // listener1->onTouchMoved = [](Touch* touch, Event* event){ // }; // listener1->onTouchEnded = [=](Touch* touch, Event* event){ // }; // _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
お気づきかもしれませんが、タッチのリスナーに使用できる3つのアクションがあります。 それらのそれぞれは、特定の条件下で呼び出されます。
onTouchBegan-押されるとトリガーされます。
onTouchMoved-タッチが移動するとトリガーされます。
onTouchEnded-リリースされるとトリガーします。
イベント吸収
リスナーがあり、オブジェクトが送信されたイベントを受け入れるようにするには、それを吸収する必要があります。 つまり、優先度の低い他のオブジェクトに移動しないように受け入れます。 実装は簡単です。
// "" , true // onTouchBegan , // listener1->setSwallowTouches(true); // true onTouchBegan() listener1->onTouchBegan = [](Touch* touch, Event* event){ // return true; };
キーボードイベントの作成
コンピュータゲームの場合、キーボードの使用が必要になる場合があります。 Cocos2d-xはキーボードをサポートしています。 タッチイベントと同様に、キーボードイベントは簡単に作成できます。
// auto listener = EventListenerKeyboard::create(); listener->onKeyPressed = CC_CALLBACK_2(KeyboardTest::onKeyPressed, this); listener->onKeyReleased = CC_CALLBACK_2(KeyboardTest::onKeyReleased, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); // callback 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); }
加速度計イベントの作成
一部のモバイルデバイスには、加速度計が搭載されています。 加速度計は、方向の変化と同様に過負荷を測定するセンサーです。 たとえば、電話を左右に動かしてバランスをとるアクションをシミュレートする必要がある場合に使用します。 Cocos2d-xはこれらのイベントもサポートしています。 加速度計イベントを使用する前に、それらを接続する必要があります。
Device::setAccelerometerEnabled(true);
// auto listener = EventListenerAcceleration::create(CC_CALLBACK_2( AccelerometerTest::onAcceleration, this)); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); // callback void AccelerometerTest::onAcceleration(Acceleration* acc, Event* event) { // Processing logic here }
マウスイベント作成
いつものように、Cococ2d-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) { // ... EventMouse* e = (EventMouse*)event; string str = "Mouse Down detected, Key: "; str += tostr(e->getMouseButton()); } void MouseTest::onMouseUp(Event *event) { // ... EventMouse* e = (EventMouse*)event; string str = "Mouse Up detected, Key: "; str += tostr(e->getMouseButton()); } void MouseTest::onMouseMove(Event *event) { // ... EventMouse* e = (EventMouse*)event; string str = "MousePosition X:"; str = str + tostr(e->getCursorX()) + " Y:" + tostr(e->getCursorY()); } void MouseTest::onMouseScroll(Event *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パラメーターとして使用できます。
ディスパッチャーでのイベントの登録
イベントの登録は簡単です。 タッチイベントリスナーの例を次に示します。
// _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
タッチイベントは1つのオブジェクトにのみ記録できることに注意することが重要です。 多くのオブジェクトに1つのリスナーを使用する必要がある場合は、これにclone()を使用する必要があります。
// _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1); // _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
ディスパッチャーからイベントを削除する
次の方法を使用して、ディスパッチャから削除できます。
_eventDispatcher->removeEventListener(listener);
特別なように見えるかもしれませんが、埋め込みNodeオブジェクトは、前述したのと同じメソッドでイベントディスパッチャーを使用します。 理にかなっていますよね? 例としてメニューをご覧ください。 メニュー項目をクリックすると、イベントが発生します。 ノードリスナーも簡単に削除できます。
翻訳者から
これで、エンジンの主要なコンポーネントが完成しました! 次の章はほとんどが非常に短く、それらのほとんどはたった1つのサンプルコードで取り上げられています。 一度に1つずつHabrにアップロードするのは不適切だと思います。 良心は私を許しません。 テーマを混在させることもお勧めできません。
それでも、純粋な翻訳ではなくなるレッスンを公開する予定です。 以下に、あなたが興味を持つものを見つけるための調査を残します。 また、コメントでオプションを提案することもできます。