# make a sprite travel distance between New and Old mouse_pos

This topic is 3664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Using Java, I have set up a mouseDown(x,y) function and a movePlayer(x,y) function. movePlayer() is called from mouseDown(). Move player has two function a) check to see if the (x,y) is in bounds b) if it is, have the player sprite gradually travel the difference bettwen (current_x, current_y) and (new_x, new_y). Let me show you the function I have set up for movement:
	//move, and keep within boundaries
public void movePlayer(int new_x, int new_y)
{
int current_x, current_y;
current_y = pa.y_pos;
current_x = pa.x_pos;

//if new position is in bounds
if ((new_x > pa_min_x) && (new_x < (pa_max_x - pa_width)) && (new_y > pa_min_y) && (new_y < (pa_max_y - pa_height)))
{
System.out.println("Moving to (" + new_x + "," + new_y + ")");

//loop through until the Player travels
//the difference between current pos. and new pos
while (new_x != current_x && new_y != current_y)
{
if (new_x < current_x)
{
pa.setVelocity(-(PLAYER_VELOCITY), 0);
}
else if (new_x > current_x)
{
pa.setVelocity(PLAYER_VELOCITY, 0);
}

if (new_y < current_y)
{
pa.setVelocity(0, -(PLAYER_VELOCITY));
}
else if (new_y > current_y)
{
pa.setVelocity(0, PLAYER_VELOCITY);
}
}
}
else
{
System.out.println("This move would cause player movement to be OOB.");
}
}

I have a few ideas for what could be wrong - including the poor setup of if/elseif statements, I'm sure there's a better way to calculate this. If I remove the loop, I can make the player move 1 unit at a time inthe correct direction.I have a feeling that my problem is that the while() statement is terminating as soon as the mouse is no longer down. I'm aiming to have have the player's sprite move independantly along a straight, open path from (a,b) to (c,d)

##### Share on other sites
Your approach is inherently flawed: you're reacting to an event with a single function call, while what you're trying to achieve is a continuous process. The player should move a little each frame, he shouldn't do all his movement in a single frame (which is more or less what you're doing now). Your while loop does not make this a continuous process. In fact, it looks like it'll stall the application, because it checks if the player has already arrived, but inside the loop, you're only changing the players velocity: he's not moving, so the while loop never terminates.

So, remove that while loop and move the player a little each frame, untill he has arrived.

##### Share on other sites
I'd say get the target position and make that a vector called intended position or whatever. Something like this(pseudocode)

if ( intended_pos.X > playerpos.X){player pos -= playerspeed}

do something like that(except prettier) for x and y and greater-than less-than.

##### Share on other sites
Okay. I have configured it in such a way that now the movePlayer() function simply alters the value of SpriteClass's next_x, next_y. Then the update() function (which is called directlyin the game loop) checks to see if there is a difference between current_ and next_ positions. If there is, I am implementing nested if statements, the same way as before - and this is causing the image to shake around the screen. Movement is VERY shaky. I need to be able to travel smoothly in a straight or diagonal line.

On top of the movement being shaky, even after Player reaches his new position, it shakes in place. This is not a clipper/buffer issue. I think there is a better way (more mathematical) to achieve this motion. Anyone?

Here is the code causing the problem.It's some kind of "order of operation" of the if statements. This code make more of a staircase-like movement pattern whereas I am looking for a smooth linear translation.

if (next_x != x_pos || next_y != y_pos)	{	if (next_x < x_pos)		{			setVelocity(-(PLAYER_VELOCITY), 0);		}		else if (next_x > x_pos)		{			setVelocity(PLAYER_VELOCITY, 0);		}		if (next_y < y_pos)		{			setVelocity(0, -(PLAYER_VELOCITY));		}		else if (next_y > y_pos)		{			setVelocity(0, PLAYER_VELOCITY);		}	}

##### Share on other sites
Quote:
 Original post by Drizzt DoUrdenOn top of the movement being shaky, even after Player reaches his new position, it shakes in place. This is not a clipper/buffer issue. I think there is a better way (more mathematical) to achieve this motion. Anyone?

There is. Read up on vector math.

Quote:
 Here is the code causing the problem.It's some kind of "order of operation" of the if statements. This code make more of a staircase-like movement pattern whereas I am looking for a smooth linear translation.

The real problem here has nothing to do with the order of your if statements. Look carefully: you're always setting the players velocity on one axis only. What you want to do instead is moving on both axis at the same time. That's where vector math comes in handy. :)

Also, you shouldn't check if your players position is exactly the same as it's destination, since it's easy to move just a little bit past the target. It then has to move back - but it likely moves back too far. That causes the shaking: the player never exactly hits the right spot, so it's never really arriving. By checking if the player is close enough to it's destination, and snapping it to that position, you can avoid this problem.

##### Share on other sites
I hear ya

I was thunkin something like this (psuedo-code)

setVelocity((absolute value of the remaining number of values between CURRENT_Y_POSand NEXT_Y_POS)/the number of remaining number of values between CURRENT_Y_POS and NEXT_Y_POS), (... CURRENT_X_POS...));

So let's say player position is (15, 10) and next position is(35,10):

setVelocity((|15|+|35|/15+35)),(|10|+|10|/10+(10));

setVelocity(45/45,20/20)

setVelocity(1,1);

so now this single formula produces the movement but this formula is flawed for negative direction. Try chaning the CURRENT_Y_POS to a negative.

What do ya think?

##### Share on other sites
You're getting closer. :)

Rather than taking the absolute difference, keep the sign: it tells you in which direction to move. Also, don't add these positions, substract them, since you want the difference between them. So:

setVelocity((current.x - next.x) / abs(current.x - next.x),            (current.y - next.y) / abs(current.y - next.y));->setVelocity((35 - 15) / abs(35 - 15),            (10 - 10) / abs(10 - 10));->setVelocity(20 / 20, 0 / 0);->setVelocity(1, ...)

However, there are some problems with the above code: it's vulnerable to divisions by zero, it only moves diagonally at 45 degrees and it moves at varying speeds (sometimes 1, sometimes 1.4, because if you move 1 on both the x and y axis, the resulting movement is more than 1 - triangle of Pythagoras).

Rather than dividing the horizontal difference by the horizontal distance and the vertical difference by the vertical distance, divide both differences by the real distance. In vector math, this is known as normalizing a vector. Now, the player will always move straight towards the target and always at the same speed. You can then multiply both results with your desired speed. You still need to prevent division by zero cases, so you'll need to check if the distance isn't 0 first.