cocos2d-x 再帰呼び出しについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ponkikki
記事: 7
登録日時: 10年前

cocos2d-x 再帰呼び出しについて

#1

投稿記事 by ponkikki » 10年前

お世話になっております。
現在cocos2d-xを用いて、ゲームを制作しているのですが、
アニメーションを作ろうと、作成した関数内でCCSequenceクラスをインスタンス化しました。インスタンス化したものにデータをセットしていき、そのインスタンスは、また新しいCCsequenceクラスをインスタンス化してデータをセットするのに使うので、作成したインスタンスを同じ関数内に渡して、再帰的に呼び出しています。
そして、最終的に出来上がった、CCsequenceクラスのインスタンスをアニメーションしたいスプライトに適用させようとしました。
以下のようにコードを組みました。

コード:

//再帰関数
cocos2d::CCSequence* HelloWorld::sequencer(cocos2d::CCSequence *seq)
{
    
    if (count != moveArray->count()){
        CCSequence *seqN = CCSequence::create(seq,(CCTargetedAction*)moveArray->objectAtIndex(count),NULL);
        count++;
        //②
        sequenser(seqN); //①
    }
    
    return seq;
    
}

main(){

CCSequence *resultSeq = sequencer(seed);

Mysprite->runAction(resultSeq);

}
デバッカでseqNにちゃんとデータがセットされているか確かめたら、
seqN
→m_pActions
→→[0] = 0x14209850(CCSequence*)
→→[1] = 0x1420a8c0(CCTargetedAction*)

のように意図した通りにデータがセットされていました。
ですが、
上記コードの①のところで再帰呼び出しをした後、seqNのアドレスを受け取ったseqの中身を確認してみたところ
先ほどまで入っていたアドレス 0x14209850 と 0x1420a8c0が無くなっていました。その代わりに、全く知らないアドレスが入っていました。
なので、ちゃんとしたseqが生成されないまま、アニメーションしたいスプライトに適用させても上手く挙動しませんでした。
アドレスが消滅する①の直前の②の部分で
Mysprite->runAction(seqN)
のようにしてみたら、アニメーションがちゃんとされました。
なので、①の部分でおかしなことになってしまったことがわかりました。
何故このようなことが起きてしまったのでしょうか?
使用している言語はC++です。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: cocos2d-x 再帰呼び出しについて

#2

投稿記事 by h2so5 » 10年前

これだけではちょっと分からないです。
そもそもこのようなCCSequenceの使い方が想定されているかが不明ですし、再帰を使う理由もよく分かりません。
あと、コードを見て疑問に思ったのはcountがどのタイミングでリセットされているのかという所です。

ponkikki
記事: 7
登録日時: 10年前

Re: cocos2d-x 再帰呼び出しについて

#3

投稿記事 by ponkikki » 10年前

ご回答ありがとうございます。
わかりにくくて申し訳ありません。
簡単に以下のようなことをシミュレートしたくて、コードを組みました。

コード:


   
    CCSprite *MySprite = CCSprite::create("sequence_0000.png");
    MySprite->setPosition(ccp(800,400));
    this->addChild(MySprite);
    
    CCAnimation *animation = CCAnimation::create();
    animation->setDelayPerUnit(0.1);
    animation->addSpriteFrameWithFileName("sequence_0001.png");
    animation->addSpriteFrameWithFileName("sequence_0002.png");
    animation->addSpriteFrameWithFileName("sequence_0003.png");
    animation->addSpriteFrameWithFileName("sequence_0004.png");
    animation->addSpriteFrameWithFileName("sequence_0005.png");
   
    CCAnimate *animate = CCAnimate::create(animation);
    
   
    
    
    CCSprite *MySprite2 = CCSprite::create("sequence_0000.png");
    MySprite2->setPosition(ccp(800,500));
    this->addChild(MySprite2);
    
    CCAnimation *animation2 = CCAnimation::create();
    animation2->setDelayPerUnit(0.1);
    animation2->addSpriteFrameWithFileName("sequence_0001.png");
    animation2->addSpriteFrameWithFileName("sequence_0002.png");
    animation2->addSpriteFrameWithFileName("sequence_0003.png");
    animation2->addSpriteFrameWithFileName("sequence_0004.png");
    animation2->addSpriteFrameWithFileName("sequence_0005.png");
    
    CCAnimate *animate2 = CCAnimate::create(animation2);
    
    
    
    CCSprite *MySprite3 = CCSprite::create("sequence_0000.png");
    MySprite3->setPosition(ccp(800,600));
    this->addChild(MySprite3);
    
    CCAnimation *animation3 = CCAnimation::create();
    animation3->setDelayPerUnit(0.1);
    animation3->addSpriteFrameWithFileName("sequence_0001.png");
    animation3->addSpriteFrameWithFileName("sequence_0002.png");
    animation3->addSpriteFrameWithFileName("sequence_0003.png");
    animation3->addSpriteFrameWithFileName("sequence_0004.png");
    animation3->addSpriteFrameWithFileName("sequence_0005.png");
    
    CCAnimate *animate3 = CCAnimate::create(animation3);
    
    //各スプライトに適用するアクションを格納しておく配列です。
    CCArray *array = CCArray::create();
    
    array->addObject(animate);
    array->addObject(animate2);
    array->addObject(animate3);


  
  
 //各スプライトにアクションを適用 
    CCTargetedAction *tMove0 = CCTargetedAction::create(MySprite, (CCAnimate*)array->objectAtIndex(0));
    
    CCTargetedAction *tMove1 = CCTargetedAction::create(MySprite2, (CCAnimate*)array->objectAtIndex(1));
    
    CCTargetedAction *tMove2 = CCTargetedAction::create(MySprite3, (CCAnimate*)array->objectAtIndex(2));
    
    //各スプライトのアニメーションの順番を決める
    CCSequence *seq = CCSequence::create(tMove0,NULL);
    CCSequence *seq2 = CCSequence::create(seq,tMove1,NULL);
    CCSequence *seq3 = CCSequence::create(seq2,tMove2,NULL);
    
    MySprite->runAction(seq3);

このコードでは、まず3つのスプライトそれぞれに適用するアクションを用意します。(animate,animate2,animate3)
次に、それぞれのスプライトに用意したアクションを適用していきます(tMove0,tMove1,tMove2)
そして、CCSequenceでアクションの順番を決めます。
このコードではちゃんと3つのスプライトが順番にアニメーションされました。
先ほどのコードに書いてあったmoveArrayには、今書いたコードのtMoveが適用したいスプライト分大量に格納されていて(今のコードだと3つ)、さらにスプライトの数もゲームを進行している中で変わってくるので、CCSequenceに渡す引数の数が可変的に変わっていきます。
(あるときはCCSequence *seq = CCSequence(tMove0,tMove1,tMove2,tMove3,tMove4,NULL)だっだり、また或る時はCCSequence *seq = CCSequence(tMove0,tMove1,tMove2,NULL)だったり)
なので、先ほどのコードのような感じにしてみました。
countは関数を抜けた後に初期化しています。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: cocos2d-x 再帰呼び出しについて

#4

投稿記事 by h2so5 » 10年前

CCSequence::createにCCArrayを渡すことができるので、数を可変にしたいのであればCCArrayを使ったほうがいいと思います。
http://www.cocos2d-x.org/reference/nati ... 83a7b1d3eb
http://www.cocos2d-x.org/wiki/CCArray

ponkikki
記事: 7
登録日時: 10年前

Re: cocos2d-x 再帰呼び出しについて

#5

投稿記事 by ponkikki » 10年前

CCArrayで単純に渡せたのですね。
なんとか自分の意図した通り動きました。
ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る