0
\$\begingroup\$

I would like to implement tile-based grid movement and I've heard that linear interpolation comes handy in the implementation process. I've tried to use it but I'm not sure how to make it stop once the target position is reached. I can't find a way to check that on the interpolation. Here's the code I'm using:

function movePlayer(deltaTime) {
    if buttonUp then
       velocity.add(0, speed);
    if buttonRight then
       velocity.add(speed, 0);
    if buttonSouth then
       velocity.sub(0, speed);
    if buttonLeft then
       velocity.sub(speed, 0);

    velocity.scl(deltaTime);

    if (targetPosition.isZero()) {
        targetPosition.add(getNextPosition());
    }

    position.lerp(targetPosition, speed * deltaTime);

    float distance = position.dst(targetPosition);
    if (allowMovement && distance < 0.1f) {
        position = targetPosition;
        allowMovement = false;
        targetPosition.set(0, 0);
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Your code seems a bit weird. What is the velocity variable being used for? Normally you would lerp between two points, the current position, and the target position, based on a percentage value between 0% and 100% - 0 meaning you are still on the current position, and 100 meaning you are on the target position. \$\endgroup\$
    – Saliken
    Jul 6, 2016 at 21:36
  • \$\begingroup\$ How i'm able to calculate the precentage between the two position. To be able to stop movement after reaching the destination. \$\endgroup\$
    – Printer
    Jul 6, 2016 at 21:41

2 Answers 2

1
\$\begingroup\$

The solution can be achieved in multiple ways, but checking the remaining distance between the current and the target position is a good way to go about this.

distance = targetPosition.sub(position).getLength();
if (distance < some_small_constant)
{
    position = targetPosition;
}

The code first creates a vector from the current position to the target position, and calculates its length. The length is then compared to a small constant (you should try out different values to see which feels good enough). If the length requirement is met, the position is snapped to the target position and then you're good to go!

\$\endgroup\$
3
  • \$\begingroup\$ I've actually tried similar method by using distance. But sometimes, it does not get it right and so the player walk infinitely or just a very small step. \$\endgroup\$
    – Printer
    Jul 6, 2016 at 16:03
  • \$\begingroup\$ The problem in that case is that the player exits the range without ever entering it. TBH your code looks a little weird to me. What is speed? Does the player currently move steadily towards the target or does the visible movement speed slow down as the player approaches the target? \$\endgroup\$
    – user35344
    Jul 6, 2016 at 16:06
  • \$\begingroup\$ The speed is max velocity, i was able to fix the infinitely walking. But problem is when i reset the targetPosition the player gets teleported to 0, 0. I've updated main post with the changes. \$\endgroup\$
    – Printer
    Jul 6, 2016 at 16:11
0
\$\begingroup\$

It seems like you are going about this the wrong way.

Linear interpolation is the process of transitioning from one value to a second value, which is exactly what you are looking for with your movement.

I'm unaware of java and libgdx syntax, but here's some example code so you get the idea.

Here's what you need:

Vector2 CurrentPosition : Your characters current position.

Vector2 StartingPosition : Your characters original position.

Vector2 EndPosition : Your characters desired position.

float timeSinceStart : The amount of time that has passed since beginning the transition.

int time : How long you want the transition to take in milliseconds.

To lerp, just do this every frame:

timeSinceStart += deltaTime; //Elapsed time since last frame
var delta = Clamp(time / timeSinceStart, 0, 1);
CurrentPosition = Lerp(StartingPosition, EndPosition, delta);
//Or possibly CurrentPosition = StartingPosition.lerp(EndPosition, delta) if that's the syntax.

First it adds the elapsed game time (delta time) to timeSinceStart to keep track of how much time has passed.

Then it creates the delta variable which is used to lerp between the start and end positions. The Clamp method is used to keep the value within 0 and 1. If delta is at 0 it means that no time has passed and the characters position should be at the starting position. If delta is at 1 it means that the amount of time that has passed is equal to how long we wanted it to take our character to move, and so our character will be at the end position.

Then it lerps between the start and end positions using the delta.

To check if your player has reached his target position, you simply check if delta == 1

\$\endgroup\$
3
  • \$\begingroup\$ Looks exaclty what i'm looking for. I will try it tomorrow \$\endgroup\$
    – Printer
    Jul 6, 2016 at 22:54
  • \$\begingroup\$ Great, comment again if you run into problems \$\endgroup\$
    – Saliken
    Jul 7, 2016 at 16:26
  • \$\begingroup\$ Well it kind of worked. But when it going to reach end pos. It interpolate very slow \$\endgroup\$
    – Printer
    Jul 7, 2016 at 18:30

You must log in to answer this question.

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