2014年01月16日

[Cocos2d-x][C++] vector、mapが参照しているメモリを開放しつつ全削除

C++のmap、vectorに慣れておらず、苦労しました。
これで良いのではないかと思ってますが、間違ってたらつっこんでください…。

vector
for (vector<Hoge *>::iterator it = hoges.begin(); it != hoges.end();) {
delete *it;
it = hoges.erase(it);
}


map
for (map<int, Hoge *>::iterator it = hoges.begin(); it != hoges.end(); it++) {
delete it->second;
}
hoges.clear();

secondが値を指しているということなんですかね。わかりにくいですね。なんでこんな名前にしたんですかね。

参考:
c++ - How to erase & delete pointers to objects stored in a vector? - Stack Overflow
C++とのつきあい方(16)
posted by t2low at 23:00| Cocos2d-x

2014年01月15日

[Cocos2d-x] Resources内のファイルの読み込み

Resources内のファイルを読み込んで使うには以下のようにすれば良いみたい。
CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();
string path = fileUtils->fullPathForFilename("hoge.json");
unsigned long size = 0;
unsigned char *data = fileUtils->getFileData(path.c_str(), "r", &size);

// ... data を使ってなんかする

delete[] data;

getFileData()の中を見たら、第2引数をそのままfopen()につっこんでいたので、バイナリデータを読み込むときは"rb"にするのかな?


タグ:C++ cocos2d-x
posted by t2low at 22:00| Cocos2d-x

2014年01月10日

[Cocos2d-x] 階層化されたCCLayerの内側からモーダルレイヤを画面の中心に表示する


以下の本の「レシピ38」を参考にモーダルレイヤを作成しました。



画面の真ん中にドンとモーダルレイヤが表示される…はずだったのですが、僕の書いたコードでは上にずれて表示されてしまいました。
原因はCCLayerをいくつか階層化していたために、画面の左下とレイヤの原点がずれてしまっていたためです。

Cocos2d-xでは位置を親との相対座標で指定するようです。
これによって、階層の途中に位置が(0, 0)でないレイヤがあると、モーダルレイヤの位置を(0, 0)にしていたとしてもずれて表示されてしまいます。
少し調べただけでは、そのようなときに使う特別なメソッドはわかりませんでした。
それならばと、親階層をたどって左下の座標を計算するコードを書きました。
float x = 0;
float y = 0;
CCNode *node = modal->getParent();
while (node) {
x -= node->getPositionX();
y -= node->getPositionY();
node = node->getParent();
}
modal->setPosition(ccp(x, y));

とりあえずこれで画面の中心に表示できるようになりました。

タグ:cocos2d-x
posted by t2low at 23:00| Cocos2d-x

2014年01月07日

[Cocos2d-x] CCSpriteの重なり順

CCSpriteの重なり順を設定するには、reorderChild()というメソッドを呼べば良いらしい。

Cocos2d-x: 重なり順の取得、変更 | Lady Wendy

CCLayerを継承したクラスで以下のように呼んでみた。
for (int i = 0; i < MAX_HOGE; i++) {
CCSprite *sprite = (CCSprite *) getChildByTag(i);
if (sprite == NULL) {
continue;
}
reorderChild(sprite, HEIGHT - sprite->getPositionY());
}

結果は失敗。重なり順は変わらない。
少し調べてみると以下のような記事が見つかった。

cocos2d-x - CCSpriteBatchNodeのzOrder - Qiita [キータ]

確かにCCSpriteBatchNodeは使っているけれど、これを使ったせいで重なり順が変えられないなんてことあるわけない(はず!)。
と、ここで気がついた。
CCSpriteBatchNode *batch = (CCSpriteBatchNode *) getChildByTag(TAG_BATCH);
for (int i = 0; i < MAX_HOGE; i++) {
CCSprite *sprite = (CCSprite *) batch->getChildByTag(i);
if (sprite == NULL) {
continue;
}
batch->reorderChild(sprite, HEIGHT - sprite->getPositionY());
}

階層としては

・CCLayer
 └CCSpriteBatchNode
  ├CCSprite
  ├CCSprite
  ├CCSprite
  :
  └CCSprite

となっているのだから、CCSpriteBatchNodeのreorderChild()を呼ばなきゃダメだったわけね。
これで期待通りの重なり順になりました。

タグ:cocos2d-x
posted by t2low at 22:00| Cocos2d-x

2014年01月06日

[Cocos2d-x] テクスチャアトラスとCCSpriteBatchNodeを使ってスプライトを描画する

また忘れてしまいそうなのでメモ。
テクスチャアトラス(atlas.plist/atlas.png)があって、その中にhoge.pngがある場合、以下のようにすると良い(っぽい)。
 CCSpriteFrameCache *cache = CCSpriteFrameCache::sharedSpriteFrameCache();
cache->addSpriteFramesWithFile("atlas.plist");

CCSpriteBatchNode *batch = CCSpriteBatchNode::create("atlas.png");
addChild(batch);

for (int i = 0; i < 100; i++) {
CCSprite *sprite = CCSprite::createWithSpriteFrameName("hoge.png");
sprite->setPosition(ccp(i, i));
batch->addChild(sprite);
}


  • CCSpriteFrameCacheにはテクスチャアトラスの○○.plist

  • CCSpriteBatchNodeにはテクスチャアトラスの○○.png

  • CCSpriteにはテクスチャアトラス内の□□.png

  • をそれぞれ指定する。
    CCSpriteBatchNodeにもテクスチャアトラス内の画像名を渡していて少しハマっていた…。

posted by t2low at 22:00| Cocos2d-x

2013年12月25日

[Cocos2d-x][C++] C++で型推論

今までC++をほとんどやってこなかったので知りませんでした。
C++では型推論できたんですね。
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCTableView *tableView = CCTableView::create(this, CCSizeMake(visibleSize.width, visibleSize.height));
tableView->setDirection(kCCScrollViewDirectionVertical);
// 以下略

↑コレを↓のように書けます。
auto visibleSize = CCDirector::sharedDirector()->getVisibleSize();
auto tableView = CCTableView::create(this, CCSizeMake(visibleSize.width, visibleSize.height));
tableView->setDirection(kCCScrollViewDirectionVertical);
// 以下略

autoで定義された変数に対しても、Eclipse/Xcodeの補完が効きます。すごい!

どうやらC++11で導入されたようですね。
C++11 - Wikipedia



posted by t2low at 22:00| Cocos2d-x

2013年12月24日

[Cocos2d-x] CCTableViewでヘッダーを使いたい

iOSのUITableView(?)にはヘッダー・フッターを扱う機能があるらしいですね。
Cocos2d-xのCCTableViewにも同様の機能があるかと思って調べたのですが、(僕が調べた限りでは)どうやらそういった機能はなさそう…。
自分でなんとかするしかないようです。
とりあえず、実現できそうだったのでやり方をメモ。


  • ヘッダーとして表示したいViewのインスタンスを用意する

    • 開放されないようにretain()しておく

    • 使わなくなったらrelease()する



  • CCTableViewDataSource#tableCellAtIndex()で返却するViewを選択する

    • idxが0のときは、ヘッダーのインスタンスを返却

    • idxが0以外のときは、その他のインスタンスを返却。CCTableView#dequeueCell()したり、create()したり。

    • CCTableView#dequeueCell()でヘッダーのインスタンスが返ってきたら使わないようにする。もっかいdequeueCell()したり、create()したり。





たぶんコレできちんと再利用されるはず。
(ソースがなくて申し訳ない)

タグ:cocos2d-x
posted by t2low at 22:00| Cocos2d-x

2013年12月20日

[Cocos2d-x] 画面を縦向きにする

Cocos2d-xで縦向き画面のゲームを作りたいので、画面を縦向きにする方法を調べました。

とりあえず、公式サイトの情報。
Device Orientation | Cocos2d-x

タイトルのDevice Orientation (need to be updated)の、「need to be updated」って、「内容が古い」ってことでしょうか…。
実際、2つあると書かれている方法のうち、最初の「setDeviceOrientation()」というメソッドはもう無いようです。

公式情報があてにならないので、非公式なブログなどをいろいろと見てみました。
どうやらAndroidはAndroidManifest.xmlのscreenOrientationをportraitに変えるだけのようですね。

AndroidManifest.xml
android:screenOrientation="portrait"


iOSの方はiOS5とiOS6で処理を変えなきゃいけないようで、iOSの知識がほとんどない僕は結構混乱しました。

【iPhoneアプリ】iOS6では画面の向きが変わった時に呼ばれる関数が違う | 桜花満開/テンシホタル

How to change the orientation to Portrait? | Cocos2d-x

RootViewController.mmというファイルをいじるようです。

RootViewController.mm
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsPortrait( interfaceOrientation );
}

- (NSUInteger) supportedInterfaceOrientations{
#ifdef __IPHONE_6_0
return UIInterfaceOrientationMaskPortrait;
#endif
}

- (BOOL) shouldAutorotate {
return NO;
}


あと、Xcodeでプロジェクトのトップを選択した時に編集できる画面の「Deployment Info → Device Orientation」の「Portrait」にチェックを入れる必要がありそう。

スクリーンショット 2013-12-20 11.21.14.png

OS毎に別々の設定が必要ということは、画面の回転についてはCocos2d-xの中だけではどうにもならないみたいですね。
OSが違うし仕方がないのかも知れませんね。


posted by t2low at 22:00| Cocos2d-x

2013年12月18日

[Android] dumpsysコマンド

dumpsysコマンドについて調べようと思い、検索したら以下のページが引っかかりました。
公式サイトのようです。
Dumpsys | Android Developers

ちゃんと読んでないのですが、Usageのところのコマンドが気になりました。
$ adb shell su -- dumpsys window

dumpsysの後にwindowと書かれています。
そして、その後にはWINDOW_MANAGERとも書かれています。
これはContext#getSystemService()で取得できる「○○マネージャー」に相当する文字列を指定できるのではないかと考えました。

Context | Android Developers

dumpsysの後に、↑ここで書かれている文字列を指定してみました。
shell@android:/ $ dumpsys window # → OK
shell@android:/ $ dumpsys layout_inflater # → NG
shell@android:/ $ dumpsys activity # → OK
shell@android:/ $ dumpsys power # → OK
shell@android:/ $ dumpsys alarm # → OK
shell@android:/ $ dumpsys notification # → OK
shell@android:/ $ dumpsys keyguard # → NG
shell@android:/ $ dumpsys location # → OK
shell@android:/ $ dumpsys search # → OK
shell@android:/ $ dumpsys vibrator # → OK?
shell@android:/ $ dumpsys connection # → NG
shell@android:/ $ dumpsys wifi # → OK
shell@android:/ $ dumpsys input_method # → OK
shell@android:/ $ dumpsys uimode # → OK
shell@android:/ $ dumpsys download # → NG

結果が返ってきたものは「OK」、エラーになったものは「NG」としました。
幾つかはエラーになってしまいましたが、だいたいのものはこれで情報が取得できるようです。
出力される情報の意味もわかっていませんが、dumpsysはこうやって使うんですね。
英語をちゃんと読めばこういうことも書いてあるんでしょうか…。
こういったコマンドも開発には役立ちそうなので、使い方を覚えてみるのも良さそうですね。


タグ:android ADB dumpsys
posted by t2low at 01:26| Android

2013年12月16日

[Android] Android4.2.2での9patch画像表示不具合?

9path画像をTextViewの背景画像として使用していたのですが、Android4.2.2の端末で正しく表示されない現象が発生しました。
以下のような画像を表示した際に、中心部分の赤丸が右下に寄ってしまうのです。

flag.9.png

ヤバそうな気配を感じましたが、幸い回避方法を公開してくれている方がいました。


Android - 9patchでStretchable Areaを横2箇所設置時に同幅にスケールしない問題の解決方法 - Qiita [キータ]


この記事のとおりに画像の幅を奇数にしたところ正しく表示されるようになりました。

HTL22(4.2.2)(上が偶数サイズの画像、下が奇数サイズの画像)
htl22_ss.png

ISW12HT(4.0.3)(上が偶数サイズの画像、下が奇数サイズの画像)
isw12ht_ss.png

画像はありませんがNexus7(2012)(4.4.2)では、偶数サイズでも正常に表示されました。
Android4.2.2の不具合なのでしょうか。


あと、この件とは関係ないのですが、上記画像に「J」という文字が表示されていますが、どれも「Content Area」に表示されていません。
「Content Area」は「Stretchable Area」と重ならないといけないのでしたっけ。
テキトーな知識で進めるからこうなるのでしょうね…。


タグ:android 9patch
posted by t2low at 23:00| Android