だいたい47度

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PageTop

Box2Dでbody破壊後もsprite画像を描画(cocos2d)

cocos2dのBox2Dで、PhysicsSpriteのbodyをDestroyした後も画像を描画したいときについて。

前提 PhysicsSpriteとは
PhysicsSpriteは、物理シュミレーションを行うbodyにSprite画像を貼り付け、bodyが動くのにあわせてSpriteも動くようにする便利なクラスです。cocos2DのBox2Dプロジェクトを作成すると自動的に生成されます。

bodyに画像がついていく動きはnodeToParentTransformで実装されています。PhysicsSpriteにsetPhysicsBodyでセットしたbodyにあわせて画像が動きます。worldをstepさせるだけで画像の回転やら移動やらを良い感じにやってくれるので、非常に便利です。

PhysicsSpriteは本来CCSpriteの子クラスですが、僕はCCSpriteを継承させたGameSpriteというクラスを作り、それを継承させてPhysicsSpriteを作る形にしています。GameSpriteクラスは、アニメーションや状態の遷移などをしやすくしたクラスでLearning Cocos2Dから学びました。詳しくは過去記事参照。CCSpriteの子・孫クラスなのでCCSpriteBatchNodeで管理します。

Body破壊後に画像を描画する方法
ゲームを作っているうちに、PhysicsSpriteのbodyを破壊しながらも、画像は表示したいことがあります。例えば、敵を倒したとき、bodyはすぐに消して(破壊して)ゲームに影響を与えないようにしつつ、画像はCCBlinkで点滅させながらFadeOutしたいときなどです。

しかし、単純にbodyの破壊だけを行うとぬるぽで落ちます。nodeToParentTransformではbodyの位置を取得するため、body破壊後に呼び出してはいけません。

対応としては単純で、PhysicsSpriteにbool型プロパティを一つ持たせ、nodeToParentTransformの先頭で確認してあげればいいだけです。bodyの破壊時にはそのプロパティをONにし、以降nodeToParentTransformが空ぶらせてあげる。

-(CGAffineTransform) nodeToParentTransform
{
  if (_isNeedToTransform == NO) return transform_;
 
  //


静的Body注意
実は、b2_staticbodyをdestroyして画像をそのままにしても、落ちません。調べてないですけど、おそらくsleep状態のbodyはnodeToParentTransformが呼ばれないのではないでしょうか。

そのため、僕はゲームをある程度作るまで上記の問題に気づきませんでした。僕が作っていたゲームでは、b2_staticbodyが破壊される時にアニメーションを描画するようにしていましたが、問題なく動きました。一方でdynamicbodyの破壊は同時にvisible = NOとなるようになっていたので、問題の発覚が遅れたのです。

そしてあるとき、とても変な動きに気づきました。b2_staticbodyの破壊をしながら、一秒に数回b2_dynamicbodyをcreateする状況になったとき、b2_dynamicbodyの画像が、破壊されたb2_staticbodyのものになっていたのです。静的なものの画像が、すごい勢いで動きまわってる……。最初はCCSpriteBatchNodeの問題かと思ったのですが、b2_staticbodyとb2_dynamicbodyを別バッチノードに登録しても問題は再発しました。

静的物体のボディに上述の制御をいれたところ、問題が生じなくなりました。具体的な原因はわからないのですが、破壊と生成が同時に起こってbodyのポインタがずれるような形になったのかな。いずれにせよ、bodyがNULLな状態でnodeToParentTransformが呼ばれうるのは良くないです。


なんか最近、書き始めたときの想定と全然違う記事があがるな……。
関連記事
スポンサーサイト

PageTop

コメント


管理者にだけ表示を許可する
 

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。