2015年

3月

17日

Cocos2d-x Ver 3.x スワイプによる画面遷移

Cocos2dx 3.x C++言語

スワイプに関しての「Cocos2d-xでジェスチャー取得」が掲載されていましたので画面遷移に流用してみました。このようにとっても扱い易いことが分かりましたので実用として取り上げています。
画面遷移用の2つのクラス + スワイプ用クラス(ジェスチャー)をそれぞれ作成し使用しています。


TopScene.h
TopScene.cpp
SecondScene.h
SecondScene.cpp
 スワイプ用クラス(ジェスチャー)

EventListenerGesture.h

EventListenerGesture.cpp


EventListenerGestureに関しては、「Cocos2d-xでジェスチャー取得」を参照願います。


 

サンプルの操作に関しては、上下左右にスワイプすれば次画面と戻る画面遷移しています。


スワイプ用(ジェスチャー)クラスを追加
EventListenerGesture.cpp

EventListenerGesture.h

 

Android.mkソースコード

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

$(call import-add-path,$(LOCAL_PATH)/../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos)

LOCAL_MODULE := cocos2dcpp_shared

LOCAL_MODULE_FILENAME := libcocos2dcpp

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \
                   ../../Classes/TopScene.cpp \
             ../../Classes/SecondScene.cpp \
             ../../Classes/EventListenerGesture.cpp

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes

LOCAL_STATIC_LIBRARIES := cocos2dx_static

include $(BUILD_SHARED_LIBRARY)

$(call import-module,.)

 

EventListenerGesture.hソースコード

#ifndef __SnowEdge__EventListenerGesture__

#define __SnowEdge__EventListenerGesture__


#include "cocos2d.h"


// 名前空間 #define USING_NS_CC using namespace cocos2d

USING_NS_CC;


class EventListenerGesture : public cocos2d::EventListenerTouchOneByOne

{

public:

    enum class SwipeDirection

    {

        NONE,

        UP,

        DOWN,

        LEFT,

        RIGHT

    };


    enum class GestureType

    {

        NONE,

        TAP,

        LONG_TAP,

        SWIPE

    };


    static EventListenerGesture* create();


    virtual ~EventListenerGesture();


    virtual EventListenerGesture* clone() override;

    virtual bool checkAvailable() override;


    void setLongTapThreshouldSeconds(const float& threshould);

    void setSwipeThreshouldDistance(const float& threshould);


    std::function<void(cocos2d::Vec2)> onTap;

    std::function<void(cocos2d::Vec2)> onLongTapBegan;

    std::function<void(cocos2d::Vec2)> onLongTapEnded;

    std::function<void(SwipeDirection)> onSwipe;


protected:

    EventListenerGesture();

    bool init();


private:

    using EventListenerTouchOneByOne::LISTENER_ID;

    using EventListenerTouchOneByOne::onTouchBegan;

    using EventListenerTouchOneByOne::onTouchMoved;

    using EventListenerTouchOneByOne::onTouchEnded;

    using EventListenerTouchOneByOne::onTouchCancelled;


    float _longTapThresholdSeconds;

    float _swipeThresholdDistance;


    std::chrono::system_clock::time_point _touchStartTime;

    std::chrono::system_clock::time_point _beforeTapEndTime;

    cocos2d::Vec2 _touchStartPos;

    cocos2d::Vec2 _touchNowPos;

    GestureType _gestureType;

    void _updateInTouch(float);


    friend class EventDispatcher;

    

    // create()を使えるようにしている。

    //CREATE_FUNC(EventListenerGesture);

};


#endif /* defined(__SnowEdge__EventListenerGesture__) */

 

EventListenerGesture.cppソースコード

#include "EventListenerGesture.h"


using namespace cocos2d;


constexpr float DefaultLongTapThresholdSeconds = 0.5f;

constexpr float DefaultSwipeThresholdDistance = 100.0f;


EventListenerGesture::EventListenerGesture()

: _longTapThresholdSeconds(DefaultLongTapThresholdSeconds)

, _swipeThresholdDistance(DefaultSwipeThresholdDistance)

, onTap(nullptr)

, onLongTapBegan(nullptr)

, onLongTapEnded(nullptr)

, onSwipe(nullptr)

, _gestureType(GestureType::NONE)

{

}


EventListenerGesture::~EventListenerGesture()

{

    CCLOGINFO("In the destructor of EventListenerGesture, %p", this);

}


bool EventListenerGesture::init()

{

    if (!EventListenerTouchOneByOne::init())

    {

        return false;

    }


    onTouchBegan = [this](Touch* touch, Event* event) -> bool

    {

        _touchStartTime = std::chrono::system_clock::now();

        _touchStartPos = touch->getLocation();

        _touchNowPos = touch->getLocation();


        Director::getInstance()->getScheduler()->schedule(schedule_selector(EventListenerGesture::_updateInTouch), this, 0.1f, false);

        return true;

    };


    onTouchCancelled = [](Touch* touch, Event* event){};


    onTouchMoved = [this](Touch* touch, Event* event)

    {

        if(_gestureType != GestureType::NONE)

            return;


        _touchNowPos = touch->getLocation();

        auto xDiff = _touchNowPos.x - _touchStartPos.x;

        auto xDiffAbs = abs(xDiff);

        auto yDiff = _touchNowPos.y - _touchStartPos.y;

        auto yDiffAbs = abs(yDiff);

        auto swipeDirection = SwipeDirection::NONE;


        if(xDiffAbs >= yDiffAbs)

        {

            if(xDiffAbs > _swipeThresholdDistance)

                swipeDirection = xDiff >= 0 ? SwipeDirection::RIGHT : SwipeDirection::LEFT;

        }

        else

        {

            if(yDiffAbs > _swipeThresholdDistance)

                swipeDirection = yDiff >= 0 ? SwipeDirection::UP : SwipeDirection::DOWN;

        }


        if(swipeDirection != SwipeDirection::NONE)

        {

            _gestureType = GestureType::SWIPE;

            if(onSwipe) onSwipe(swipeDirection);

        }

    };


    onTouchEnded = [this](Touch* touch, Event* event)

    {

        if(_gestureType == GestureType::NONE)

        {

            if(onTap) onTap(touch->getDelta());

        }

        else if(_gestureType == GestureType::LONG_TAP)

        {

            if(onLongTapEnded) onLongTapEnded(touch->getDelta());

        }


        Director::getInstance()->getScheduler()->

            unschedule(schedule_selector(EventListenerGesture::_updateInTouch), this);

        _gestureType = GestureType::NONE;

    };


    return true;

}


EventListenerGesture* EventListenerGesture::create()

{

    auto ret = new (std::nothrow) EventListenerGesture();

    if (ret && ret->init())

    {

        ret->autorelease();

    }

    else

    {

        CC_SAFE_DELETE(ret);

    }

    return ret;

}


void EventListenerGesture::setLongTapThreshouldSeconds(const float& threshould)

{

    if (threshould > 0)

    {

        _longTapThresholdSeconds = threshould;

    }

    else

    {

        CCLOGWARN("EventListenerGesture::LongTapThreshouldTime can set over 0.0f!");

    }

}


void EventListenerGesture::setSwipeThreshouldDistance(const float& threshould)

{

    if(threshould > 0)

    {

        _swipeThresholdDistance = threshould;

    }

    else

    {

        CCLOGWARN("EventListenerGesture::setSwipeThreshouldDistance can set over 0.0f!");

    }

}


bool EventListenerGesture::checkAvailable()

{

    if (onTouchBegan == nullptr)

    {

        CCASSERT(false, "Invalid EventListenerGesture!");

        return false;

    }


    return true;

}


EventListenerGesture* EventListenerGesture::clone()

{

    auto ret = new (std::nothrow) EventListenerGesture();

    if (ret && ret->init())

    {

        ret->autorelease();


        ret->onTap = onTap;

        ret->onLongTapBegan = onLongTapBegan;

        ret->onLongTapEnded = onLongTapEnded;

        ret->onSwipe = onSwipe;


        ret->_longTapThresholdSeconds = _longTapThresholdSeconds;

        ret->_swipeThresholdDistance = _swipeThresholdDistance;

    }

    else

    {

        CC_SAFE_DELETE(ret);

    }

    return ret;

}


void EventListenerGesture::_updateInTouch(float)

{

    if(_gestureType != GestureType::NONE)

    {

        Director::getInstance()->getScheduler()->

            unschedule(schedule_selector(EventListenerGesture::_updateInTouch), this);

        return;

    }


    std::chrono::duration<float> duration = std::chrono::system_clock::now() - _touchStartTime;

    if(duration.count() > _longTapThresholdSeconds)

    {

        _gestureType = GestureType::LONG_TAP;

        if (onLongTapBegan) onLongTapBegan(_touchNowPos);

    }

}


 

TopScene.hソースコード

#ifndef __Sprite__TopScene__

#define __Sprite__TopScene__


#include "cocos2d.h"


// 名前空間 #define USING_NS_CC using namespace cocos2d

USING_NS_CC;


class TopScene : public cocos2d::Layer

{

public:

    

    // コンストラクタ

    TopScene();

    // デストラクタ

    virtual ~TopScene();


    // 初期化のメソッド

    virtual bool init();

    

    static cocos2d::Scene* createScene();

    

    // create()を使えるようにしている。

    CREATE_FUNC(TopScene);


};


#endif /* defined(__Label__Top__) */

 

TopScene.cppソースコード

#include "TopScene.h"

#include "SecondScene.h"

// Swipe UP DOWN RIGHT LEFT

#include "EventListenerGesture.h"

//音をならすためにinclude

#include "SimpleAudioEngine.h"


// 名前空間 #define USING_NS_CC using namespace cocos2d

USING_NS_CC;


// _/_/_/ コンストラクタ プロパティー _/_/_/

TopScene::TopScene()

{

    

}


#pragma mark - デストラクタで解放 メモリーリークを防ぐ


// SecondScene デストラクタで解放 メモリーリークを防ぐ

TopScene::~TopScene()

{

    

}


Scene* TopScene::createScene()

{

    // 「シーン」は自動解放オブジェクトです

    auto scene = Scene::create();

    

    // 「レイアウト」は自動解放オブジェクトです

    auto layer = TopScene::create();

    

    // シーンに子としてレイヤーを追加

    scene->addChild(layer);

    

    // シーンを返す

    return scene;

}



// INIT」初期化

bool TopScene::init()

{

    if ( !Layer::init() )

    {

        return false;

    }

    

    // 画面の座標関係の詳しい説明はここ http://www.cocos2d-x.org/wiki/Coordinate_System

    // 画面サイズを取得

    Size winSize = Director::getInstance()->getVisibleSize();

    //マルチレゾリューション対応がどうとか

    Point origin = Director::getInstance()->getVisibleOrigin();

    

    // バックグランドカラー

    auto background = LayerColor::create(Color4B::WHITE,

                                         winSize.width,

                                         winSize.height);

    // バックグランドカラー 第2引数は表示順

    this->addChild(background, 0);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // タイトルを設置

    auto lbl_title = Label::createWithSystemFont("Top", "HiraKakuProN-W6", 100);

    lbl_title->setPosition(Point(origin.x + winSize.width/2,

                                 origin.y + winSize.height

                                 -lbl_title->getContentSize().height));

    lbl_title->setColor(Color3B::BLUE);

    // ラベルタイトルを追加

    this->addChild(lbl_title,1);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // 矢印画像Spriteクラスを初期化しています。

    auto sprite = Sprite::create("Arrow.png");

    // 位置を設定

    sprite->setPosition(Point(winSize.width /2 ,winSize.height/2 - 50));

    // 画面に追加をしています。

    this->addChild(sprite);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // ラベルを作成し、初期化する。

    // Label::createWithSystemFont("文字列", "フォントの種類", 文字サイズ);

    auto label1 = Label::createWithSystemFont

                        ("上下左右スワイプで次画面", "HiraKakuProN-W6", 50);

    // ラベルの色:ホワイト

    label1->setColor(Color3B::ORANGE);

    //画面の中央に表示

    label1->setPosition(Point(winSize.width/2, winSize.height/2 - 250));

    // Layerにラベルを追加

    this->addChild(label1);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // Swipe UP DOWN RIGHT LEFT

    auto listener = EventListenerGesture::create();

    

    //if dont set this value is 0.5f.

    listener->setLongTapThreshouldSeconds(1.0f);

    //if dont set this value is 100.0f.

    listener->setSwipeThreshouldDistance(150.0f);

    listener->onTap = [](Vec2 vec2){log("onTap called.");};

    listener->onLongTapBegan = [](Vec2 vec2){log("onLongTapBegan called.");};

    listener->onLongTapEnded = [](Vec2 vec2){log("onLongTapEnded called.");};

    listener->onSwipe = [](EventListenerGesture::SwipeDirection direction)

    {

        

        if (direction == EventListenerGesture::SwipeDirection::UP) {

            log("Swipe UP.");

            CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

            Scene *pScene = SecondScene::createScene();

            Director::getInstance()->replaceScene(pScene);

        }

        

        if (direction == EventListenerGesture::SwipeDirection::DOWN) {

            log("Swipe DOWN.");

            CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

            Scene *pScene = SecondScene::createScene();

            Director::getInstance()->replaceScene(pScene);

        }

        

        if (direction == EventListenerGesture::SwipeDirection::RIGHT) {

            log("Swipe RIGHT.");

            CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

            Scene *pScene = SecondScene::createScene();

            Director::getInstance()->replaceScene(pScene);

        }

        

        if (direction == EventListenerGesture::SwipeDirection::LEFT) {

            log("Swipe LEFT.");

            CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

            Scene *pScene = SecondScene::createScene();

            Director::getInstance()->replaceScene(pScene);

        }

        

    };

    

    getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    

    return true;

}

 

SecondScene.hソースコード


#ifndef __Screen__SecondScene__

#define __Screen__SecondScene__


#include "cocos2d.h"


USING_NS_CC;


class SecondScene : public cocos2d::Layer

{

public:

    static Scene *createScene();

    virtual bool init();

    CREATE_FUNC(SecondScene);

    

    void makeBackground();

    

    // スタートボタン押下時の処理宣言 戻る Object → Ref に変更

    void pushBack(cocos2d::Ref *pSender);

};


 

#endif /* defined(__Screen__SecondScene__) */


 

SecondScene.cppソースコード

#include "SecondScene.h"

#include "TopScene.h"

// Swipe UP DOWN RIGHT LEFT

#include "EventListenerGesture.h"

//音をならすためにinclude

#include "SimpleAudioEngine.h"


// 名前空間 #define USING_NS_CC using namespace cocos2d

USING_NS_CC;


// _/_/_/ コンストラクタ プロパティー _/_/_/

SecondScene::SecondScene()

{

    

}


#pragma mark - デストラクタで解放 メモリーリークを防ぐ


// SecondScene デストラクタで解放 メモリーリークを防ぐ

SecondScene::~SecondScene()

{

    

}


Scene* SecondScene::createScene()

{

    // 「シーン」は自動解放オブジェクトです

    auto scene = Scene::create();

    

    // 「レイアウト」は自動解放オブジェクトです

    auto layer = SecondScene::create();

    

    // シーンに子としてレイヤーを追加

    scene->addChild(layer);

    

    // シーンを返す

    return scene;

}


// INIT」初期化

bool SecondScene::init()

{

    if ( !Layer::init() )

    {

        return false;

    }

    

    //画面の座標関係の詳しい説明はここ http://www.cocos2d-x.org/wiki/Coordinate_System

    //画面サイズを取得

    Size winSize = Director::getInstance()->getVisibleSize();

    Point origin = Director::getInstance()->getVisibleOrigin();  //マルチレゾリューション対応がどうとか

    

    // バックグランドカラー

    auto background = LayerColor::create(Color4B::GREEN,

                                         winSize.width,

                                         winSize.height);

    //バックグランドカラー追加 第2引数は表示順

    this->addChild(background, 0);


    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    //タイトルを設置

    auto lbl_title = Label::createWithSystemFont("Second", "HiraKakuProN-W6", 100);

    lbl_title->setPosition(Point(origin.x + winSize.width/2,

                                 origin.y + winSize.height

                                 -lbl_title->getContentSize().height));

    this->addChild(lbl_title,1);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // 矢印画像Spriteクラスを初期化しています。

    auto sprite = Sprite::create("Arrow.png");

    // 位置を設定

    sprite->setPosition(Point(winSize.width /2 ,winSize.height/2 - 50));

    // 画面に追加をしています。

    this->addChild(sprite);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // ラベルを作成し、初期化する。

    // Label::createWithSystemFont("文字列", "フォントの種類", 文字サイズ);

    auto label1 = Label::createWithSystemFont

                  ("上下左右スワイプでTop画面に戻る", "HiraKakuProN-W6", 50);

    // ラベルの色:ホワイト

    label1->setColor(Color3B::ORANGE);

    //画面の中央に表示

    label1->setPosition(Point(winSize.width/2, winSize.height/2 - 250));

    // Layerにラベルを追加

    this->addChild(label1);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // Swipe UP DOWN RIGHT LEFT

    auto listener = EventListenerGesture::create();

    

    //if dont set this value is 0.5f.

    listener->setLongTapThreshouldSeconds(1.0f);

    //if dont set this value is 100.0f.

    listener->setSwipeThreshouldDistance(150.0f);

    listener->onTap = [](Vec2 vec2){log("onTap called.");};

    listener->onLongTapBegan = [](Vec2 vec2){log("onLongTapBegan called.");};

    listener->onLongTapEnded = [](Vec2 vec2){log("onLongTapEnded called.");};

    listener->onSwipe = [](EventListenerGesture::SwipeDirection direction)

    {

        

        if (direction == EventListenerGesture::SwipeDirection::UP) {

            log("Swipe UP.");

            CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

            Scene *pScene = TopScene::createScene();

            Director::getInstance()->replaceScene(pScene);

        }

        

        if (direction == EventListenerGesture::SwipeDirection::DOWN) {

            log("Swipe DOWN.");

            CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

            Scene *pScene = TopScene::createScene();

            Director::getInstance()->replaceScene(pScene);

        }

        

        if (direction == EventListenerGesture::SwipeDirection::RIGHT) {

            log("Swipe RIGHT.");

            CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

            Scene *pScene = TopScene::createScene();

            Director::getInstance()->replaceScene(pScene);

        }

        

        if (direction == EventListenerGesture::SwipeDirection::LEFT) {

            log("Swipe LEFT.");

            CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

            Scene *pScene = TopScene::createScene();

            Director::getInstance()->replaceScene(pScene);

        }

        

    };

    

    getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/


    return true;

}


GitHub Swipe

 

目 次