Search code examples
javaandroidlibgdx

Java LibGDX Moving to Touch Position on Android


I'm using this code but somethings aren't perfect. It's working but not smooth. First it goes touchX and then goes touchY. But I want this at the same time. I tried different codes but didn't work. How can I fix it? What's the problem?

package com.anil.game1;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
public class Game1 extends ApplicationAdapter {
    private SpriteBatch batch;
    private OrthographicCamera camera;
    private Texture player1Texture;
    private Rectangle player1Rectangle;
    private Vector3 touchPos;
    @Override
    public void create () {
        batch = new SpriteBatch();
        camera = new OrthographicCamera(480, 800);
        player1Texture = new Texture("Player1.png");
        player1Rectangle = new Rectangle();
        player1Rectangle.set(240, 0, 64, 64);
        touchPos = new Vector3();
    }
    @Override
    public void render () {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        if (Gdx.input.isTouched()) {
            touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
            camera.unproject(touchPos);
            //player1Rectangle.setPosition(new Vector2(touchPos.x, touchPos.y));
        }
        if (touchPos.x > player1Rectangle.x)
            player1Rectangle.x += 5;
        else
            player1Rectangle.x -= 5;
        if (touchPos.y > player1Rectangle.y)
            player1Rectangle.y += 5;
        else
            player1Rectangle.y -= 5;
        batch.draw(player1Texture, player1Rectangle.x - 32, player1Rectangle.y - 32);
        batch.end();
    }
    @Override
    public void dispose () {
        batch.dispose();
        player1Texture.dispose();
    }
}

Solution

  • In this section:

        if (touchPos.x > player1Rectangle.x)
            player1Rectangle.x += 5;
        else
            player1Rectangle.x -= 5;
        if (touchPos.y > player1Rectangle.y)
            player1Rectangle.y += 5;
        else
            player1Rectangle.y -= 5;
    

    You are forcing the rectangle to always move in the X and Y directions by a set amount. It's never allowed to just sit still or slow down. Also, you probably don't want to be handling X and Y separately, because then its speed will be slower in the cardinal directions and faster in the diagonal directions, which would look weird. And finally, you need to work with speed and time to keep a stable movement speed.

    So first of all, define a speed for your object. Also, you're going to want a Vector2 handy for calculations.

    private static final float SPEED = 300f; //world units per second
    private final Vector2 tmp = new Vector2();
    

    Now after you have calculated touch position, you want to figure out what direction to move in, and how far to move along that direction. So right after your isTouched block:

    //how far the player can move this frame (distance = speed * time):
    float maxDistance = SPEED * Gdx.graphics.getDeltaTime();
    
    //a vector from the player to the touch point:
    tmp.set(touchPos.x, touchPos.y).sub(player1Rectangle.x, player1Rectangle.y); 
    
    if (tmp.len() <= maxDistance) {// close enough to just set the player at the target
        player1Rectangle.x = touchPos.x;
        player1Rectangle.y = touchPos.y;
    } else { // need to move along the vector toward the target
        tmp.nor().scl(maxDistance); //reduce vector length to the distance traveled this frame
        player1Rectangle.x += tmp.x; //move rectangle by the vector length
        player1Rectangle.y += tmp.y;
    }