2009年8月29日土曜日

どのクラスのインスタンスを作っているかに注意しましょう・・・

突然ですが問題です。以下のソースはコンパイルできますがバグがあります。
http://github.com/akisute/MyShooting/blob/4570825e7384157d3572b689cc23f9bb3acc0b82/Classes/MSTGObjectFactory.m

さて、どこが間違っているでしょうか?




■なんて突然言ってもわからないですが
正解はこちら。
+ (MSTGObject *)cannon
{
// ここが間違い。MSTGObjectではなくてMSTGCannonのインスタンスを生成する必要がある
MSTGObject *object = [MSTGObject spriteWithFile:@"cannon.png"];
return object;
}
で、MSTGObjectはライフがデフォルトゼロなので、生成された瞬間に即死して画面から退場してくださるという悲しいバグが。うーむJavaではこんな情けないバグ作ったりはしないのですが・・・ともかくこれで一歩前進。

イニシャライザとかコンポジットとか考えた結果がこれだよ!

前回の記事から引き続きCocos2Dでちょこちょこアプリを書いてます。
ソースコードも公開してみました。
http://github.com/akisute/MyShooting/tree/master


■で、あれからどうなった
全面作り直しorz

コーディングを進めていくうちに次々と問題点が噴出してきたのですが、その中でもこれはまずいと思ったのが2点。


■問題点その1.オブジェクトリストの管理が面倒
画面への描画を担当してくれるCocosNodeにSpriteを登録するのとは別にオブジェクトを管理するためのマネージャクラスを持っていたため、オブジェクトを追加するたびにこんなコードを書かなくちゃいけなかったんです。
// MSObjectの親ノード(Layer)の中で・・・
MSObject *object = [[[MSBullet alloc] initWithPosition:ccp(100,100)
angle:0.0
speed:200.0] autorelease];
[self addChild:object.node];
[[MSObjectManager sharedInstance] addObject:object
forOwner:kMSObjectOwnerEnemy];
これだけならまだしも、今度は消すのが面倒。
[self removeChild:object.node];
[[MSObjectManager sharedInstance] removeObject:object];
どちらかを消し忘れるとエラーになりますし、ループ中にMSObjectManagerからインスタンスを消すとエラーになったりと結構散々です。この問題点1はまだCocosNodeにaddMSObject:forOwner:とかremoveMSObject:みたいなメソッドを追加すればなんとか対応できたのですが、もっと深刻な問題点2が。


■問題点その2.オブジェクトクラスの中でscheduleが使えない
これで完全に積みました。要するにこんなコードが書けないわけです。
// MSObjectの中で
// 毎フレームごとに呼び出されるメソッドを定義する
- (void)onFrame:(ccTime)dt
{
// 死亡判定してみたり
// 衝突判定してみたり
// ライフを回復したり無敵フレームを設定してみたり
}

- (id)init
{
if(self = [super initWithFile:@"ship.png"])
{
// sceduleメソッドはCocosNodeのメソッドなのでこうやって登録する
// しかしschedule出来るのはCocosNode自身が持っているメソッドのみ
// そのためこの方法でメソッドを登録しても
// 実行時に「spriteにはonFrameなんてメソッドがありません」とエラーになる
[self.sprite schedule:@selector(onFrame:)];
}
return self;
}
これを回避するにはMSObjectにスケジューラを自分で実装する必要が出てきて・・・ってそれもうCocos2dでやる意味なくね?ということで結論。Cocos2dはCocosNodeを継承して使え。


■作り直しの結果
MSObjectをコンポジットではなくSpriteのサブクラスにして解決。ついでに名前をMSTGObjectに改名しました。イニシャライザが漏れてややこしいと言う問題が発生してしまいますが、そこは以下のようにファクトリクラスを使って解決。
MSTGObject *ship = [MSTGObjectFactory ship];
MSTGObject *bullet = [MSTGObjectFactory bullet];

Macbook Air (Early 2008)にMac OS X 10.6 Snow Leopardをインストールしてみた


最初は見送ろうかと思っていたのですが、Twitterのタイムラインを眺めていると「速い!」とか「良い!」との声が多数見受けられ、居ても立っても居られず仕事帰りにさくっと買ってきてさくっとインストールしてみました。
iMacとMacBook Airの2台あるので、まずはAirのほうに試しにインストール。

(2009/08/30追記) QuickSilverが動作するようになったので追記しました。
(2009/09/13追記) 64bit Kernel起動を試してみたので追記しました。


■インストールにかかる時間
大体40分〜50分ぐらいでした。OKボタンを数回押して放置するだけ。簡単です。


■インストールしてみて第一印象
確かに「速い!」です。もっとも印象に残るのが再起動やスリープ→復帰。また、アプリの起動や終了も明らかに速くなっています。具体的にはDockの上で4回はねないと起動しなかったアプリが1回はねただけで起動したりします。

それから地味に嬉しいのが入力ソースをアプリごとに保持するオプション。10.4までは可能で10.5で廃止されたオプションですが、10.6でめでたく復活しました。QuickSilverとTextMateは英字でTweetieは日本語でとか保持してくれるのがいい感じ。
http://d.hatena.ne.jp/Psychs/20090828/1251467136

そして何よりトップにも載せましたが4本指スワイプが使えるようになりました。最近のMacBookでは当たり前でしたが、なにせ私が使っている初代MacBook Airはこのオプションが無くてずいぶん肩身の狭い思いをしていたので嬉しくてたまりません。もうこれだけのために3000円払ってもいい。


■使えて良かった開発系のツール一覧
Firefoxは完全にそのままOK。Multiclutchの設定もそのまま使えました。
XcodeとiPhone SDKは専用の物をインストールしなおしてすぐにそのままビルド出来るようになりました。こちらも問題なし。
TextMate問題なし。OmniFocusやEvernoteも問題なさそうです。DropBoxも動いています。Growlも意外なことにきちんと動作しています。日本語入力のATOK2008 for Macも大丈夫です。
最大の問題としてMacPortがバージョン1.7系だと動作しませんが、つい先ほど公式の1.8インストーラがリリースされたため、こちらからSnow Leopard用の1.8をインストールしなおし、sudo port uninstall installedしてから必要な物を再度installし直すことで復旧できました。
QuickSilverもそのままでは設定画面が壊れて表示されなくなってしまいますので、最新のβビルドをこちらのページ(http://code.google.com/p/blacktree-alchemy/downloads/list)からダウンロードして入れ直すことで無事使えるようになりました。


■使えなくなってしまったアプリ一覧
SIMBLを使っていたアプリは32ビットモードで起動しても使えなくなっているようです。たとえばTerminalColourは完全にダメ。MenuMetersもダメです。QuickSilverも起動するだけなら問題なさそうですが、設定画面を開いた瞬間にフリーズして落ちてしまいます。
幸いにしてあまりSIMBLに依存した生活をしていなかったおかげで、ほとんど被害無く過ごすことが出来ています。


■64bit kernel起動は?
そもそもMacBook Air(Early 2008)は64bitカーネルのサポート対象外なのですが、ダメ元で試してみました。
結果、Boot modeは64bitにできましたが、実際に立ち上がるカーネルは32bitになってしまいました。やっぱりダメみたいです。あと、EvernoteとFirefoxのEvernoteプラグインの挙動が変になってしまったため、すぐに戻しました。


■まとめ
普通に使っている方にはアップグレードの手間もほとんど無くいい感じです。特に初代MacBook Airをお使いの方は是非アップグレードをお勧めします。逆にSIMBLやSafariプラグインに依存した生活をお送りで、ユーティリティが動かないと困る方はしばらくアップグレードを見合わせた方がよいかもしれません。

あと各所でインストールディスクが傷だらけでインストールできないという症例が報告されておりますのでご注意ください。最悪の場合はApple Storeに持ち込めばたぶん交換してくれます。