ホーム < ゲームつくろー! < IKD備忘録

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連の両端に相手のパネルを追加で置くアルゴリズムを作ります。この辺りから「置く」というのをメッセージで指定出来るようにする必要が出てきそうです。