7
\$\begingroup\$

I feel like this is a simple problem, but I'm having issues finding the correct search terms.

I have a Screen that includes two Stages.

  1. The first, stage, contains a number of objects deriving from Actor and added via the standard stage.addActor(Actor). This is for the actual game objects.

  2. The second, hudStage, consists of a single Table actor. This table includes a button as well as two Labels. This is for the static user interface/HUD.

I'm handling touch events on my custom actors in the game stage like the following:

public class GameObject extends Actor {
    private final static String TAG = GameObject.class.getName();
    // ...

    public GameObject() {
        // ...

        addListener(new InputListener() {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                Gdx.app.log(TAG, "touchDown on GameObject actor: <" + x + "," + y + ">");
                return super.touchDown(event, x, y, pointer, button);
            }
        });
    }

This works perfectly and logs what I need. However, I would now like to update the HUD with information about the object the user touched.

My screen has defined the Label I want to update (added via hudStage), but I'm not sure how to go from an actor in stage to the screen, or to the hudStage label.

public class GameScreen implements Screen {
    Stage stage;
    Stage hudStage;
    // This is the label I want to update.
    Label infoLabel;
    // ...
}

I know I can call setText(String) on the label, but I'm not sure the best way to bubble the click up. Plenty of examples have simplified versions where objects are defined in the main class (in my case, GameScreen) and are able to refer to them that way, but I've already broken these apart.

I started to look at creating a custom event that my actor could trigger, and that the stage would handle, but documentation is sparse and I'm not sure this is required.

I've also thought about scrapping the idea of having a label in the hudStage and instead having my actor draw text where the HUD would have. However, from what I continue to see, I think Scene2D is the right direction to go for the UI.

Thanks!

EDIT: What I'm looking for:

  1. An actor in GameScreen.stage is target of a touchDown event.
  2. Logic in actor fires and updates object.
  3. touchDown event in actor finishes by updating infoLabel in GameScreen.hudStage or updates String value in GameScreen (if easier, I'll go this route).
\$\endgroup\$
  • \$\begingroup\$ Do the Stage's not have access to each other? And if they don't, why not? \$\endgroup\$ – StrongJoshua Apr 26 '15 at 19:42
  • \$\begingroup\$ Good question. I think the answer is no, at least unless you go through GameScreen. It looks like the only window I have open is this answer on SO about multiple stages. Note that my cameras are different, which made me think two sibling stages would be required. \$\endgroup\$ – James Skemp Apr 26 '15 at 20:22
  • \$\begingroup\$ But you're already using 2 stages (one for hud and one for the game), how is that any different from the answer you linked? \$\endgroup\$ – StrongJoshua Apr 26 '15 at 21:10
  • \$\begingroup\$ It's not different, it's actually why I went with two stages ... Sorry, that was an attempt to answer your question "[I]f they don't, why not?" / why I coded this as I did. I assumed that they would have access to each other if one was the child of another. \$\endgroup\$ – James Skemp Apr 26 '15 at 21:13
  • \$\begingroup\$ Ok, so what is the problem with your current implementation? What do you by you wanting the click event to bubble up? What is supposed to happen? \$\endgroup\$ – StrongJoshua Apr 26 '15 at 21:32
1
\$\begingroup\$

To make this work you need the two stages to communicate. There are two ways you could have the result you desire.

  1. Have each actor you create (that is touchable) contain a reference to the HUD stage. Then when the actor is touched, simply update the HUD by calling a method with the actor as a parameter (hudStage.update(thisActor)).
  2. Do not assign listeners to your actors. Instead assign a listener to your HUD stage (not the table within it) that listens for clicks on the entire screen. When a click is registered, call hit(x, y, true) and see which actor is hit. Call that actor's update method (or whatever it is you want to do when an actor is touched) and update the HUD's info with that actor.

I think these would be the easiest ways to accomplish what you want, but of course, you can make variations on these two ideas as you need.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.