1
\$\begingroup\$

I am very new to programming, and trying to get my player to walk to the mouse click position. I currently have this script, which "teleports" my character to the clicked position:

private void getInput() {
    xMove = 0;
    yMove = 0;

    float tempX = handler.getMouseManager().getMouseX();
    float tempY = handler.getMouseManager().getMouseY();
    float diffX = tempX - x;
    float diffY = tempY - y;

    if (handler.getMouseManager().leftPressed) {
        x = tempX;
        y = tempY;
    }
}

The first thing that came to my mind was to use the following script, for moving to a click which is to the right:

if (handler.getMouseManager().leftPressed) { 
    if(diffX>0) {
        for(float counter = 0; counter = diffX; counter++)
            xMove = speed;
    }
}

However, this doesn't work. How would I go about making my player walk to the mouse click position?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

So first thing to be aware of is that the movement is a small bit at a time per game loop. It happens over a number of frames. And so the code here should help once you are sure about the concept of a game loop.

I guess there are a few ways to achieve this. This method uses a direction to move. It may seem a bit over the top but once you have a direction you can multiply it easily in order to adjust speed for gameplay reasons. It can also help if you are not using fixed frame rates.

I've just hard codes target and source here, but target would be your click position and source would be your character position.

        double targetX = 100;
        double targetY = 100;

        double sourceX = 200;
        double sourceY = 10;


        // tweak this to alter movement speed
        double speed = 2.0;

        // create a vector from source to target
        double vx = targetX - sourceX;
        double vy = targetY - sourceY;

        // create a normalised direction (in the range 0-1)

        // .. we'll need the distance of the vector to figure out a normalised vector.
        double distance = Math.sqrt(vx * vx + vy * vy);

        // figure out the direction
        double dirX = vx / distance;
        double dirY = vy / distance;

        // dirX,DirY is now normalised vector to target from source.
        sourceX += (dirX * speed);
        sourceY += (dirY * speed);

`

\$\endgroup\$
0
\$\begingroup\$

First of all, the loop in the second code snippet you gave doesn't terminate. You don't have a condition for termination. I think you meant counter <= diffX. Secondly, when you assign something in a loop, it will just get overwritten each time - so instead of setting xMove to speed inside the loop, you could just do it without the loop entirely, so this is probably not what you want.

To get your player towards the mouse position you could create a loop and in each step, just walk a very short amount. Here's an example:

private void walkToPosition(float toX, float toY, int steps) {
    float diffX = toX - x;
    float diffY = toY - y;

    // The increments are our step sizes. In each step of the for-loop,
    // the player walks as much as incrementX, resp. incrementY indicates.
    float incrementX = diffX / steps;
    float incrementY = diffY / steps;

    for (int i = 0; i < steps; i++) {
        x += incrementX;
        y += incrementY;
        // if the drawing doesn't happen in parallel, we'll need to do it explicitly
        updatePlayerView();
        Thread.sleep(1);
    }
}

One disadvantage of this method is that you have to choose a really large step size, because otherwise the player moves really fast. Also, how fast the player moves depends on the speed of your PC because the for loop just executes as fast as possible. If you want to fix this, it gets a bit more complicated. Essentially, your goal is to make the player speed independent of how fast your code is running (so that the player moves with the same speed on every PC, and also so that the player doesn't slow down when your PC is running many programs at the same time).

To decouple player speed and PC computation speed, you'll have to measure how much time your computer takes to do each loop step. This is a bit more complicated, so if you want to learn how to do that, I suggest you try this tutorial: http://www.java-gaming.org/index.php?topic=24220.0

Hope this helps!

\$\endgroup\$
4
  • \$\begingroup\$ That code works in the exact same way that the above code. It will instantly move the character. \$\endgroup\$
    – Charanor
    Jul 31, 2017 at 11:09
  • \$\begingroup\$ Well, you have the for-loop to step through. The idea is that you can control the speed through the step size. You're right though, I should probably put a sleep() for clarity. \$\endgroup\$ Jul 31, 2017 at 14:09
  • \$\begingroup\$ Using sleep won't do anything either. It will still move the player instantly. This will just look like the game freezes, then the character is instantly moved. You have to use the game loop and update movement once per frame to achieve smooth movement. \$\endgroup\$
    – Charanor
    Jul 31, 2017 at 14:40
  • \$\begingroup\$ Yeah, I've already updated my answer with a updatePlayerView(). Usually with these beginner projects (at least in Java) the drawing is done asynchronously anyway, so the updatePlayerView is not necessary if I recall correctly. And you're completely right, a gameloop is the way to go. I just deemed it out of scope for a simple answer. The tutorial I linked uses a game loop and explains thoroughly why it is a sensible thing to use one, \$\endgroup\$ Jul 31, 2017 at 15:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .