Cocos2d-x 10円ゲーム講座 第5回、画像(スプライト)を表示してみます。
4つ用意しました。
背景画像とフレームの画像です。
コイン投入口。コインを投入するボタンの役も兼ねます
コイン。
これらの画像をプロジェクト内のResourcesフォルダに配置します。
Resourceフォルダ + background.png + coin.png + coin_entry.png + frame.png
画像(スプライト)の表示にはSpriteクラスを利用します。
// 筐体背景画像の描画 auto background = Sprite::create("background.png"); // Resources内の画像を指定 background->setPosition(Vec2(180.0f, 320.0f)); // 表示位置の設定 this->addChild(background); // 現在のシーンに加える
1行目はSpriteクラスの生成と共に画像のファイル名を指定しています。Cocos2d-xプロジェクトはResourcesフォルダにパスが通っているため、Resourcesフォルダにbackground.pngを置くことですぐさまスプライトを使用できます。
setPositionは位置の設定です。Cocos2d-xでは左下原点なので、上のソースコードでは左から180ピクセル、下から320ピクセルの位置に画像を配置します。
Spriteクラスを定義しただけでは画像は表示されません、現在のシーン(this)に対してスプライトを子として追加し、シーンに結びつけることで表示されるようになります。3行目のaddChildはそのためのコードになります。
このコードの実装はinit()で行います。init()はシーン遷移時に1度だけ呼ばれるので、初期化処理を実装する所に最適です。
背景画像が描画できました。
スプライトの表示がたった数行のコードでできるところが、Cocos2d-xなどゲーム開発プラットフォームの大きな利点でもあります。
背景画像は表示できました。これから他の画像を表示していきますが、その前にレイヤーの概念について説明しておきます。
レイヤーとは表示順序のことです。今回配置した背景画像の裏にコインが表示されても意味がありません。そこで、用意した画像の表示順序を決めておく必要があります。
10円ゲームでは、筐体の画像は最下層になり、その上にコイン、コインの上に筐体のフレーム、筐体のフレームの上にコイン投入口やレバーがあって欲しいので、
上記のような画像の表示順序が良いことがわかります。
このレイヤーの順序をコードで反映させていきます。レイヤーの順序は、前回の画像の表示でも使用したaddChild()メソッドの第二引数がレイヤー順序に相当します。
void Node::addChild(Node *child, int zOrder)
第二引数のint zOrderは、数値が高くなるほど上位層のレイヤーとなります。
addChild()はCocos2d-xのほとんどのクラス(Nodeを継承している)が持つため、孫Nodeなども簡単に作ることができますが、孫のレイヤー順序は、子のレイヤー順序を越えて表示されることがありません。あくまで孫同士のレイヤー順序の関係を指定するものです。
// 筐体画像(フレーム)の描画 auto frame = Sprite::create("frame.png"); frame->setPosition(Vec2(visibleSize.width*0.5f, visibleSize.height*0.5f)); this->addChild(frame, 2);
addChild()の第二引数を2にしています。
コイン投入口はボタンにして、コイン投入口ボタンをタッチした際にはコインを表示するようにしてみます。
コインは後々位置を移動させたりするので、OneCoinGameクラスのメンバ変数として定義しておきます。ついでにコイン投入口のボタンを押した時のコールバック関数も定義しておきます。
class OneCoinGame : public cocos2d::Layer { // コイン投入口ボタン押下時のコールバック void insertCoinCallback(cocos2d::Ref* pSender); private: cocos2d::Sprite *_coin; // コイン };
コインの画像表示はこれまで通りinit()内でSpriteクラスを使って描画します。
// コインの描画 _coin = Sprite::create("coin.png"); _coin->setPosition(Vec2(visibleSize.width*0.5, visibleSize.height*0.5)); this->addChild(_coin, 1); // コインを非表示にしておく _coin->setVisible(false);
setVisible(bool bVisible)でスプライトの表示と非表示を切り替えることができるため、最初は非表示にしておきます。
続いてコイン投入口ボタンの追加。これもinit()内で実装します。
// コイン投入口(ボタン) auto insertCoinItem = MenuItemImage::create( "coin_entry.png", "coin_entry.png", CC_CALLBACK_1(OneCoinGame::insertCoinCallback, this)); insertCoinItem->setPosition(Vec2(visibleSize.width*0.7, visibleSize.height*0.9)); auto menu = Menu::create(insertCoinItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 2);
Cocos2d-xのボタンは、メニューアイテムとしてボタンの元となるパーツを作成し、メニューに追加することで実装できます。
画像のメニューアイテムには、MenuItemImageクラスを使用します。今回は通常時と選択時のボタン画像を同じにしています。コールバック関数の指定には、Cocos2d-xのマクロであるCC_CALLBACK_1を利用して、定義した関数を指定します。
ボタンを押した際に呼ばれるコールバック関数の中身を実装します。
// コイン投入ボタン void OneCoinGame::insertCoinCallback(cocos2d::Ref* pSender) { // コインの表示 _coin->setVisible(true); }
先ほどのsetVisible()を使ってコインを表示します。
ビルドして実行するとコイン投入口が表示できました。またコイン投入口を押すとコインが表示されます。ただしコインはまだ動きません。
ソースコードはこちら
MenuItemImage::create()はいくつか引数のパターンがあり、無効時のボタンイメージなども指定できます。
メニューアイテムにはMenuItemLabelクラスを使用することで、文字列をボタンにすることができます。
ラベルボタンのコード例
// コイン投入口(ボタン) auto insertCoinItem = MenuItemLabel::create( Label::create("コイン投入口", "fonts/Marker Felt.ttf", 12), CC_CALLBACK_1(OneCoinGame::insertCoinCallback, this)); insertCoinItem->setPosition(Vec2(visibleSize.width*0.5, visibleSize.height*0.5)); auto menu = Menu::create(insertCoinItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 2);
]]>
Cocos2d-x 10円ゲーム講座 第4回、10円ゲームの進め方と画面の縦長使用についてです。
10円ゲームの遊び方をふまえて、今回のゲームの遊び方を決めてみます。
10円ゲームは大体こんな感じだと思います。
筐体としてこんな画像を用意しました。
コイン投入口ボタンを押すことで、コイン投入口からコインを投下、重力とレールに従って左に転がっていきます。そこからレバーで4回はじき、下部の橙色のゴールに入ればゴールとして、景品を出力することにします。
10円玉ではなくコインにしましたが、この画像を元に10円ゲームを作っていきます。
コインゲームはゲーム的に縦長の方が良いと思います。用意した筐体画像も縦長なので、画面を縦長にします。
Cocos2d-xではデザイン解像度と画面解像度があります。
static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);
designResolutionSizeがデザイン解像度の定義。Cocos2d-x内で指定する座標系は、全てこの座標を元にした値になります。この例では180, 320が中心位置ということになり、画像表示位置を180,320にすると中心に貼り付けることになるということです。(AnchorPointなどによって中心位置の取り扱い方を変えることはできます)
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 320); static cocos2d::Size mediumResolutionSize = cocos2d::Size(1024, 768); static cocos2d::Size largeResolutionSize = cocos2d::Size(2048, 1536);
こちらha
画面解像度の定義。スマートフォンなどの解像度に合わせて、画面のスケーリング(拡縮)を決定します。
今回は縦長9:16の360×640を解像度として設定します。9:16なのでスマフォでもピッタリになることが多いでしょう。
static cocos2d::Size designResolutionSize = cocos2d::Size(360, 640); static cocos2d::Size smallResolutionSize = cocos2d::Size(360, 640); static cocos2d::Size mediumResolutionSize = cocos2d::Size(640, 1136); static cocos2d::Size largeResolutionSize = cocos2d::Size(1080, 1920);
デザイン解像度と画面解像度を360×640とその倍率に合わせて変更します。
実行結果。縦長になりました。
ソースコードはこちら
現在のファイル構成は上記のようになっています。
初期プロジェクトでは、アプリケーション起動後、各種初期化を行ってからHelloWorldシーンに遷移してCocos2d-xロゴを表示するのが流れになります。
bool AppDelegate::applicationDidFinishLaunching() { // ... 省略 ... // // create a scene. it's an autorelease object auto scene = HelloWorld::createScene(); // run director->runWithScene(scene); }
HelloWorld::createScne()はHelloWorldScene.cppで定義されており、プロジェクト生成時に作られるCocos2dのロゴを表示するサンプルシーンになります。
そのまま利用しても良いですが、HelloWorldという名前がいまいちなので変更して使用します。
HelloWorldScene.hとHelloWorldScene.cppを、それぞれOneCoinGameScene.hとOneCoinGameScene.cppに変更します。
変更に合わせて、AppDelegate.cppのapplicationDidFinishLaunching()で指定するシーンも変更します。
// create a scene. it's an autorelease object auto scene = OneCoinGame::createScene();
OneCoinGameScene.hとOneCoinGameScene.cppのコードも載せておきます。
#ifndef __ONECOINGAME_SCENE_H__ #define __ONECOINGAME_SCENE_H__ #include "cocos2d.h" class OneCoinGame : public cocos2d::Layer { public: static cocos2d::Scene* createScene(); virtual bool init(); // implement the "static create()" method manually CREATE_FUNC(OneCoinGame); }; #endif // __ONECOINGAME_SCENE_H__
元々のHelloWorldScene.cppにあったサンプル表示コードは削除して、何も表示しないようにします。
#include "OneCoinGameScene.h" USING_NS_CC; Scene* OneCoinGame::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = OneCoinGame::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool OneCoinGame::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); return true; }
実行結果。サンプルコードの内容を空にしたので、実行すると真っ黒です。
ソースコードはこちら
次回は画像(スプライト)を表示します。
]]>