Question

In fear of reinventing the wheel, I wonder:

What is the best approach to implement a smooth grid based game character movement on a top-down Tiled (2D) map with libGDX?

The character should keep moving smoothly between tiles as long as an arrow key is pressed (or a touch event occures on certain direction of the character) and should finish confined to a grid position on key / touch release. The movement should be independent from the frame rate.

I would be glad about some already implemented examples that can be studied and lead to a proper libGDX API usage.

Was it helpful?

Solution

Test if a specific button is pressed (or screen touched), if it is, set the correct target tile (the tile where the player will go) in a field and start moving there, this Movement will only end when the player is in the next tile. When that happens, check for input again to keep moving (i.e. repeat).

Lets suppose, your tile width/height is 1, and you want to move 1 tile per second. Your user pressed Right arrow key. Then you just set the targettile to the tile just right of the player.

if(targettile!=null){
    yourobject.position.x += 1*delta;
    if(yourobject.position.x>=targettile.position.x){
        yourobject.position.x = targettile.position.x;
        targettile = null;
    }
}

This code is simplified for right movement only, you need to make it for the other directions too.
Dont forget to poll the input again if the player is not moving.

Edit:

InputPolling for keys:

if (Gdx.input.isKeyPressed(Keys.DPAD_RIGHT)){

InputPolling for touchs (cam is your camera, and touchPoint is a Vector3 to store the unprojected touch coordinates, and moverightBounds a (libgdx) Rectangle):

if (Gdx.input.isTouched()){
    cam.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
    //check if the touch is on the moveright area, for example:
    if(moveRightBounds.contains(touchPoint.x, touchPoint.y)){
        // if its not moving already, set the right targettile here
    }
}

And noone already said it, you get the delta as a parameter in the render method, or you can get it anywhere else using:

Gdx.graphics.getDeltatime();

References:

OTHER TIPS

This is only for one dimension but I hope you get the idea, by checking the directional keys and adding/subtracting 1 and then casting it to an int (or flooring) will give you the next tile. If you release the key you still have an unreached target and the entity will keep moving until it reaches the target tile. I think it would look something like this:

void update()(
    // Getting the target tile
    if ( rightArrowPressed ) {
        targetX = (int)(currentX + 1); // Casting to an int to keep 
                                       // the target to next tile
    }else if ( leftArrowPressed ){
        targetX = (int)(currentX - 1);
    }

    // Updating the moving entity
    if ( currentX < targetX ){
        currentX += 0.1f;
    }else if ( currentX > targetX ){
        currentX -= 0.1f;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top