Search code examples
androidlibgdxscene2d

Inconsistent (flickering) mouse coordinates in InputListener.touchDragged


I have an actor that I want to move with a touch drag.

class Tile extends Actor {
    Tile (char c) {
        addListener(new InputListener() {
            private float prevX, prevY;

            @Override
            public void touchDragged (InputEvent event, float x, float y, int pointer) {
                Gdx.app.log(TAG, "touchDrag: (" + x + "," + y);
                Tile cur = (Tile)event.getTarget();
                cur.setPosition(  //this call seems to cause the problem
                        cur.getX() + (x - prevX),
                        cur.getY() + (y - prevY) );
                prevX = x; prevY = y;
            }
        });
    }

    @Override
    public void draw(Batch batch, float alpha) {
        batch.draw(texture, getX(), getY());
    }

}

The tile kind of shudders while being dragged and moves about half the speed of the touch. This is confirmed by the logging line which outputs coordinates like the following:

I/Tile: touchDrag: (101.99991,421.99994)
I/Tile: touchDrag: (112.99985,429.99994)
I/Tile: touchDrag: (101.99991,426.99994)
I/Tile: touchDrag: (112.99985,433.99994)
I/Tile: touchDrag: (101.99991,429.99994)
I/Tile: touchDrag: (112.99985,436.99994)

If I remove the commented line (i.e. don't reset the actor's position), the dragging output looks much more reasonable:

I/Tile: touchDrag: (72.99997,78.99994)
I/Tile: touchDrag: (65.99997,70.99994)
I/Tile: touchDrag: (61.99997,64.99994)
I/Tile: touchDrag: (55.99997,58.99994)
I/Tile: touchDrag: (51.99997,52.99994)
I/Tile: touchDrag: (42.99997,45.99994)

Any ideas? Thanks for looking!


Solution

  • The coordinates in the InputListener methods are given in relation to the Actor's position, so they are not comparable to their previous values if you are moving the Actor at the same time.

    Instead, store the original position and move in relation to that. The math works out to accommodate your movements:

        addListener(new InputListener() {
            private float startX, startY;
    
            @Override
            public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
                startX = x;
                startY = y;
                return true;
            }
    
            @Override
            public void touchDragged (InputEvent event, float x, float y, int pointer) {
                Tile cur = (Tile)event.getTarget();
                cur.setPosition(
                        cur.getX() + (x - startX),
                        cur.getY() + (y - startY) );
            }
        });