ShineHe
ShineHe

Reputation: 13

Cocos2dx I got something wrong with CCArray

void SkillManager::initBuff() {
CCObject* pobj;
CCLog("in init Buff");
CCARRAY_FOREACH(mSkills, pobj) {
    Skill* skill = (Skill*) pobj;
    CCLog("skillDuration:%d,skillIndex: %d",skill->mSkillDuration,skill->mSkillDebuffTag);
    if (skill->mSkillDuration <= 0) {
        mSkills->removeObject(skill);
    }
    else
        skill->initBuffData();
}

}

I create a CCarray mSkills to save my skills,when the skill's duration is over,i remove it from the array,every time before check one skill's duration i will cclog it's duration and debuff tag.I will also add some skill in array at any time.

In most cases, the code works well . But a occasional error is is an obsession for me.

In normal times the log is :

Cocos2d: in init Buff

Cocos2d: skillDuration:6,skillIndex: 203

Cocos2d: duration:6

Cocos2d: in init Buff

Cocos2d: skillDuration:5,skillIndex: 203

Cocos2d: skillDuration:2,skillIndex: 0

Cocos2d: in init Buff

Cocos2d: skillDuration:4,skillIndex: 203

Cocos2d: duration:4

Cocos2d: skillDuration:1,skillIndex: 0

Cocos2d: skillDuration:0,skillIndex: 0

In error log is :

ocos2d: in init Buff

Cocos2d: skillDuration:1,skillIndex: 0

Cocos2d: skillDuration:6,skillIndex: 203

Cocos2d: duration:6

Cocos2d: in init Buff

Cocos2d: skillDuration:0,skillIndex: 0

Cocos2d: skillDuration:2,skillIndex: 0

Cocos2d: skillDuration:1,skillIndex: 0

Cocos2d: in init Buff

Cocos2d: skillDuration:5,skillIndex: 203

Cocos2d: skillDuration:0,skillIndex: 0

Cocos2d: skillDuration:0,skillIndex: 0

Cocos2d: in init Buff

Cocos2d: skillDuration:4,skillIndex: 203

Cocos2d: duration:4

Cocos2d: skillDuration:2,skillIndex: 0

that means the skill which index is 203 have changed , or CCArray got wrong data at this time? But i can see in next time init Buff the 203's data is correct.

I found when using CCARRAY_FOREACH will run out some bug if you change the data in array.But this time i change it to for() {} the problem is still here.

Someone knows this problem?

Upvotes: 0

Views: 373

Answers (1)

godel9
godel9

Reputation: 7390

You don't want to remove an element from a CCArray in the middle of iterating through it. Try:

for(int i = mSkills->count() - 1; i >= 0; i--) {
    Skill *skill = mSkills->objectAtIndex(i);
    ...
}

It's not the most efficient, but it also doesn't seem like you're going to be spending a lot of time in this function. Let me know if that helps.

Explanation

When you remove an element from a CCArray, the implementation moves all the later elements up one spot to fill the gap created by the missing element.

If you're iterating in a forward direction, you're moving elements that you haven't visited yet, and you end up skipping the element after the one being removed. Iterating backwards through the array solves this problem because you've already visited the elements being moved.

Upvotes: 2

Related Questions