記事一覧

Making an introduction clip

I want to make a short clip to introduce my app on the web and need to make the scene to show how the app works on your real device.
If you only need the pure digital image on the screen you can screen-capture the emulator window with certain kind of freeware, but to show how to operate by your finger and how the accelerometer works you have to shoot the real device by video camera.
It's not easy to hold the device steadily (to use accelerometer you have to hold it floating from the ground) and cast the light without undesirable reflection.
Hmm...

Appの提出は

開発者がそのまま iTunes Connect で提出する場合は手順通りで良いわけですが(それでもけっこう面倒ですがね)、提出する人が別だと大変ですね。

提出用の最終ビルドは、Developer Program に Team Agent として登録している人しか作れないわけですが、Team Agent ってそもそも会社を代表して Apple と契約した人なわけで、そういう人ってわりと事務方の人間であることが多いんじゃないでしょうか。
その人にソース渡してコンパイルしてください、ってのは酷な話ですわ。

似たような状況にある方々は結局みんな、秘密鍵を受け渡しして「なりすまし」で切り抜けるというパターンに落ち着いているのではないかと推測します。
ちなみに、その場合に使う方法手順はこちら。「バックアップまたは環境移行」のための方法。これを裏技的に使うわけですね。
http://developer.apple.com/iphone/library/documentation/Xcode/Conceptual/iphone_development/128-Managing_Devices/devices.html

アイコンが急に真っ白に!

今まできちんと表示されていたアプリのアイコンが急に真っ白に。
なぜだ!!?? ターゲットの設定とかInfo.plistとかいじったからその影響か!?
と思って悩むこと十数分。

なんのことはない、ちょっと前にアイコンのデザインを変更したときに間違えて psd データを Icon.png として保存してました;
たまにやるんだよなコレ;

バージョン違いのバイナリを作る

iPhoneで、有料バージョンと無料バージョンみたいな複数のバージョンを作りたい場合、それぞれ用のバイナリを作らなければいけないわけですが、そんな場合は、XCodeでターゲットを2つ作って、それぞれに "OTHER_CFLAGS" を設定すればいいんですね。

http://www.codza.com/free-iphone-app-version-from-the-same-xcode-project

これでソースの冒頭に #define FREEVERSION とか宣言したのと同じ事になるので、あとはソース中に適宜
#ifdef FREEVERSION
...(フリー版特有の処理)
#endif
とか書けばよいです。

ここで注意なのが、ターゲット編集時、編集対象となる構成を「すべての構成」にして Debug/Build/その他(Ad-hoc用など) すべてについて変更しておかないと、Debug構成のときは無料バージョン設定になってくれるけど、Releaseにしたら急に有料バージョン設定になっちゃって「???」な事態になります。

あと、フラグの書き方は、
-D(フラグ名)
で、フラグ名が大文字だと
-DFREEVERSION
とかくっついた格好になるので -D を見落としやすいかもしれません。

NSTimer

うーん、NSTimerは微妙に難しいなぁ〜
インスタンスは保持したまま停止/再開ってどうやるんだ。
invalidateするとインスタンス自体消滅しちゃうっぽいし。
スケジュールをずっと先に設定するとか?
それもなんか不毛なのでひとまず自前で bool timerWorking なるものを用意して timerCallback の冒頭で
if(!timerWorking){return;}
とかしてある。なんか納得いかんけどひとまずそんなにパフォーマンスも落ちてないっぽいしいいかな・・・・

そもそも cocosNode 絡みだったら schedule: が使えるんだけど、シーンを越えて保持したいオブジェクトだから cocosNode に紐付いてると不便なんだよねえ。


('10 8/2追記)
invalidate 済みの myTimer へメッセージを送ろうとしたときに Bad Access になるのを回避したいだけなら
[myTimer invalidate];
した後に
myTimer = nil;
とすれば良いらしい。ウチの場合もこれで良かったんだな・・
http://www.iphonedevsdk.com/forum/iphone-sdk-development/22040-exe-bad-access-error.html

Landscape な cocos2dのウィンドウにUITextFieldを貼り付ける

fieldWidth, fieldHeight はテキストフィールドのサイズ、
fieldX, fieldY はLandscape状態で画面左上から見た座標。M_PIは定数πでありんす。

UITextField* field = [[UITextField alloc]
initWithFrame:CGRectMake(320-fieldY-fieldHeight, fieldX, fieldHeight, fieldWidth)];
field.text = @"text";
field.transform = CGAffineTransformMakeRotation(2.0/M_PI);
field.bounds = CGRectMake(fieldX, fieldY, fieldWidth, fieldHeight);
[[[Director sharedDirector] openGLView] addSubview:(UIView*)field];

UITextField の貼り付け自体はあっけないくらい簡単だった。
でも Landscape 方向だととたんにややこしくなりますね。
座標が左下原点ってのも非常に馴染みがなくてやりずらい・・・

あと、boundsの設定は自信無し; とりあえず動いているので放置してあるが・・・

TouchDispatcher @ cocos2d

cocos2d の TouchDispatcher を使ってタッチの振り分けをしようと思ったらうまく動かない。
cocos2dフォーラムとかも調べてみたがだいたいありがちな対策はとってある・・・
と、途方にくれていたのだけど、突然 priority の値設定がテキトーだったことに気づいていじってみたら動いた。
どうやらディスパッチを特に指定しないで受け取った場合の priority が 0 で、これより優先する場合は負の数を指定しないといけないようですね。というわけで、
[[TouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
が正解か。

あと、ここでswallowsTouchesを指定するとすべてのタッチが飲み込まれてしまうかというとそうではなくて、
ccTouchBegan で return NO; を返すと優先度の低いデリゲートへとタッチをスルーできるようだ。

provisioningの更新

三ヶ月ごとに切れる開発者用provisionですが、更新の手続き自体は、
iPhone Provisioning Portal で Provisioningのページに行って renew ボタンを押す → 新しい .mobileprovision が出来たらダウンロード、なんですが、
(参考: http://iced.tea-nifty.com/lemon/2009/10/provisioning-pr.html
僕が一瞬つまづいたのが、

(1)期限が切れてからでないと renew できない(微妙に不便;)
(2)XCode上だけでなく、iPhone上でも期限切れした .mobileprovision を削除しないと、そっちを読みに行ってしまって期限切れエラーになる

の2点。 (1)の仕様のせいで出かける間際に作業するハメになったところに(2)の仕様で引っかかってえらい焦った;

むむ。

TilemapAtlasはもうdepricatedだったのね;
でもTMXTilemapが思いのほか使いやすくて良かった。

なるほど

cocos2dで別のシーンに移るときは、もろもろdeallocされるのだけど
加速度センサのdelegateは存続するので放っておくと
クラッシュするわけですね。
シミュレータだと動いてたのがデバイスで突然動かなくなったから
何事かと思ったですよ。
ちゃんと
[UIAccelerometer sharedAccelerometer].delegate = nil;
とかしておかないといけないのね。