cocos2d-xのコーディングしてて思ったこと。(ガベコレの話)

C#やJavaにはガベージコレクションと言って、使用しなくなったオブジェクトを自動的に解放してくれる仕組みがありまして、

だからnewしたオブジェクトの使用後を意識しなくても使用できるんですが、

C++にはそんな機能は無く、

newしたオブジェクトは明示的にdeleteしないと、そのオブジェクトは消えません。

で、cocos2d-xはspriteなどを作成するときにnewを使用せずにcreate()メソッドを使用しているんです。

そして、サンプルを見る限りではdeleteは行っていない。

これはcocos2d-xのプラットフォームの中で独自にガベージコレクション的な動きをしています。

ただ、cocos2d-xのガベコレとC#やJavaのガベコレとは少しロジックが異なるようです。

詳しい内容はこの記事を見て欲しく

http://furicotech.blogspot.com/2015/03/memory-management-in-cocos2d-x.html

まぁ、この内容をまとめると、

cocos2d-xのspriteなどのオブジェクトは1回使い切り。(その都度createしなければならない。)

これ、自分もコーディングしててハマりました。

あると思っていたspriteのポインタが無効なポインタになっていた、と言うことが多々ありました。

C#と同じ感覚で使用することができないんですね。

なので、クラス設計をどうするか、少し悩んでいます。

spriteなどの部品はシーンクラスの中で全部処理させた方が良いかもしれない。

【cocos2d-x】タッチした場所にエフェクトを入れる

よくスマホゲームって、タッチした場所にアニメーションを入れてエフェクトかけてるじゃないですか。

あれを実装して見たいと思います。

今回もフリー素材のぴぽや倉庫さんから素材を拝借しました。

すでに、タッチ処理のやり方もアニメーションのやり方も知っているので、これを組み合わせます。

コードはこうなりました。

bool HelloWorld::init()
{

  中略

    auto listener1 = EventListenerTouchOneByOne::create();
    listener1->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);

    return true;
}

bool HelloWorld::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event)
{
    auto anime = Sprite::create("pipo-btleffect007.png");
    if (anime == nullptr)
    {
        problemLoading("'pipo-btleffect007.png'");
    }
    else
    {
        this->addChild(anime, 0);
    }
    float frameHeight = anime->getContentSize().height;
    float frameWidth = anime->getContentSize().width / 14.0;
    Vector<SpriteFrame*> animFrames;
    animFrames.reserve(14);
    for(int i = 0; i < 14; i++) {
        animFrames.pushBack(SpriteFrame::create("pipo-btleffect007.png", Rect(frameWidth * i,0,frameHeight,frameWidth)));
    }
    Animation* animation = Animation::createWithSpriteFrames(animFrames, 0.02f);
    Animate* animate = Animate::create(animation);

    anime->setPosition(touch->getLocation().x, touch->getLocation().y);
    anime->runAction(animate);

    return true;
}

前回のタッチ処理でラムダ式を使いましたが、

C++のラムダ式は思った以上に使いづらいので

普通にコールバックとして関数を定義し、マクロで登録する形にしました。

アニメーション画像は14枚横に並んでいるので、この画像を横に14等分割にクリッピングして使用しています。

あとはアニメーション画像の位置をタップ位置に設定してアニメーションを実行します。

前回はanimateをforever(無限ループ)していましたが、今回は1回きりのアニメーションなので、animateをそのまま使用しています。

どちらも親クラスがActionクラスなので、問題ありません。