CCRepeat bug

Hi there

CCRepeat has bug with repeat count 99 or 9999

For example my action

CCRepeat(CCSequence::createWithTwoActions( move_30_x , move_-30_x),99)

And now it stops on first action from sequence.

Example with position of node

On start
position = 0

now we run action

position = 30 # repeat 1
position = 0 # repeat 1
position = 30 # repeat 2
position = 0 # repeat 2

position = 30 # repeat 99

:slight_smile:

Pull request https://github.com/cocos2d/cocos2d-x/pull/5519

OK simply don’t use CCRepeat for such things it gives bad results not only for 99. I leave it for some time and still i have such thing

position = 30 # repeat XYZ
position = 0 # repeat XYZ
position = 30 # repeat XYZ + 1
position = 60 # repeat XYZ + 2 <------------------
position = 30 # repeat XYZ + 2
position = 60 # repeat XYZ + 3
position = 30 # repeat XYZ + 3

position = 90 # repeat XY
position = 60 # repeat XY

and so on

@gelldur
Could you paste some demo codes?

Thanks.

	{
		CCSprite* pSprite = CCSprite::create(R::Sprite::GUI_ARROW);
		addChild(pSprite);
	
		pSprite->setPosition(ccp(100,100));
		pSprite->runAction(CCRepeat::create(CCSequence::createWithTwoActions( CCMoveBy::create(0.05F,ccp(130,0)) ,CCMoveBy::create(0.05F,ccp(-130,0))),99));
	}

For example we start in point (0,0) and it stops in (130,0) it should stop in (0,0) but if you change times if CCMoveBy and distance you will see something odd that sprite starts walking to right edge of screen :slight_smile: but it depends on time of CCMoveBy i think and repeat count

in this example arrow start walking to right :slight_smile:

	{
		CCSprite* pSprite = CCSprite::create(R::Sprite::GUI_ARROW);
		addChild(pSprite);

		pSprite->setPosition(ccp(100,100));
		pSprite->runAction(CCRepeat::create(CCSequence::createWithTwoActions( CCMoveBy::create(0.02F,ccp(130,0)) ,CCMoveBy::create(0.02F,ccp(-130,0))),11099));
	}

My implementation of CCRepeat it works correctly :slight_smile: but you can’t do such stuff like you can do with oryginal CCRepeat like Easing. The reason of this is in update method. But for what i use it i don’t need it :slight_smile:

Repeat.h

/** @brief Repeats an action a number of times.
 * To repeat an action forever use the RepeatForever action.
 */
class Repeat : public CCActionInterval
{
	typedef CCActionInterval inherited;
public:
	/** creates a Repeat action. Times is an unsigned integer between 1 and pow(2,30) */
	static Repeat* create( CCFiniteTimeAction* pAction, unsigned int times )
	{
		Repeat* pRet = new Repeat();

		if( pRet && pRet->initWithAction( pAction, times ) )
		{
			pRet->autorelease();
			return pRet;
		}

		CC_SAFE_DELETE( pRet );
		return pRet = nullptr;
	}

	/** initializes a Repeat action. Times is an unsigned integer between 1 and pow(2,30) */
	bool initWithAction( CCFiniteTimeAction* pAction, unsigned int times );

	virtual ~Repeat();

	virtual CCObject* copyWithZone( CCZone* pZone );
	virtual void startWithTarget( CCNode* pTarget );
	virtual void stop();
	virtual void step( float dt );
	virtual void update( float dt );
	virtual bool isDone();
	virtual CCActionInterval* reverse();

	inline void setInnerAction( CCFiniteTimeAction* pAction )
	{
		if( m_pInnerAction != pAction )
		{
			CC_SAFE_RETAIN( pAction );
			CC_SAFE_RELEASE( m_pInnerAction );
			m_pInnerAction = pAction;
		}
	}

	CCFiniteTimeAction* getInnerAction()
	{
		return m_pInnerAction;
	}

private:
	unsigned int m_times;
	unsigned int m_total;
	CCFiniteTimeAction* m_pInnerAction;
	bool m_isActionInstant;

	Repeat();
};

Repeat.cpp


Repeat::Repeat() :
	m_times( 0 )
	, m_total( 0 )
	, m_pInnerAction( nullptr )
	, m_isActionInstant( false )
{
}

Repeat::~Repeat()
{
	CC_SAFE_RELEASE( m_pInnerAction );
}

bool Repeat::initWithAction( CCFiniteTimeAction* pAction, unsigned int times )
{
	float d = pAction->getDuration() * times;

	if( inherited::initWithDuration( d ) == false )
	{
		return false;
	}

	m_times = times;
	m_pInnerAction = pAction;
	pAction->retain();

	m_isActionInstant = dynamic_cast<CCActionInstant*>( pAction ) ? true : false;

	//an instant action needs to be executed one time less in the update method since it uses startWithTarget to execute the action
	if( m_isActionInstant )
	{
		m_times -= 1;
	}

	return true;
}

CCObject* Repeat::copyWithZone( CCZone* pZone )
{
	//Do not use
	assert( false );
	return nullptr;
}

void Repeat::startWithTarget( CCNode* pTarget )
{
	inherited::startWithTarget( pTarget );
	m_total = 0;
	m_pInnerAction->startWithTarget( pTarget );
}

void Repeat::stop( void )
{
	inherited::stop();
	m_pInnerAction->stop();
}

void Repeat::update( float dt )
{
	if( dt == 1 )
	{
		m_pInnerAction->update( 1 );
		m_pInnerAction->stop();
		++m_total;
		return;
	}

	step( CCDirector::sharedDirector()->getDeltaTime() );
}


void Repeat::step( float dt )
{
	m_pInnerAction->step( dt );

	if( m_pInnerAction->isDone() )
	{
		m_pInnerAction->stop();
		m_pInnerAction->startWithTarget( m_pTarget );
		++m_total;
	}
}


bool Repeat::isDone( void )
{
	return m_total >= m_times;
}

CCActionInterval* Repeat::reverse( void )
{
	return Repeat::create( m_pInnerAction->reverse(), m_times );
}