我正在使用令人惊叹的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会阻止这种情况发生,还是我在这里做错了什么?
非常感谢!干杯
答案 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...));
}
希望它有所帮助!