Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Click through an Actor in libGDX

I have an overlay in my game that consists of an image of a screen, and a set of buttons that are "on" the screen.

Screenshot:

Screenshot showing UI components

My Screen has one Stage. The Stage has a set of Group objects, which I think of as layers. The first group has the backgrounds, the groups in the middle has the game elements, and the frontmost group has the screen overlay.

The overlay layer consists of one Image, the screen itself, and four TextButton (one in each corner).

This would work great, if it weren't for the fact that I can't click on anything in the game layer as long as the image in the overlay layer is in front of it. Even if the image is transparent, it still interecepts all touch events before they reach the game layer.

So my questions is: How can I make the image in the overlay layer ignore all touch events, so that the game layer will get them and one can actually play the game?

I tried one idea myself, but I'm not sure this is the right way to do it: I tried creating the image as a custom Actor that always had height/width set to 0, but still (by overloading the draw() method) drew the image on the entire screen. This works very well, except for the fact that the image for some reason gets drawn behind elements in lower layers.

Screenshot: https://dl.dropboxusercontent.com/u/1545094/Screen2.png

In this screenshot, I have opened a instruction messagebox, which adds itself to one of the game layers (group 6). Note that all the buttons in the overlay layer (which is group 7) is in front of the messagebox, but the screen frame (which is a custom Actor) somehow gets drawn behind the messagebox. Why is that? Note: If I take this exact same case, and change my custom actor into a regular Image, everything is drawn correctly, but then I can't click anything in the lower layers anymore, as described above.

This is my custom actor, if anybody can make any sense of it:

public class ClickThroughImage extends Actor {

    BaseDrawable d;

    public NonexistingImage(BaseDrawable d){
        this.d = d;
        setSize(0, 0);
    }

    @Override
    public void draw(SpriteBatch batch, float parentAlpha) {
        d.draw(batch, 0, 0, 1024, 768); //Yes, I tried swapping these two lines. 
        super.draw(batch, parentAlpha); //It had no effect.
    }
}
like image 874
Erlend D. Avatar asked Jul 05 '13 14:07

Erlend D.


Video Answer


2 Answers

In addition to the other methods note you can also call:

setTouchable(Touchable.disabled);

Which is documented as:

No touch input events will be received by the actor or any children.

Method is n the Actor class.

like image 152
Pool Avatar answered Oct 11 '22 06:10

Pool


Yes, Pool is right.

Just set touchable to disabled.

It is questionable, whether it is a "good" default of the engine to make all actors touchable in a stage, because in most of my games the majority of actors is _not_ touchable, and there are only few elements the user can/shall interact with. Therefore I always create a base class of "nonTouchableActor" where I derive all my Actors from that shall not react on clicks/taps and this base class sets touchable(disabled) in the constructor. That way you no longer have to think about it.

like image 42
Grisgram Avatar answered Oct 11 '22 06:10

Grisgram