Cocos2d-xで作る弾幕シューティング(ソースコードあり)

shooting01

こんにちは。野口です。

業務アプリプログラマーがCocos2d-xでゲームを作るシリーズ第2弾です。

[ Cocos2d-xで作る弾幕シューティング ]

さて、今回はシューティングゲームです。
シューティングゲームの中でも、画面いっぱいに入り乱れる敵弾を回避しながら戦ういわゆる「弾幕シューティング」と呼ばれるジャンルに挑戦してみたいと思います。

ソースコードはGitHubで公開しているのでご希望の方は以下から取得してください。
(cocos2d-x-2.2.0で、Xcode5.0のiPhone Retina(4-inch)環境でのみ動作確認しています)
https://github.com/noguchi999/shooting.git

・ 画面の更新

シューティングなので、画面には最低限、「自機」、「自弾」、「敵機」、「敵弾」が存在しており、それぞれが接触した場合の処理が必要になります。
また、それぞれは停止しているわけではなく画面内を動き回っています。

定期的に画面の再描画処理が行われています。
Cocos2d-xでは、デフォルト設定だと最大1/60秒に1回のペースで画面が再描画されます。
CCLayerクラスには、そのタイミングで関数を呼び出す仕組みとしてscheduleメソッドが用意されています。

今回は、定期的にupdate関数を呼出すscheduleUpdateメソッドを紹介します。
使い方は以下の通りです。

・ scheduleUpdateの定義

bool GameScene::init()
{
    this->scheduleUpdate();
    return true;
}

void GameScene::update(float delta)
{
    CCNode* player = this->getChildByTag(kTagPlayer);
    CCObject* obj = NULL;
    CCARRAY_FOREACH(this->getChildren(), obj)
    {
        CCNode* child = dynamic_cast<CCNode*>(obj);
        if (child->getTag() == kTagEnemy)
        {
            if (child->boundingBox().intersectsRect(player->boundingBox()))
            {
                // 自機と敵機の衝突時の処理
            }
        }
    }
}

シーンのinit関数の中で、scheduleUpdateを呼出すことで、定期的にupdate関数が呼び出されるようになります。

後は、update関数の中にコードを記述していけば画面の再描画のタイミングでその処理が実行されるというわけです。
上記は、自機と敵機の衝突判定の処理の例です。

・ 画像処理の高速化

弾幕シューティングということで、画面いっぱいに敵弾が乱舞するわけです。
Cocos2d-xでは、画面に画像を表示させたい場合、表示させたい画像ファイルを指定してスプライトを作成するわけですが、
通常の方法で大量の画像を読み込むとメモリ消費が大変なことになりますし、パフォーマンスも劣化してしまいます。

ではどうするのか? というと、Cocos2d-xには同一の画像ファイルを読み込んで画面に大量のスプライトを効率的に表示させるための機能が用意されています。
それが、CCSpriteBatchNodeクラスです。

CCSpriteBatchNodeクラスの利用方法は、とても簡単で通常のスプライトの使い方と大差ありません。
では、実際に通常のスプライトの利用方法とCCSpriteBatchNodeクラスを利用した方法でのソースコードを比較してみましょう。

・ 通常の方法でスプライトを100個表示する

for (int i = 0; i < 100; i++)
{
    CCSprite* bullet = CCSprite::create('bullet.png');
    bullet->setPosition(ccp(100, 100))
    this->addChild(bullet);
}

・ CCSpriteBatchNodeクラスでスプライトを100個表示する

CCSpriteBatchNode* batchNode = CCSpriteBatchNode::create("bullet.png");
this->addChild(batchNode);

for (int i = 0; i < 100; i++)
{
    CCSprite* bullet = CCSprite::createWithTexture(batchNode->getTexture());
    bullet->setPosition(ccp(100, 100));
    batchNode->addChild(cat);
}

いかがでしょうか?
簡単ですよね。これだけで大量の画像処理を扱う際のパフォーマンスアップを図ることが出来るので、これを使わない手はありません。

・ サンプル動画

■ 最後に。

本記事のプログラム作成にあたっては以下の書籍が非常に参考になりました。
cocos2d-xによるiPhone/Androidアプリプログラミングガイド

ソースコードや画像の一部も流用させていただいています。

コメントを残す

メールアドレスが公開されることはありません。

ABOUTこの記事をかいた人

僕と契約してアーティストになってよ。 普段はJavaやPHPで業務Webアプリばっかり作っています。 安西先生、Rubyで仕事がしたいです・・・。