# how to move a node or sprite without action?

how to move a node or sprite without action?
0.0 0

#1

Hi there,
I want to move the sprite on fixed path with many control points,
like
1079,383 —> 1072,383 —> 1065,384 —-> ……

I can use the action moveto or moveby to do this, but i want to
try this without action, by using setPosition/setRotation in
update schedule function, of cause the sprite has velocity and
angel feature.

Is there any sample for this ? Thanks a lot.

#2

If the sprite has velocity, what’s problem? Inherit CCSprite with some MegaCCSprite, declare: CCPoint pos, vel;
And in update cycle (schedule something):

float dt = CCDirector::getSharedDirector()->getDeltaTime();

vel.x = SPEED * dt;
vel.y
= SPEED * dt;

pos.x = vel.x;
pos.y
= vel.y;

SPEED is a constant, try to find it by hands.

#3

@Max Frai

``````vel.x += SPEED * dt;
vel.y += SPEED * dt;
``````

This is wrong. you have to calculate the speed component on y axis and speed component on x axis.

``````vel.x = SPEED * cos(angle) * dt;
vel.y = SPEED * sin(angle) * dt;
``````

#4

@Plato Manchi
Oh, yea, Monday’s morning

#5

Consider the case as shown in the image

“Starting Point” is the starting point and “Control Point” is next control point.
“angle” is the angle between x-axis and the line connecting start and control.
If sprite is at (x, y), in deltaTime sec the amount of distance traveled by sprite will be

``````float deltaDistanceTravelled = SPEED * dt;
``````

the angel can be obtained by the formula

``````//consider that start, control are starting point and control point
float angel = atan2f( (control.y - start.y), (control.x - start.x) );
``````

we have angle and deltaDistanceTravelled. so calculating deltaX and deltaY.

``````// cos( angel ) = adjacent side / hypotenuse;
// => adjacent side = hypotenuse * cos( angel )
float deltaX = deltaDistanceTravelled * cos( angel );
float deltaY = deltaDistanceTravelled * sin( angel );
``````

the new position will be

``````float newX = currentX + deltaX;
float newY = currentY + deltaY;
``````

Putting everything together into cocos2dx code using scheduler …
Control points can be saved using CCPointArray. (dont forget to retain, since you want the array to stay in memory.)

I did this in a basic helloworld project.

Inside init()

``````// creating and retaining a CCPointArray
this->mControlPoints = CCPointArray::create( 5 );
this->mControlPoints->retain();

// adding some control points to the array

// initializing the totalDistanceToBeCovered to the
// distance between sprite's current position and the 1st control point
if( this->mControlPoints->count() > 0 )
// calculating distanceSquare instead of distance,
// because calculating sqrt(float) is costly operation on CPU (compared to multiplying)
this->totalDistanceToBeCovered = distanceSquare(this->sprite->getPosition(), this->mControlPoints->getControlPointAtIndex(0));
else
this->totalDistanceToBeCovered = 0.0f;

// this used to keep track of how much distance traveled by the sprite.
this->distanceCovered = 0.0f;

// totalDistanceToBeCovered and distanceCovered has to be initialized before
// scheduling the moveSprite function
this->schedule( schedule_selector(HelloWorld::moveSprite) );
``````

and the moveSprite function is

``````void HelloWorld::moveSprite(float deltaTime){
HelloWorld* thisScene = (HelloWorld*)this;

// if there are no control points
// then unschedule the function.
if( thisScene->mControlPoints->count() == 0 ){
thisScene->unschedule( schedule_selector(HelloWorld::moveSprite) );
return;
}

float speed = 100.0f; // pixels per second

// getting the next control point to which
// sprite should move
CCPoint mNextDestination = thisScene->mControlPoints->getControlPointAtIndex( 0 );

// current sprite position
CCPoint mCurrentPosition = thisScene->sprite->getPosition();

// calculating how much distance the sprite should travel
// distance = velocity * time;
float deltaDistanceTravelled = speed * deltaTime;

// calculating the total distance covered by the sprite

if( (thisScene->distanceCovered * thisScene->distanceCovered) < thisScene->totalDistanceToBeCovered ){
// this means the sprite is still on its way towards the control point
// see the image attached for reference on calculating deltaX and deltaY

// calculating the angle btw next control point and the sprite
// tan( angle ) = ( y2 - y1 ) / ( x2 - x1 );
// angle = tanInverse( ( y2 - y1 ) / ( x2 - x1 ) );
float angle = atan2f( (mNextDestination.y - mCurrentPosition.y), (mNextDestination.x - mCurrentPosition.x) );

float deltaX = deltaDistanceTravelled * cos( angle );
float deltaY = deltaDistanceTravelled * sin( angle );

thisScene->sprite->setPosition( ccp(mCurrentPosition.x + deltaX, mCurrentPosition.y + deltaY) );
}
else{
// this means the sprite reached the control point
thisScene->sprite->setPosition( mNextDestination );

// removing the control point from the array of control points
thisScene->mControlPoints->removeControlPointAtIndex(0);

// since we just removed a point from array, making sure that array contains points
if( thisScene->mControlPoints->count() > 0 ){
// calculating the distance towards next control point
thisScene->totalDistanceToBeCovered = distanceSquare(mNextDestination, thisScene->mControlPoints->getControlPointAtIndex(0));
thisScene->distanceCovered = 0.0f;
}
}
}
``````

I’m sure there will be another more better and faster way to do this. (atan2f is costly operation on CPU)
Please let me know if there is any.

#6

Great answer. But anyway, I don’t see the reason to use trigonometry (including atan2f) if we can work with pure vector math which excludes this.

#7

Sorry, but i have more confidence on trigonometry than on vectors. So i couldn’t think of way to do it using vectors.
I very much appreciate it if you can show how it can be done