アニメーションを利用してエフェクト表示するときに、以下のようなエフェクト素材を目にすることはよくあると思います。背景が透過処理されているものではなく、黒く塗りつぶされているものです。
元になる素材は「ぴぽや」様から頂いております。
ぴぽや倉庫 様
これをそのままCocos2d-x上でアニメーションとしてみます。アニメーションのやり方は過去記事「Cocos2d-x アニメーションを利用した回復エフェクトの表示方法」を参照してください。
当然、黒い背景をそのまま含めたアニメーションが表示されます。このままではゲーム中には使えませんよね。この問題は「加算合成」を利用することで解決できます。
【前回まで】
・第1回 : アニメーションを利用した回復エフェクトの表示方法
加算合成を利用する
加算合成の仕組み
スプライトを重ねる際に、すでに存在しているスプライトのRGB値を加算します。黒色のRGBは(0,0,0)なので、加算後のRGB値はすでに存在しているスプライトのRGBと変わらないことになります。
それでは次に、Cocos2d-xのゲーム中で加算合成するやり方を見てきます。
BlendFuncを使う
BlendFuncを利用します。
BlendFunc func; func.src = GL_SRC_ALPHA; func.dst = GL_ONE; sprite->setBlendFunc(func);
ポイントは、元となるスプライトにBlendFuncを適用してからアクションを設定し、スプライトをRunActionさせると、アクションに紐付けられたアニメーションも加算合成されるところです。私はこれがわからずに大苦戦してました。
ではプログラムを見ていきます。
プログラムの実装
Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); cocos2d::SpriteFrameCache::getInstance()->addSpriteFramesWithFile("sprites.plist"); Sprite* sprite = Sprite::createWithSpriteFrameName("effect_cure02_0000.png"); sprite->setPosition(Vec2(visibleSize.width/10 * 5 + origin.x, visibleSize.height/2 + origin.y)); sprite->setScale(1.5); this->addChild(sprite); // 加算合成 BlendFunc func; func.src = GL_SRC_ALPHA; func.dst = GL_ONE; sprite->setBlendFunc(func); // アニメーションの作成 Animation* animation = Animation::create(); SpriteFrame* sprite0 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0000.png"); animation->addSpriteFrame(sprite0); SpriteFrame* sprite1 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0001.png"); animation->addSpriteFrame(sprite1); SpriteFrame* sprite2 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0002.png"); animation->addSpriteFrame(sprite2); SpriteFrame* sprite3 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0003.png"); animation->addSpriteFrame(sprite3); SpriteFrame* sprite4 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0004.png"); animation->addSpriteFrame(sprite4); SpriteFrame* sprite5 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0005.png"); animation->addSpriteFrame(sprite5); SpriteFrame* sprite6 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0006.png"); animation->addSpriteFrame(sprite6); SpriteFrame* sprite7 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0007.png"); animation->addSpriteFrame(sprite7); SpriteFrame* sprite8 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0008.png"); animation->addSpriteFrame(sprite8); SpriteFrame* sprite9 = SpriteFrameCache::getInstance()->getSpriteFrameByName("effect_cure02_0009.png"); animation->addSpriteFrame(sprite9); // アニメーションの間隔 animation->setDelayPerUnit(0.1); // アニメーション終了後に最初に戻すかどうか animation->setRestoreOriginalFrame(true); // アクションの設定 FiniteTimeAction* repeat = RepeatForever::create(Animate::create(animation)); // アクションの実行 sprite->runAction(repeat);
エフェクトアニメーションの表示
シミュレータを起動して黒い背景が見えなくなっていることを確認します。はあああ、やっとできたー!!(当時の心の声)
やった!これでゲームのエフェクト表現をかなりリッチにできるぞ!!!!