Search code examples
javaandroidlibgdxgame-enginedrag

Avoid image to go outside screen (Android) (libGDX)


I would like to make a sprite not to be able to go outside the edges of the screen. I tried but I made it bounce off the edges.

my try

But I need to stop the movement towards the edge (s) that collide with the image. (without bounce)

For example: You drag diagonally towards bottom-right, sprite collides with right edge and still slides down till the corner.

Kind of like this:

how it should work

My code attempt (see first image for result):

public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
Sprite sprite;
float offsetX;
float offsetY;

@Override
public void create() {
    batch = new SpriteBatch();
    img = new Texture("badlogic.jpg");
    sprite = new Sprite(img);

}

@Override
public void render() {
    Gdx.gl.glClearColor(1, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    batch.begin();
    sprite.draw(batch);
    batch.end();

    /*
    Bouncing sprite off the edge.
     */

    if(sprite.getX() <= 0){
        sprite.setX(1);
    } else if( sprite.getX() + sprite.getWidth() >= Gdx.graphics.getWidth() ){
        sprite.setX(Gdx.graphics.getWidth() - sprite.getWidth() - 1);
    } else if(sprite.getY() <= 0){
        sprite.setY(1);
    } else if (sprite.getY() + sprite.getHeight() >= Gdx.graphics.getHeight()) {
        sprite.setY( Gdx.graphics.getHeight() - sprite.getHeight() - 1);
    }

    if (Gdx.input.justTouched()) {

            offsetX = Gdx.input.getX() - sprite.getX();
            offsetY = Gdx.graphics.getHeight() - Gdx.input.getY() - sprite.getY();

    }

    if (Gdx.input.isTouched()){

        sprite.setPosition(Gdx.input.getX() - offsetX, (Gdx.graphics.getHeight() - Gdx.input.getY()) - offsetY);

    }

}

}

Solution

  • The logic is that you are allowing the image to go beyond the boundaries you chose and rendering it then calculating the x position and getting it back inside.

    Obviously you need to calculate the boundaries and based on that, you decide what the new X and Y will be before rendering it.

    You can create a method called calculatePosition which takes the user's input (x,y) and then sets the sprite position.

    Editing your isTouched() to

    calculatePosition(Gdx.input.getX() - offsetX, (Gdx.graphics.getHeight() 0 Gdx.input.getY()) - offsetY);
    

    Then adding this to your code:

    private void calculatePosition(float x, float y) {
        float minX = 0;
        float maxX = Gdx.graphics.getWidth() - sprite.getWidth();
        float minY = 0;
        float maxY = Gdx.graphics.getHeight() - sprite.getHeight();
    
        float newX = Math.min(maxX, Math.max(x, minX));
        float newY = Math.min(maxY, Math.max(y, minY));
    
        sprite.setPosition(newX, newY);
    }