在LibGDX的`scene2d` API中是否可以在多个阶段中拥有相同的Actor实例?

时间:2016-09-22 22:28:57

标签: libgdx scene2d

我正在使用令人惊叹的libGDX + scene2d API创建一个程序,我的结构如下:

  • 我有一个MyGame个实例,只有一个PolygonSpriteBatch个实例。
  • 有一个抽象的MyScreen课程,持有MyStage课程(见下文)
  • 然后有许多不同的屏幕类继承自MyScreen,并且可以随意实例化。

(在所有情况下,删除“My”会为您提供其扩展的相应库类的名称)

此模型工作正常,直到我遇到一些问题,无法使用Action系统在屏幕之间执行操作。我当时决定让一个OmnipresentActor属于MyGame是个好主意,就像名字所说的那样,它存在于每个场景中。所以我修改MyStage看起来或多或少是这样的:

public class MyStage extends Stage {
public MyStage(MyGame g) {
    super(new FitViewport(MyGame.WIDTH, MyGame.HEIGHT), g.batch);
    addActor(game.omnipresentInvisibleActor);
}

@Override
public void clear() {
    unfocusAll();
    getRoot().clearActions();
    getRoot().clearListeners();
    removeActorsButNotListenersNorActions();
}

public void removeActorsButNotListenersNorActions() {
    for (Actor a : getActors()) if (a.getClass()!= OmnipresentInvisibleActor.class) a.remove();
}

它经历了一个痛苦的调试阶段,直到我发现了以下内容:

public PresentationScreen(MyGame g) {
    // super() call and other irrelevant/already debugged code
    System.out.println("PRINT_BEFORE: "+ stage.getActors().toString()); // OmnipresentActor is there
    mainMenuScreen = new MainMenuScreen(game);
    System.out.println("PRINT_AFTER: "+ stage.getActors().toString()); // OmnipresentActor is not there anymore, but was added to the mainMenuScreen

"PRINT_BEFORE"语句显示stage拥有omnipresentActor。在"PRINT_AFTER"它不再存在,而mainMenuScreen确实持有它。所以我的问题,现在更精确:

scene2d会阻止这种情况发生,还是我在这里做错了什么?

非常感谢!干杯

1 个答案:

答案 0 :(得分:0)

演员只能是一个舞台的成员:感谢@ Tenfour04确认。经过一些研究后,解释非常清楚:

Stage.addActor()看起来像这样:

(这里是Stage.java的github代码)

/** Adds an actor to the root of the stage.
     * @see Group#addActor(Actor) */
    public void addActor (Actor actor) {
        root.addActor(actor);
}

而root只是在Stage构造函数中初始化为一个组:root = new Group();

Group.addActor()看起来像这样:

(这里是Group.java的github代码)

/** Adds an actor as a child of this group. The actor is first removed from its parent group, if any. */
public void addActor (Actor actor) {
    if (actor.parent != null) actor.parent.removeActor(actor, false);
    children.add(actor);
    actor.setParent(this);
    actor.setStage(getStage());
    childrenChanged();

}

因此,在树中,第一行是答案:在创建新阶段时,如果要添加的actor已经具有父级,则将从其当前父级中删除它。那么,我提出的问题有两种可能的解决方案:

解决方案1:覆盖addActor删除if语句或库的任何其他更改,我不确定它是否可行。我认为这可能是非常有问题的,例如它可能会阻止阶段正确处置

解决方案2:更改设计,这样您就不需要无所不在的演员,也不需要更改/重新实现库。目前这是我基于this所做的事情。回答,它不是很干净,但它到目前为止有效:

1)在MyScreen课程中添加了以下字段:

private boolean watchingTemp;
private Actor watchActorTemp;
private Action actionTemp;

2)然后添加了这个方法:

public void addActionOnStageAfterActorEndsHisActions(Actor actor, Action action) {
    watchActorTemp = actor;
    actionTemp = action;
    watchingTemp = true;
}

3)然后在render方法中,我添加了以下内容:

if (watchingTemp && !watchActorTemp.hasActions()) {
        watchingTemp = false;
        stage.addAction(actionTemp);
    }

4)最后,当希望在屏幕转换时执行操作(并最终处理第一个)时,您可以执行以下操作:在屏幕之间单击门时使用类似的东西

public void movePlayerTHENgotoNewScreen(float xPos, float yPos, whatever else...) {
    game.player.walkToAnyPoint(xPos, yPos);
    yourFavoriteScreen.addActionOnStageAfterActorEndsHisActions(game.player, gotoNewScreen(wathever else...));
}

希望它有所帮助!