cocos2d-x タッチイベント取得

概要

  • タッチイベントを取得してゲーム中で使用する

ブランチ「develop/multi-scene-stack」をベースにする

  • 前回サンプルに追加実装した

タッチイベントコールバックをオーバーライド

  • cocos2d-xのクラスリファレンスを見るとタッチイベント用関数の仮想関数があるのでそれをアプリ用ヘッダでも宣言する
    void registerWithTouchDispatcher();
    bool ccTouchBegan( cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent );
    void ccTouchEnded( cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent );

タッチイベント実装

  • cpp側でオーバーライドした関数の実装を行う
    • http://dummyimage.com/ で画像つくってボタンを押したら画像がかわるようにする
    • CCSpriteのオブジェクトをメンバ変数で保持してるようにしているが省略
bool Title::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
    this->mSprite->initWithFile("background_touch_began.png");
    
    return true;
}

void Title::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
    this->mSprite->initWithFile("background_touch_end.png");
}

タッチイベントをとるオブジェクトの設定

void Title::registerWithTouchDispatcher()
{
    //CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-129,true);
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-127,true);
}

タッチイベントの有効化

  • デフォルトでも有効かもしれないが一応initの中で呼んどく
    // enable touch event
    this->setTouchEnabled(true);

動かす

f:id:kambayashi:20120820003851p:plainf:id:kambayashi:20120820003852p:plain

cocos2d-x 別シーンに行って元のシーンに戻る

概要

  • 前回のサンプルでは切り替えたら前のシーンには戻れなかったが、ポップアップメニューや設定画面など、完了したら元の画面に戻りたい画面を作る

scene切り替え処理を変更する

  • TitleSceneのreplaceSceneは完全にシーンを置き換える処理だったが、pushSceneにするとシーンのスタックに積まれる

TitleScene.cpp

void Title::menuChangeScene(CCObject *pSender)
{
    //CCDirector::sharedDirector()->replaceScene( HelloWorld::scene());
    CCDirector::sharedDirector()->pushScene(HelloWorld::scene());
}

前のシーンに戻る

  • 子として作ったHelloWorldから前のTitleSceneに戻る処理を作る
    • とりあえず終了ボタンを押した時の処理を戻る機能にして確認してみる

HelloWorld.cpp

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    /*
    CCDirector::sharedDirector()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
     */
    CCDirector::sharedDirector()->popScene();
}

前のシーンに戻るボタンを作る

f:id:kambayashi:20120818184526p:plain

cocos2d-xでシーンを切り替える

概要

  • タイトル、ゲームメニュー、ゲームのように複数シーンの時の切り替え処理を作る

シーンクラス追加

  • 新規でシーンクラスを作る
    • メニューと選択物は下記画像参照

f:id:kambayashi:20120818153311p:plainf:id:kambayashi:20120818153320p:plain

背景画像用意

f:id:kambayashi:20120818160001p:plain

  • TitleSceneで読み込んでる背景画像名を変更する

TitleScene.cpp

    // add "HelloWorld" splash screen"
    CCSprite* pSprite = CCSprite::create("title_back.png");

起動時のシーンをタイトルシーンにする

  • AppDelegate.cppのrunWithSceneの引数をTItleSceneのオブジェクトにする

AppDelegate.cpp

    // create a scene. it's an autorelease object
    CCScene *pScene = Title::scene();
  • とりあえずここまでで動かす

f:id:kambayashi:20120818160509p:plain

タイトルシーンから次のシーンに行くボタンをつける

  • とりあえずなんかボタン押したらcocos2d-xの画面が出るようにする
    • ボタン作成とコールバックはHelloWorldから持ってくる

TitleScene.h

    // a selector callback
    void menuChangeScene(CCObject* pSender);

TitleScene.cpp:ボタン作成

    /////////////////////////////
    // 2. add a menu item with change scene
    CCMenuItemImage *pChangeSceneItem = CCMenuItemImage::create(
                                                                "CloseNormal.png",
                                                                "CloseSelected.png",
                                                                this,
                                                                menu_selector(Title::menuChangeScene) );
    pChangeSceneItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );
    
    // create menu, it's an autorelease object
    CCMenu* pMenu = CCMenu::create(pChangeSceneItem, NULL);
    pMenu->setPosition( CCPointZero );
    this->addChild(pMenu, 1);

TitleScene.cpp:ボタンのコールバック

void Title::menuChangeScene(CCObject *pSender)
{
    CCDirector::sharedDirector()->replaceScene( HelloWorld::scene());
}

動かす

  • 最初にタイトルが出てボタンを押すとcocos2d-xのマスコットの画面が出る

f:id:kambayashi:20120818162747p:plainf:id:kambayashi:20120818162751p:plain

cocos2d-xで画像を動かす

追記

画像配置コード確認

  • 今までのサンプルでも参考にしているHelloWorldの全画面に出ている画像をどう出しているか確認する
  • コードは前回ボタンを追加したコードにそのまま追加。なのでボタン2つでてる
    // add "HelloWorld" splash screen"
    CCSprite* pSprite = CCSprite::create("HelloWorld.png");

    // position the sprite on the center of the screen
    pSprite->setPosition( ccp(size.width/2, size.height/2) );

    // add the sprite as a child to this layer
    this->addChild(pSprite, 0);

左右に揺らしてみる

  • 正弦の値を使って揺らす

追加するメンバ

  • ひと揺れの中のフレーム番号(ループ変数)
  • 動かす画像オブジェクト
  • 定期的に呼び出される関数
class HelloWorld : public cocos2d::CCLayer
{
private:
    cocos2d::CCLabelTTF *mLabel; // ボタンを押したときにテキストを変更するラベル
    int mLoopCount; // ひと揺れの中のフレーム番号
    cocos2d::CCSprite *mSprite; // 動かす画像オブジェクト
    
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();
    
    // there's no 'id' in cpp, so we recommand to return the exactly class pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
    void menuCloseCallback(CCObject* pSender);
    
    // new callback function
    void menuTextChangeCallback(CCObject *pSender);

    // move sprite logic
    void gameLogic();
    
    // implement the "static node()" method manually
    LAYER_CREATE_FUNC(HelloWorld);
};

画像オブジェクト保存

    // add "HelloWorld" splash screen"
    CCSprite* pSprite = CCSprite::create("HelloWorld.png");
    this->mSprite = pSprite; // 画像オブジェクトを保存

毎フレーム座標更新

    this->schedule( schedule_selector(HelloWorld::gameLogic), 1.0 / 60.0 );
    
    return true;
}
  • 画像移動処理実装
    • 久しぶりに書いたら三角関数忘れてたのでコード汚いけどこんな感じ
void HelloWorld::gameLogic()
{
    float x = 0;
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    const float PI = 3.1415f;
    int max_loop_count = 60 * 1;
    float cos_value = cosf(PI * ((float)this->mLoopCount++ / (float)max_loop_count));
    x = (float)size.width * cos_value;
    
    if( this->mLoopCount > (max_loop_count * 2) )
    {
        this->mLoopCount = 0;
    }
    
    this->mSprite->setPosition( ccp( x + size.width / 2, size.height / 2) );
    
}

画面

  • 静止画だけど左右に揺れてる

f:id:kambayashi:20120729154448p:plain

cocos2d-xでボタンを作る

ボタン機能を見てみる

  • 付属しているサンプルをもとにUIのボタンを追加してみる。
  • HelloWorld.cppの中を見るとこんな感じでボタンを作っている。
    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        this,
                                        menu_selector(HelloWorld::menuCloseCallback) );
    pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );

画面中の右下の丸いのがこのボタンで押すとmenuCloseCallbackが呼ばれてアプリが終了する。
f:id:kambayashi:20120729135015p:plain

このボタンの上に表示されるようにボタンを追加してみる。

コード追加

  • 元のボタン作成コードのすぐ下で変数名、コールバック名、座標をかえたコードを入れる。
  • CCMenuのオブジェクトを作ったあとにaddChildでボタンをメニューに追加する。
  • CCLabelTTFで作成しているテキストラベルはあとで変更できるようにメンバ変数として保存する
  • まだこの段階ではコールバック関数がなくてエラーで動かない
    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        this,
                                        menu_selector(HelloWorld::menuCloseCallback) );
    pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );

    CCMenuItemImage *pTextChangeItem = CCMenuItemImage::create(
                                                          "CloseNormal.png",
                                                          "CloseSelected.png",
                                                          this,
                                                          menu_selector(HelloWorld::menuTextChangeCallback) );
    pTextChangeItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 40) );
    
    // create menu, it's an autorelease object
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
    pMenu->addChild(pTextChangeItem, 1);
    pMenu->setPosition( CCPointZero );
    this->addChild(pMenu, 1);

    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label
    CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Thonburi", 34);
    this->mLabel = pLabel;

ヘッダ編集

  • ラベルを保存する変数をメンバに追加
  • コールバックで呼ばれる関数を追加
class HelloWorld : public cocos2d::CCLayer
{
private:
    cocos2d::CCLabelTTF *mLabel; // ボタンを押したときにテキストを変更するラベル
    
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommand to return the exactly class pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
    void menuCloseCallback(CCObject* pSender);
    
    // new callback function
    void menuTextChageCallback(CCObject *pSender);

    // implement the "static node()" method manually
    LAYER_CREATE_FUNC(HelloWorld);
};

コールバック関数の実装追加

  • cppにもどりコールバック関数を実装する
void HelloWorld::menuTextChangeCallback(CCObject* pSender)
{
    this->mLabel->setString("Pressed");
}

画面

  • ボタンが表示されて押すと画面上部のテキストが変わった

f:id:kambayashi:20120729142216p:plain