Getting Stage coordinates of Actor in Table in libGDX

后端 未结 1 466
我寻月下人不归
我寻月下人不归 2021-01-04 08:20

I want to create a floating help bubble to introduce the basic functioning of my game. This bubble should float above the Actor I want it to explain, like shown in the pictu

相关标签:
1条回答
  • 2021-01-04 09:20

    I think I understand where you got confused. It is actually very simple to get the stage coordinates of an actor (assuming screen aligned, unrotated, unscaled actors).

    All you need to do is this:

    public static Vector2 getStageLocation(Actor actor) {
        return actor.localToStageCoordinates(new Vector2(0, 0));
    }
    

    What you are doing wrong is trying to get the location of the actor relative to the table (by using actor.getX() and actor.getY()), and then transform that location to the stage. That will end up giving you the location of table because it will be adding the location of the actor. What you really what is to know where point new Vector2(0, 0) inside your actor is. This tells you where the bottom left corner of the actor is. If you want top left you would use new Vector2(0, actor.getHeight()), and the other corners in a similar manner.

    Additionally, if you are working with events and want to know the stage location of an event you would simply do the following:

    @Override public void touchUp(final InputEvent event, final float x, final float y, final int pointer, final int button) {
        if (pointer == Buttons.LEFT) {
            Gdx.app.log("Event", "x: " + event.getStageX() + " y: " + event.getStageY());
        }
    }
    

    For a more complete example look at the following code:

    import com.badlogic.gdx.ApplicationListener;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.graphics.GL20;
    import com.badlogic.gdx.math.Vector2;
    import com.badlogic.gdx.scenes.scene2d.InputEvent;
    import com.badlogic.gdx.scenes.scene2d.Stage;
    import com.badlogic.gdx.scenes.scene2d.ui.*;
    import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
    
    public class ActorStage implements ApplicationListener {
        private Stage stage;
        private Skin skin;
    
        @Override public void create() {
            Gdx.app.log("CREATE", "App Opening");
    
            this.stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
            Gdx.input.setInputProcessor(this.stage);
    
            this.skin = new Skin(Gdx.files.internal("skin/uiskin.json"));
            this.skin.hashCode();
    
            final Table table = new Table();
            table.setFillParent(true);
    
            final Button btnLab = new TextButton("Lab", skin);
            final Button btnSea = new TextButton("Sea", skin);
    
    
            setupButton(table, btnLab);
            setupButton(table, btnSea);
    
            this.stage.addActor(table);
    
            Gdx.gl20.glClearColor(0f, 0f, 0f, 1);
            Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        }
    
        private void setupButton(Table table, final Button button) {
            table.add(button).expandX().center();
    
            button.addListener(new ClickListener() {
                @Override public void clicked(InputEvent event, float x, float y) {
                    Gdx.app.log("XY", "[" + x + ", " + y + "]");
                    Gdx.app.log("Event", "[" + event.getStageX() + ", " + event.getStageY() + "]");
                    Gdx.app.log("Actor", "[" + button.getX() + ", " + button.getY() + "]");
    
                    Vector2 loc = new Vector2(button.getX(), button.getY());
                    Vector2 stageLoc = button.localToStageCoordinates(loc);
                    Gdx.app.log("ActorStage", "[" + stageLoc.x + ", " + stageLoc.y + "]");
    
                    Vector2 zeroLoc = button.localToStageCoordinates(new Vector2());
                    Gdx.app.log("ZeroStage", "[" + zeroLoc.x + ", " + zeroLoc.y + "]");
                }
            });
        }
    
        @Override public void render() {
            this.stage.act();
    
            Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
            Gdx.gl20.glEnable(GL20.GL_BLEND);
    
            this.stage.draw();
        }
    
        @Override public void dispose() {
            Gdx.app.log("DISPOSE", "App Closing");
        }
    
        @Override public void resize(final int width, final int height) {
            Gdx.app.log("RESIZE", width + "x" + height);
            Gdx.gl20.glViewport(0, 0, width, height);
            this.stage.setViewport(width, height, false);
        }
    
        @Override public void pause() {}
    
        @Override public void resume() {}
    }
    

    When clicking btnLab once, clicking btnSea once and then closing the window, outputs:

    CREATE: App Opening
    RESIZE: 800x600
    XY: [18.0, 13.0]
    Event: [200.0, 296.0]
    Actor: [182.0, 283.0]
    ActorStage: [364.0, 566.0]
    ZeroStage: [182.0, 283.0]
    XY: [6.0, 23.0]
    Event: [588.0, 306.0]
    Actor: [582.0, 283.0]
    ActorStage: [1164.0, 566.0]
    ZeroStage: [582.0, 283.0]
    DISPOSE: App Closing
    

    As you can see you want the "ZeroStage" message because that gives you the location of the actor on the stage.

    0 讨论(0)
提交回复
热议问题