kwantuM kwantuM - 2 months ago 37
Android Question

LibGDX touchDown touchUp on different Actors

In my LibGDX game, I have a raster of clickable Actors. I want the player to be able to swipe across them and get the Actor where the swipe stops.

I don't want a

GestureListener
, the only thing I need is a touchUp event on the touchDown generated on another Actor. For example: think about Androids login screen where you swipe a pattern to unlock, but I only need an event for the last dot/Actor.

I have tried using
touchDown
/
touchUp
, but the event always fires on the Actor where the
touchDown
occurred.

A fine solution would be to get events for every Actor hit by the swipe, and then get a global
touchUp
event. Is this possible in a relatively accessible way - eg. without writing a whole new InputListener?

Answer

In touchUp() of your listener, call hit on the parent WidgetGroup of all your clickable Actors to see which one the finger is over when it is released. Note that since you're adding the actors to the group, the group needs to be added to the stage instead of adding the widgets to the stage directly. And remember that an Actor's X and Y are relative to its parent.

final WidgetGroup parent = new WidgetGroup();

InputListener inputListener = new InputListener(){
    private final Vector2 tmp = new Vector2();

    public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
        return true;
    }

    public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
        event.getTargetActor().localToParentCoordinates(tmp.set(x, y));
        Actor releaseOverActor = parent.hit(tmp.x, tmp.y, true);
        if (releaseOverActor != null){
            //doSomethingTo(releaseOverActor);
        }
    }
}

for (Actor clickable : clickableActors){
    parent.add(clickable);
    clickable.addListener(inputListener);
}

The above is a little bit simplified. You might want to return true one touchDown only if pointer 0 is used, for example.