Cocos2d-x
パネルを置いて3連以上だったらピカーン!
(2015. 2. 3)
前章でBoardクラスを作ってパネルを盤上に置く事ができるようになりました。いよいよここに「○×Evolutionルール」を適用していきます。
@ パネルに「光る」モーションを追加
○×Evolutionのルールでは3連以上になったパネルが有効列と判定されます。置いた時に3連以上になった事をプレイヤーに示すために、パネルを「ピカーン!」っと光らせようと思います。これまでパネルには「バチーン!」と置くモーションがアタッチされていましたが、新しく「ピカーンと光るモーション」が追加されるというわけです。
PanelクラスにはsetMotionというメソッドを用意していました。この中で再生するモーションを切り替えるつもりで仕様を切っていました:
// モーションをセット
void Panel::setMotion( int motionId, float startTime ) {
if ( motionId == 0 )
createPlaceMotion( startTime );
}
motionIdが0の時が置くモーションです。createPlaceMotionが具体的なモーションの作成場所。これと同じようにmotionIdが1の時にcreateBrightMotionメソッドを呼ぶようにします。
さて、パネルを光らせる方法には色々あると思いますが、簡単な方法の一つは加算合成です。次のようなテクスチャを用意して上に重ねます:
重ねる時にもスプライトにシーケンスアクションを付けます:
Panel.cpp // 光るモーション生成
void Panel::createBrightMotion( float startTime ) {
auto bright_ = Sprite::createWithTexture( Director::getInstance()->getTextureCache()->addImage( "bright_panel.png" ) );
bright_->setOpacity( 0.0f );
CCSequence *seq = CCSequence::create(
CCFadeTo::create( 0.2f, 168 ),
CCDelayTime::create( 0.3f ),
CCFadeTo::create( 0.2f, 0 ),
NULL
);
bright_->runAction( seq );
BlendFunc blendAdd;
blendAdd.src = GL_ONE;
blendAdd.dst = GL_ONE;
bright_->setBlendFunc( blendAdd );
this->addChild( bright_ );
}
光るテクスチャ(bright_panel.png)からスプライトを作り、透過度を0にしておきます。シーケンスアクションはCCFadeToを使っています。これは第1引数に時間、第2引数には透過度を0〜255の整数で指定します。0〜1の小数では無いので注意です。CCFadeInだと100%不透明までフェードしてしまいますが、CCFadeToならば指定の透過度までなのでより細かな透過度調整が可能です。上の例では100%にすると物凄く眩しくなってしまうのでちょっと抑えました。
BlendFuncにはsrc、dst共にGL_ONEを指定し加算合成にしています。後はこれをパネル本体に登録するだけです。
A 3連以上でピカーン!
光るモーションが出来たので、次はパネルを配置した時に3連以上が成立しているかを判定します。これは「MatchNクラス」をすでに作ってありますのでとても簡単に出来ます(^-^)。Boardに対してパネルを置く度に判定します:
bool GameLayer::init() {
....
// パネルが置かれたらコールされる
board_->onPanel = [&]( int px, int py, Panel* panel ) {
// 置かれた位置をMatchN判定器に登録
matchN_->setVal( px, py, 0 );
// 3連以上出来ているかチェック
std::vector< MatchN::MatchIDInfo > idArys;
if ( matchN_->check( idArys, MatchN::All, 3, 5, px, py ) > 0 ) {
// 連が成立している位置のパネルを光らせる
std::vector<int> ids = MatchNUtil::getMatchIds( idArys );
for ( size_t i = 0; i < ids.size(); i++ ) {
unsigned x, y;
matchN_->getXY( ids[ i ], x, y );
Panel *pn = board_->getPanel( x, y );
pn->setMotion( 1, 0.0f );
}
}
};
....
}
「パネルを置いた!」という瞬間に、まず置かれた位置をMatchNオブジェクトに登録します。今は仮に値を0にしています(何も置いていない所は-1に設定してます)。次にMatchN::checkメソッドで置かれた位置の周辺で3連以上が出来ているか動かをチェックします。もし出来ていたら列情報の配列がやって来るので、MatchNUtil::getMatchIdsメソッド(ユーティリティ)を使ってそこから列のIdを抽出します。後はMatchN::getXYメソッドでIdからXY位置を取りだし、その位置にあるパネルをBoard::getPanelメソッドで取得、先程の光るモーションをPanel::setMotion(1,
0)で再生しています。これまで作ってきたクラスのメソッドの連携ですね(^-^)
実際に動かしたのがこちら:
ピカーン!ちゃんと3連時に眩しく光っております(^-^)/
今はすべてのパネルが同じ(値を0)としているので○も×も関係なく3連すると光りますが、パネルの種類に対応した値を入れれば同じパネルが3連以上連なった時に光ります。んでは次、3連の両端に相手のパネルを追加で置くアルゴリズムを作ります。この辺りから「置く」というのをメッセージで指定出来るようにする必要が出てきそうです。