LoginSignup
35
35

More than 5 years have passed since last update.

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

Posted at

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;
}
35
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
35