Posted at

cocos2d-x v3.0でのタッチイベントの取り方

More than 5 years have passed since last update.

cocos2d-xはv2.0とv3.0でタッチイベントなどのイベント取得方法が変更になっています。これを踏まえて、サンプルを作成しながら解説します。

詳細は本家の記事を参照して下さい。

元のテンプレートのソースから出発して、コメントを追加しました。



  • HelloWorldクラスMoleSceneクラスに変更します。(必ずしも必要ではありません。)


  • HelloWorldScene.hMoleScene.hに、HelloWorldScene.cppMoleScene.cppに変更します。(必ずしも必要ではありません。)

  • ソースの可読性を上げるため、using句を追加します。(必ずしも必要ではありません。)

using namespace cocos2d;


  • cocos2d-xのサンプルにあるアイコン( Icon.png)をResourcesに追加します。

  • スプラッシュスクリーンの代わりに、アイコンを読み込むようにします。

  • スプライトと画面サイズがクラス全体で必要になりますので、メンバー変数にします。


MoleScene.h

#ifndef __MOLE_SCENE_H__

#define __MOLE_SCENE_H__

#include <CCGeometry.h>
#include "cocos2d.h"

using namespace cocos2d;

class MoleScene : public cocos2d::Layer
{
private:
// 画面サイズ
Size visibleSize;

// スプライト
cocos2d::Sprite* sprite;

public:
// C++にはIDがないので、クラスのインスタンスポインタを返すことを推奨する。
static Scene* createScene();

// initメソッドは、cocos2d-iphoneではIDを返すが、cocos2d-xではboolを返すという違いがある。
virtual bool init();
// a selector callback
// セレクタのコースバック
void menuCloseCallback(cocos2d::Ref* pSender);

// static create()関数のマニュアル実装
CREATE_FUNC(MoleScene);

// 次の位置を取得する。
Point* getNextPosition();
};

#endif
// __MOLE_SCENE_H__



MoleScene.cpp

/*

* Sample2: 簡単なもぐらたたき風サンプル。
*
* Copyright (C) Takao WADA.
*/

#include "MoleScene.h"

USING_NS_CC;

/**
* シーンを作成する。
*
* @return シーン
*/

Scene* MoleScene::createScene()
{
// 'scene' は autorelease オブジェクト
auto scene = Scene::create();

// 'layer' は autorelease オブジェクト
auto layer = MoleScene::create();

// レイヤーをシーンの子として追加する。
scene->addChild(layer);

// シーンを返す。
return scene;
}

/**
* インスタンスを初期化する。
*
* @return 成功したらtrue
*/

bool MoleScene::init()
{
//////////////////////////////
// 1. 親クラスを初期化する。
if ( !Layer::init() )
{
return false;
}

// 画面サイズを取得する。
visibleSize = Director::getInstance()->getVisibleSize();
// 画面の原点を取得する。
Point origin = Director::getInstance()->getVisibleOrigin();

/////////////////////////////
// 2. クリックすると終了する”X”画像付きのメニュー項目を追加する。これは変更してもよい。

// プログラムを終了する"close"アイコンを追加する。これは autorelease オブジェクト。
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(MoleScene::menuCloseCallback, this));

closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));

// メニューを作成する。これは autorelease オブジェクト。
auto menu = Menu::create(closeItem, NULL);
// メニューの位置を設定する。
menu->setPosition(Point::ZERO);
// メニューを子レイヤーとして追加する。
this->addChild(menu, 1);

/////////////////////////////
// 3. 独自のコードを追加する。
this->setTouchMode(Touch::DispatchMode::ONE_BY_ONE);

// ラベルを作成し、初期化する。
auto label = LabelTTF::create("whack a mole sample", "Arial", 24);

// 画面の中央にラベルを位置づける。
label->setPosition(Point(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));

// ラベルをレイヤーの子として追加する。
this->addChild(label, 1);

// cocosアイコンを追加する。
sprite = Sprite::create("Icon.png");

// スプライトを画面の中央に位置づける。
sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

// スプライトをレイヤーの子として追加する。
this->addChild(sprite, 0);

// シングルタッチイベントリスナーを作成する。
auto listener1 = EventListenerTouchOneByOne::create();
// スワロータッチモードにするとonTouchBeganメソッドはタッチイベントは他では使われない。
listener1->setSwallowTouches(true);

// onTouchBeganイベントコールバック関数実装のラムダ式の例
listener1->onTouchBegan = [](Touch* touch, Event* event) {
// event->getCurrentTarget() は、リスナーのsceneGraphPriorityの優先順に対象オブジェクトを返す。
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) {
// ターゲットを取得する。
// auto target = static_cast<Sprite*>(event->getCurrentTarget());
// ここに移動した場合の処理を書く。touch->getDelta()で移動量が取得できる。
};

// タッチイベントが終了した場合
listener1->onTouchEnded = [=](Touch* touch, Event* event) {
// ターゲットを取得する。
auto target = static_cast<Sprite*>(event->getCurrentTarget());
// ここに終了した場合の処理を書く。
log("sprite onTouchesEnded.. ");
// スプライトを画面の中央に位置づける。
sprite->setPosition(*getNextPosition());
// 不透明度を元に戻す。
target->setOpacity(255);
};

// イベントリスナーをスプライトに追加する。
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite);

return true;
}

/**
* メニューの"Close"が選択された場合のコールバック関数。
*
* @param pSender 送信元
*/

void MoleScene::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif

// ディレクタを終了する。
Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

/**
*
* 画面上のランダムな位置を取得する。
*
* @return 画面上のランダムな位置
*/

Point* MoleScene::getNextPosition()
{
// スプライトを新しい位置に変更する。
Point* point = new Point(random() % (int)visibleSize.width, random() % (int)visibleSize.height);

return point;
}