段々とcocos2dとの違いが出てきて、速度ががくっと落ちて来ました。 前回から、今回にかけて出来たことと疑問に思っている所を今回紹介したいと思います。 基本的なことですが、もし、何かの参考にしていただければ嬉しいです。
アニメーション
cocos2dでもそうでしたが、アニメーションをする際に一々同じコードを書くのは良くないと思いましたので、CCAnimateクラスを返すメソッドをオブジェクトの一番下のクラスに設置しました。 アニメーションは主にオブジェクトが行うものですので、これさえ定義しておけば、後は個別に呼び出して使うだけです。
CCAnimateを返すメソッド
[c] //アニメーションのアクションを返す cocos2d::CCAnimate GameObject::getAnimation(const char animationPNG,int animationFrames,float delay,CCSpriteFrameCache*cache){
CCAnimate *action = NULL;
CCAnimation *_animation = CCAnimation::create();
CCArray *animeFrameArray = new CCArray();
for (int i = 0; i<animationFrames; i++) {
CCString *string = CCString::createWithFormat(animationPNG,i);
puts(string->m_sString.c_str());
CCSpriteFrame * frame = cache->spriteFrameByName(string->m_sString.c_str());
animeFrameArray->addObject(frame);
}
_animation->initWithSpriteFrames(animeFrameArray);
_animation->setDelayPerUnit(delay);
_animation->setRestoreOriginalFrame(true);
action = CCAnimate::create(_animation);
return action;
}
[/c] こんな感じでとりあえず動いています。 もし、もっといい方法があれば教えて下さい。
実際に使う場合
上記のメソッドをこんな感じで使います。 [c]
CCAnimate *walkAnimetion = NULL; walkAnimetion = this->getAnimation("mario-walk00%d.png", 8, 0.05f,cache); walkAnimetion->setTag(114); sprite->runAction(walkAnimetion);
[/c]
疑問点
CCSpriteFrameCacheクラスについての疑問点。 今回の処理は、CCAnimateクラスを返すメソッドと実際のアニメーションを行うクラスが違います。 親クラスにメソッドがあり、それを継承した子クラスがアニメーションを実行します。
その場合、CCSpriteFrameCacheクラスでplistを子クラスで読み込んでいるのですが、この読み込んだキャッシュが親クラスでは利用できないのです。 cocos2dでは、それが可能でしたので、わざわざ引数でCCSpriteFrameCacheクラスを引っ張ってきていませんでした。 [c]
//cocos2dx CCSpriteFrameCacheクラスの引数有り cocos2d::CCAnimate getAnimation(const char animationPNG,int animationFrames,float delay,CCSpriteFrameCachecache);
//cocos2d CCSpriteFrameCacheクラスの引数無し -(CCAnimate)getAnimation:(NSString)animationPNG animationFrames:(int)animationFrames delay:(float)delay;
[/c] これは、何かやり方が間違っているのか、それとも言語の違いなのか、かなり考えました。
タイルマップ
ゲームの背景を作成する際に、Tiledを利用したタイルマップを使っています。
色々使い方があると思うのですが、「マップ内に衝突判定を司るレイアー」と「敵やアイテムなどのオブジェクト」が簡単に設置できます。
オブジェクト
この2日間悩んでいたのが、オブジェクトの配置です。 オブジェクトを生成する方法がなかなか良いコードが作れませんでした。 で、出来たのがこのような形です。 [c]
define ifDynamicCast(type,var,varName) \
type varName = dynamic_cast<type>(var); \ if( varName )
void myTMXTileMap::addObjects(){
auto groups = this->getObjectGroups();
for (int i = 0; i < groups->count(); i++) {
ifDynamicCast(CCTMXObjectGroup*, groups->objectAtIndex(i), group){
auto objects = group->getObjects(); for (int j = 0; j < objects->count(); j++) {
ifDynamicCast(CCDictionary*, objects->objectAtIndex(j), properties){
ifDynamicCast(CCString*, properties->objectForKey("type"), className){
//オブジェクトの生成
this->addObject(className->getCString(),properties);
}
}
}
}
}
}
//オブジェクトの生成 void myTMXTileMap::addObject(const char classname,CCDictionaryproperties){
//名前によってif分を使い、マップ上にオブジェクトを作成する。
if (strcmp(classname, "player") == 0) {
Player *obj = Player::create();
this->addChild(obj);
obj->setproperties(properties);
}
}
//オブジェクト側で場所を設定する。 void GameObject::setproperties(cocos2d::CCDictionary *dict){
float x = dict->valueForKey("x")->floatValue();
float y = dict->valueForKey("x")->floatValue();
CCLOG("property position x:%f y:%f",x,y);
CCPoint point = CCPointMake(x, y);
this->setPosition(point);
}
[/c] ほぼ、下記サイトのコードを真似しました。 こんな感じで、オブジェクトが設置出来ます。
疑問
このコードではオブジェクトが増えるに従って、コードが長くなってしまいます。 cocos2dの時は、以下の様なコードを使えば、どのオブジェクトにも対応出来ました。 [c]
//cocos2d
Class cla = NSClassFromString([[prop valueForKey:@"type"] capitalizedString]);
[/c] このような方法は、cocos2dx(C++)では出来ないのでしょうか? 色々調べたのですが、それらしいコードが該当しませんでした。
[参考サイト]
疑問点 継承・拡張
「継承・拡張」と言いましたが、本当はどう呼べばいいのかわかりませんが、cocos2dで用意されているクラスを自分用にカスタマイズする方法がわかりません。 cocos2dでは以下のようなコードでCCNodeクラスやCCSpriteクラスを触っていました。 [c]
//ヘッダー //既存のクラスの後ろにカッコを付ける @interface CCTMXMapInfo(Extended) {
}
//既存のクラスにあるメソッドを上書き、もしくは少し修正する
@implementation CCNode (Extended)
-(float) width { return self.contentSize.width; }
-(float) height { return self.contentSize.height;
}
[/c]
こうすることで、新しいメソッドを追加したり、また既存のメソッドを修正・改修したりすると非常に楽でした。 cocos2dの時には、TileMapを読み込む時に呼び出されるCCTMXMapInfoクラスを上記の方法で修正して、一つのタイルマップでretinaにも対応できるようにしていました。 色々調べたのですが、既存のクラスを修正する方法が見つかりませんでした。
現状retina用に別途タイルマップのデータ(それぞれの値を2倍にしたもの)を用意して利用しているのですが、タイルマップが大きいとメモリーに負荷がかかるので、できれば別の方法を使いたいのですが。 これを含めて、cocos2dxではマルチディスプレイへの対応をしっかりしないと、後で苦労しそうです。 もし、このタイルマップを利用した際のretina・その他のディスプレイに対応するいい方法があれば教えて欲しいです。
最後に
cocos2dがある程度わかれば、cocos2dxもそんなんでも無いだろうと思っていましたが、そうでもないようです。 新しい言語なので、これは致し方ない部分でもありますが、効率良く作業をして行きたい所です。(今のこの感じはcocos2dをやり始めていた時を思い出します。)
やはり、生きたコードを見ない行けないと感じますね。Webにも情報がありますが、断片的なモノが多いので、実際にそれを利用できるようにするのが大変です。 こうなると本がほしい。今週発売されるcocos2dxのレシピ本を見に行こう。
Cocos2dーx開発のレシピ―オープンソース・ゲームエンジン 松浦 晃洋 秀和システム 売り上げランキング : 1774 Amazonで詳しく見る |
これAmazonだと、時間かかるので本屋にあればいいのですが。