cocos2d-xでゲームを作ろう! 第十回 キャラクタを動かそう2編
さて、前回は結構自信満々だったんですが、あえなく撃沈。
まぁ、プログラムにバグはつきものということで、調査してみましょう。
コールスタックを確認しよう!
さて、エラーの内容は、以下の箇所の「m_pActionManager」がNULLということなんですが。。。
このCCNodeがどこかで解放されたということでしょうか?
さて、コールスタックはどうなっているのでしょう。以下、通りです。
「void Human::walkRamdom(void)」が動作していることから考えると、移動のアニメーションの契機で問題が発生しているようですね。
「pSprite->runAction(pAction)」の呼び出しがまずいようですねー。
まっさきに思いつくのは、pSpriteがリリースされていると思いますよね。でも、pSpriteがリリースされているとrunAction()のメソッドもコールできないでしようし。
まず、このpSpriteのアドレス以下のメソッド毎に出力させてみました。
Cocos2d: Human::addParent pSprite 0xb451ed0 Cocos2d: Human::addParent pSprite 0xb452c20 Cocos2d: Human::addParent pSprite 0xb4538d0 Cocos2d: Human::walkRamdom pSprite 0x3f800000
あ!なんか、Human::walkRamdom()の時のpSpriteのアドレスが違う。。。今回、3つのキャラクタを登録しているので、Human::addParentが3回コールされるのは想定通りです。その後のHuman::walkRamdom()で表示されるpSpriteは、このうちのどれかになるはずですが、うーん。
そもそも、このHuman::walkRamdom()は、どのインスタンスからコールされているのでしょう。
では、thisポインタのアドレスを表示してみましょう。
Cocos2d: Human::addParent this 0x9e84510 Cocos2d: Human::addParent this 0x9e93340 Cocos2d: Human::addParent this 0x9e93ef0 Cocos2d: Human::walkRamdom this 0x9e84590
やっぱりです。最後にコールされた「Human::walkRamdom()」は、あらかじめ作成したHumanインスタンスのどれでもないです。だれなんでしょう?
Cocos2d: Human::addParent this 0x9b2e720 Cocos2d: Human::addParent this 0x9b3d550 Cocos2d: Human::addParent this 0x9b3e100 Cocos2d: HelloWorld::init() 0x9b2e7a0 Cocos2d: Human::walkRamdom this 0x9b2e7a0
わー!HelloWorldと同じインスタンスのアドレス指しています。どういうこと?「schedule()」は以下のように登録しています。
あっ!schedule()で渡したメソッドは、schedule()を登録したインスタンスからコールされるんですね。。。なるほど。。。
Humanクラスのインスタンス経由で呼び出したい場合は、schedule()はHumanクラスのメソッドをコールしないといけないんですねー。
ということになると、schedule()はCCNodeのメソッドだから、HumanクラスはCCNodeを継承しないといけませんね。
では、早速修正!
まずは、CCNodeを継承して、schedule()の呼び出しをHumanクラスのインスタンス経由にするように修正します
さぁ、どうだ!
ん、あれ、落ちなくはなったけど、移動してくれません。
あ、cocos2d-xはシーンノードで構築されているから、schedule()の呼び出しもシーンとの関連がないと動かないのかもしれません。
今は、Humanは、どのシーンとも関連をもっていません。では、シーンにHumanインスタンスを登録しましょう。
歩いたよ〜