読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

Cocos2d-x 3.0 を触ってみる

Cocos2d-x

こんにちは。今回ブログを担当します長屋です。
正式にリリースされたCocos2d-x 3.0 を触ってみたいと思います。

☆Cocos2d-x v3.0☆
http://www.cocos2d-x.org/download

〜 プロジェクト作成 〜

RC版からプロジェクト生成ツール「create_project.py」は廃止され、cocosコマンドを使用することでプロジェクトを生成できるようになっています。
cocos2d-x-3.0フォルダの直下に存在する環境変数設定ツール[setup.py]を使用することでAndroid用の環境変数とcocosコマンド用の環境変数を対話形式で設定することができます。
[setup.py]での設定が完了するとcocosコマンドを使用することができます。

①ターミナルを起動し、Cocos2d-x 3.0のインストール先直下のディレクトリで以下のコマンドを実行
./setup.py

②環境変数設定後ルートディレクトリで以下のコマンドを実行する。又はターミナルの再起動
source ~/.bash_profile

③環境変数設定後、以下のコマンドを使用することでプロジェクトを生成
cocos new [プロジェクト名] -p [パッケージ名] -l [使用言語 cpp | lua | js ] -d [プロジェクト出力ディレクトリ]

プロジェクト作成例
cocos new HogeProject -p com.blog.HogeProject -l cpp -d /Users/Guest/Documents/

またcocosコマンドを利用してプロジェクトをビルドしシミュレーター上で実行することもできます。
※ -m は省略可 デフォルトは[debug]になっています。
cocos run -s [プロジェクトベースディレクトリ] -p [プラットフォーム ios | android] -m [debug | release]

エラーログやソース上で設定したログはターミナルに出力されます。

〜コンテナクラスについて〜

v3.0から[CCArray]や[CCDictionary]は使用できなくなりました。
(厳密には使用できますが非推奨です。いつ使用できなくなるかわかりません)
かわりに[cocos2d::Vector]と[cocos2d::Map]が用意されています。
Vectorは内部で[std::vector]を保持しており、Mapは[std::unordered_map]を保持しています。
各コンテナを参照カウンタに対応させたものであり各コンテナの機能をほぼ全て利用することができます。
ただし、参照カウンタの関係で一部の機能が使えないようになっています。

//CCArrayとVector  
  
Node * pNode1 = Node::create();  
pNode1->setTag(1);  
Node * pNode2 = Node::create();  
pNode2->setTag(2);  
Node * pNode3 = Node::create();  
pNode3->setTag(3);  
Node * pNode4 = Node::create();  
pNode4->setTag(4);  
  
//こっちは非推奨  
//    CCArray * pArray = CCArray::create();  
//  
//    //要素追加  
//    pArray->addObject(pNode1);  
//    pArray->addObject(pNode2);  
//    pArray->addObject(pNode3);  
//    pArray->addObject(pNode4);  
//  
//    //マクロを使用して監査  
//    CCObject * pObj = NULL;  
//    CCARRAY_FOREACH( pArray , pObj) {  
//        CCLOG("tag %d",((CCNode*)pObj)->getTag());  
//    }  
//  
//    //削除  
//    pArray->removeObject(Node1);  
  
//渡せる型はcocos2d::Refを継承しているオブジェクトのみ  
Vector<Node*> vec;  
  
//要素追加  
//このタイミングでretain()が呼ばれている  
vec.pushBack(pNode1);  
vec.pushBack(pNode2);  
vec.pushBack(pNode3);  
vec.pushBack(pNode4);  
  
//監査  
//retain、releseの関係上[]演算子でのアクセスはできません。  
for(int i = 0; i < vec.size();i++){  
    log("tag %d",vec.at(i)->getTag());  
}  
for(auto it = vec.begin();it != vec.end(); ++it){  
    log("tag %d",(*it)->getTag());  
}  
for(auto * obj : vec){  
    log("tag %d",obj->getTag());  
}  
  
//削除  
//このタイミングでrelease()が呼ばれます。  
vec.erase(vec.find(pNode1));  
  
//中身はstd::vectorなので便利なのですよ  
if (std::find_if(vec.begin(),  
                 vec.end(),  
                 [](Node* node) { return node->getTag() == 2;})  
                 != vec.end()){  
    log("tagが2の人いるよ");  
}  
  
//CCDictionaryとMap  
  
Node * pDicNode1 = Node::create();  
pDicNode1->setTag(1);  
Node * pDicNode2 = Node::create();  
pDicNode2->setTag(2);  
Node * pDicNode3 = Node::create();  
pDicNode3->setTag(3);  
Node * pDicNode4 = Node::create();  
pDicNode4->setTag(4);  
  
//こっちも非推奨  
//    //要素追加  
//    CCDictionary * pDict = CCDictionary::create();  
//    pDict->setObject(pDicNode1, "Node1");  
//    pDict->setObject(pDicNode2, "Node2");  
//    pDict->setObject(pDicNode3, "Node3");  
//    pDict->setObject(pDicNode4, "Node4");  
//  
//    //要素習得  
//    pDict->objectForKey("Node1");  
//  
//    //要素監査  
//    DictElement * pEl = NULL;  
//    CCDICT_FOREACH(pDict, pEl){  
//        log("key %s ",pEl->getStrKey());  
//        log("value_tag %d ",((Node*)pEl->getObject())->getTag());  
//    }  
//  
//    //要素削除  
//    pDict->removeObjectForKey("Node1");  
  
//データに渡せる型はcocos2d::Refを継承しているオブジェクトのみ  
Map<std::string, Node*> map;  
  
//[]演算子によるアクセスは不可  
//map["Node1"] = pDicNode1;  
  
//要素セット  
//このタイミングでretain()が呼ばれます。  
map.insert("Node1", pDicNode1);  
map.insert("Node2", pDicNode2);  
map.insert("Node3", pDicNode3);  
map.insert("Node4", pDicNode4);  
  
//要素習得  
map.at("Node1");  
  
//要素監査  
for(auto pair : map){  
    log("key %s ",pair.first.c_str());  
    log("value_tag %d ",pair.second->getTag());  
}  
  
//要素削除  
//このタイミングでrelease()が呼ばれます  
map.erase(map.find("Node1"));

v2.X系のようなマクロを使用することなくC++チックにコーディングできるようになりました。

〜グローバルZオーダー〜

ノードツリーの親子関係を超えて描画順を設定できるようになりました。
親ノードのZオーダーが他のノードよりも後ろに設定されている場合でも、
グローバルZオーダーを手前に設定することで隠れることなく表示することができます。

// 例  
// 画面全体にグレーアウト処理をさせてもアイコンだけは目立たせたい  
  
//中心座標  
Point center(Director::getInstance()->getWinSize()/2);  
  
//背景色設定  
LayerColor * pWhite = LayerColor::create(Color4B::WHITE);  
this->addChild(pWhite);  
  
//上にかぶせるグレーレイヤ  
LayerColor * pGray = LayerColor::create(Color4B::GRAY);  
pGray->setOpacity(160);  
this->addChild(pGray,100);  
  
//ONボタン  
Sprite * pOn = Sprite::create("On.png");  
pOn->setPosition(Point(center.x,center.y - 270));  
this->addChild(pOn, 10);  
  
//ウインドウを管理しているノード  
Node * pWindowNode = Node::create();  
pWindowNode->setPosition(center);  
pWindowNode->setContentSize(Size::ZERO);  
this->addChild(pWindowNode, 10);  
  
//ウインドウ  
Sprite * pBlackWindow = Sprite::create("BlackWindow.png");  
pWindowNode->addChild(pBlackWindow);  
  
//アイコン生成  
Sprite * pRed = Sprite::create("Red.png");  
Sprite * pBlue = Sprite::create("Blue.png");  
Sprite * pYellow = Sprite::create("Yellow.png");  
  
//アイコンの座標設定  
pRed->setPosition(Point::ZERO);  
pBlue->setPosition(Point(100,0));  
pYellow->setPosition(Point(-100,0));  
  
//ローカルZオーダーは10  
//pBlackWindowの上にボタンは表示される  
pWindowNode->addChild(pRed,10);  
pWindowNode->addChild(pBlue,10);  
pWindowNode->addChild(pYellow,10);  
  
//グローバルZオーダーを10.0fに  
//アイコンを保持しているノードがグレーのレイヤよりもローカルZオーダーが後ろでも  
//アイコンのグローバルZオーダーがよりグレーのレイヤより高いため背景より前に描画される  
pRed->setGlobalZOrder(10.0f);  
pBlue->setGlobalZOrder(10.0f);  
pYellow->setGlobalZOrder(10.0f);  

☆実行結果
image1

まだまだ他にも3.0での変更点はありますので、追って紹介したいと思います。

☆Cocos2d-x 3.0 Reference☆
http://www.cocos2d-x.org/reference/native-cpp/V3.0/index.html