[solved] Simple walkTo(x, y) method for starter game.

Hey JGO, I’m trying to write a method that simulates the player walking to the clicked position on the screen. (Game tiles stationary atm)

What I have now produces a buggy system where the player is usually over the targetX by a few or under, this results in the player bouncing. (Happens for x and y -> bounces both ways)

Can anyone recommend a better way to do this than what I have below?


		// If a destination has been flagged.
		if (walkToX != -1 && walkToY != -1) {

			if (playerY <= walkToY) {
				playerY += 5;
			} else if (playerY >= walkToY) {
				playerY -= 5;
			}
			if (playerX <= walkToX) {
				playerX += 5;
			} else if (playerX >= walkToX) {
				playerX -= 5;
			}
		}

Thanks guys :slight_smile:

Could it be due to the fact you are stepping 5 units at a time?

I do believe that’s why, but incrementing by 1 results in a slow movement D:

I haven’t came up with a solution on how to do this >__<

EDIT: Stepping by 1 still produces the glitch.

Simple route:

Step by 1 at a time, but put the whole check & move bit in a 5x loop.

This ^

Also if you want things to move nicer and such, make sure you are using a unit system. As in don’t treat 1 pixel as 1 unit.

Another simple thing is separating speed, acceleration and velocity to get a cool little movement thing going on. Simple to implement, good for learning. Well imo. Don’t know how basic you want to keep it :D.

I believe I tried implementing it properly, and it’s still producing the bounce glitch D:


		// If a destination has been flagged.
		if (walkToX != -1 && walkToY != -1) {
			int xVelocity = 5;
			int yVelocity = 5;
			
			// Handle our y.
			for (int i = 0; i < yVelocity; i++) {
				if (playerY <= walkToY) {
					playerY += 1;
				} else if (playerY >= walkToY) {
					playerY -= 1;
				}
			}

			// Handle our x
			for (int i = 0; i < xVelocity; i++) {
				if (playerX <= walkToX) {
					playerX += 1;
				} else if (playerX >= walkToX) {
					playerX -= 1;
				}
			}
		}

I’m a newb, did I do this right?

If I was to make the player move 1 tile at a time (32pixels), how could I make it so the player doesn’t zip to the next tile, I’d like to make him transition.

Could someone post pseudo-code of how to do what I asked above? just a layout :slight_smile:

A cheap way would be to multiply the movement speed by delta time. So:

player.x += 1 * delta

Down the line people tend to frown upon this and say a fixed time step is better, which is true if you are leaning more towards velocity, speed, acceleration, dampening, friction and all that nice stuff.

Some vector stuff, should be right:


public class Player {

	public static final int MOVEMENT_SPEED = 10; // set to whatever

	private Point destination;

	public void moveTo(int x, int y) {
		destination = new Point(x, y);
	}

	public void update() {

		if(destination != null) {}
			Point current = getPosition();

			double dx = destination.x - current.x;
			double dy = destination.y - current.x;

			double dist = Math.sqrt(dx * dx + dy * dy);

			double dx2 = dx / dist * MOVEMENT_SPEED;
			double dy2 = dy / dist * MOVEMENT_SPEED;

			dx2 = Math.min(Math.abs(dx), Math.abs(dx2)) * Math.signum(dx2);
			dy2 = Math.min(Math.abs(dy), Math.abs(dy2)) * Math.signum(dy2);

			setPosition(current.x + dx2, current.y + dy2);

			if(dist < MOVEMENT_SPEED)
				destination = null;
		}
	}
}

Try something like this, It’ll stop you from going past your destination. But, Let you go as fast as possible.


// If a destination has been flagged.
      if (walkToX != -1 && walkToY != -1) {
         int xVelocity = 5;
         int yVelocity = 5;
         
         // Handle our y.
         for (int i = 0; i < yVelocity; i++) {
            if (playerY < walkToY && playerY + yVelocity <= walkToY) {
               playerY += yVelocity;
            } else if (playerY < walkToY) {
               playerY += 1;
            }
         }

         // Handle our x
         for (int i = 0; i < xVelocity; i++) {
            if (playerX < walkToX && playerX + xVelocity <= walkToX) {
               playerX += xVelocity;
            } else if (playerX < walkToX) {
               playerX += 1;
            } 
         }
      }

/Edit2: Fixed

Questions:
Is getPosition the players position?
Is setPosition setting the players position?

I tried implementing it in my game and the player just runs off screen and keeps going XD.
Never dealt with vector math so o: all help’s appreciated :slight_smile:
Would love to get this working for my game.

Update method:


	public static void update() {
		if (destination != null) {

			Point current = new Point(playerX, playerY);

			double dx = destination.x - current.x;
			double dy = destination.y - current.x;

			double dist = Math.sqrt(dx * dx + dy * dy);

			double dx2 = dx / dist * MOVEMENT_SPEED;
			double dy2 = dy / dist * MOVEMENT_SPEED;

			dx2 = Math.min(Math.abs(dx), Math.abs(dx2)) * Math.signum(dx2);
			dy2 = Math.min(Math.abs(dy), Math.abs(dy2)) * Math.signum(dy2);

			playerX = (int) (current.x + dx2);
			playerY = (int) (current.y + dy2);

			if (dist < MOVEMENT_SPEED) {
				destination = null;
			}
		}
	}

Mouse pressed method:


			public void mousePressed(MouseEvent arg0) {
				// TODO Auto-generated method stub
				super.mousePressed(arg0);
				if (arg0.getButton() == 3) {// right click
					Game.walkTo(mouseX, mouseY);
				} else if (arg0.getButton() == 1) {// left click

				}
			}

This seems to work, but it only lets me go right/down XD
I’ll see if I can get it working :c
Thanks ^____^

That’s probably due to the for loops, I don’t think they’re necessary in that code. But, Left them there for you to debug :wink:

Yes.

If it doesn’t work, well, your code is so stateful (not a put down, everyone starts like that) it’s nearly impossible for us, outside observers, to reason about your code without seeing all of it, and even then it’s a chore.
Overly-stateful code is also why you’re having these bugs. I can’t really give any tips that will be helpful to you except for keep practicing and try to think about problems in ways that don’t involve fields and if/else statements all over. Embrace the concept of the pure function whenever you can.

Twas exactly the error XD
Thanks alot, up is now working I think I can manage to get left working. Thanks :slight_smile:

EDIT: schweet :smiley:

Looks like you had a different plan in mind than me lol.

I tweaked your code like so:


// Handle our y
if (playerY < walkToY && playerY + yVelocity <= walkToY) {
	playerY += yVelocity;
} else if (playerY > walkToY && playerY - yVelocity >= walkToY) {
	playerY -= yVelocity;
}

// Handle our x
if (playerX < walkToX && playerX + xVelocity <= walkToX) {
	playerX += xVelocity;
} else if (playerX > walkToX && playerX - xVelocity >= walkToX) {
	playerX -= xVelocity;
}

looks like my else statement enabled the up/left where as yours disabled it XD idk
Got it solved though, thanks ^___^