cocos2dで、TableViewを実現する方法(CCUIViewWrapper編) ・・・(または、cocos2dでUIViewを使う方法)

cocos2dを利用してGameを作成しているのですが、得点のランキングやアイテムの一覧等、スクロールを伴うTableViewを表示したいというニーズは結構あります。

cocos2dには、標準ではテーブルビューを扱うクラスがないので、いくつか方法を調べてみました。

実現するには大きく分けて2つの方法があります。

①iPhone標準のTableViewをラップして、それをcocos2dのレイヤーにaddする。

②cocos2dの拡張であるSWTableView(CCTableView)コンポーネントを利用する。

どちらもそれぞれ長所と短所がありましたので、利用シーンに応じて使い分けるのが良いと思います。簡単にそれぞれの長所と短所を挙げてみます。

①ラップするだけでcocos2dに追加できるので、簡単。ただ、描画ロジックが異なるため、シーン間のトランジション(Transition)で、オブジェクトが残る。

回避方法は見つけたが、シーンの描画パフォーマンスが若干落ちる。

②cocos2dと同じレイヤーで描画されるので、表示が高速。そのまま使用すると、メモリリークが発生し、スクロールのたびに遅くなる。

回避方法は見つけたので、それに従って、ソースをいじる必要あり。

これから2回に渡って、両方法の実装について記述したいと思います。まずは①の方から。

cocos2dを利用してGameを作成する際には、Sceneの描画がOpenGLベースで行われるため、UIViewを継承したiPhone標準のパーツをSceneにaddすることができません。UITableViewもUIViewを継承していますので、同じ問題に突き当たります。

Sceneとは別のレイヤーで使う分にはそれで特に問題ないのですが、Sceneに、標準のcocos2dオブジェクトであるCCSpriteのように突っ込んで描画させたいとなると、ひと手間かける必要があります。

CCUIViewWrapperというUIViewのラッパークラスを公開されている方がいらっしゃるので、それを利用させてもらいます。

その名のとおり、UIViewをラップするクラスですので、この方法だと、UITableViewのみならず他の色々なUIViewの継承クラスをaddできることになります。

利用方法はシンプルで、下記のようにCCUIViewWrapperの「wrapperForUIView:」を使って、UIViewのインスタンスを包んであげます。

[CCUIViewWrapper wrapperForUIView:(UIViewのインスタンス)]

CCUIViewWrapperはCCSpriteのサブクラスとなっていますので、後は、通常のCCSpriteと同様に、cocos2dのレイヤーにaddすることができます。

下記の例を参考に、UIViewとして、UITableViewのクラスをラップしてあげれば、テーブルが描画されることが確認できます。

【例】

UIView *myView = [[[UIView alloc] init] autorelease];
CCUIViewWrapper *uiWrapper =

[CCUIViewWrapper wrapperForUIView:myView];
uiWrapper.contentSize = CGSizeMake(300, 150);
uiWrapper.position = ccp(64,64);
[self addChild:uiWrapper];
[uiWrapper setVisible:NO];

実際に動かしてみると、テーブルが描画されました!ただ、Transitionを使用して、別のシーンに遷移させると、ちょっと奇妙な動きをしませんか? そうです。通常のcocos2dのオブジェクトが流れるように遷移するのに対して、ラップしたテーブルオブジェクトは当シーンのインスタンスが破棄されるタイミングまで残り続け、最後に「パッ」と消えてしまいます。 これではcocos2dの魅力の一つである、豊富な遷移エフェクトを使えない!ということで、自分なりに回避策を考えてみました。他にいい方法があれば、ぜひ教えてください。 なぜ、このような動きをしてしまうのでしょうか。動きを追ってみると、どうも、ラップしたオブジェクトの再描画が行われていないようです。 そのため、明示的にそのオブジェクトを毎フレーム描画してあげればよさそうだということが分かりました。 cocos2dで、毎フレーム呼ばれるメソッドを定義するには、CCLayerのinitで、

-(void)step:(ccTime *)dt
{
[uiWrapper updateUIViewTransform];
[uiWrapper setVisible:YES];
}

ラップしたオブジェクトの「updateUIViewTransform」を毎フレーム呼ぶことで、Transition時の動きが反映されるようになります。

[uiWrapper setVisible:YES] の行は必須ではありませんが、initの[uiWrapper setVisible:NO] と対になっていて、初めは不可視にしておき、初めてstep:が呼ばれたときに見えるようにすると、動きが自然に見えたために記述しました。

毎フレーム、ViewのTransformを呼ぶので、描画パフォーマンスが若干落ちるのが難点ですが、これだけの記述でiPhoneの標準Viewが利用できるので、利用箇所を選べば、少ない手間で機能を実装することができると思います。

コラム

cocos2dでゲームを作る際に参考にした本です。初心者用、中級者用とありますので、参考にしてください。私には非常に役立ちましたよ!

cocos2dで作る iPhone&iPadゲームプログラミング cocos2dで作る iPhone&iPadゲームプログラミング

これは非常にいい本です。画面遷移の基本から応用まで、体系だって解説がなされており、ゲーム作成時に何度も読み返しました。パフォーマンスを考慮したコーディングや物理エンジンについても言及があります。

 

cocos2d for iPhoneレッスンノート cocos2d for iPhoneレッスンノート

cocos2dを使ってゲームを作るのが初めての人に最適です。いくつかのサンプルのプロジェクトとその解説があり、それをもとに、簡単なゲームは作れるようになるでしょう。初心者がつまづきやすい、AppStoreへの申請方法も例示されています。初めてゲームをリリースするときに参考にしました。

 

Learning Cocos2D: A Hands-On Guide to Building iOS Games with Cocos2D, Box2D, and Chipmunk Learning Cocos2D: A Hands-On Guide to Building iOS Games with Cocos2D, Box2D, and Chipmunk

cocos2dで物理エンジンを利用したゲームを作る際に参考になります。英語ですが、物理エンジンを解説した本は少ないため、貴重です。

 



こんな記事も関係あるかも。読んでみてね。

コメントを残す

サブコンテンツ

このページの先頭へ