在 LibGDX 的 `scene2d` API 中是否可以在多个阶段拥有相同的 Actor 实例?
Is it possible in LibGDX's `scene2d` API to have the same Actor instance in multiple Stages?
我正在使用令人惊叹的 libGDX
+scene2d API 制作一个程序,我将其结构化如下:
- 我有一个
MyGame
个实例,持有一个 PolygonSpriteBatch
个实例。
- 有摘要
MyScreen
class,持有MyStage
class(见下文)
- 然后有很多不同的screen class继承自
MyScreen
,并随意实例化。
(在所有情况下,删除“My
”将为您提供它扩展的相应库 class 的名称)
这个模型运行良好,直到我在使用 Action
系统在屏幕之间执行操作时遇到一些问题。那时我决定拥有一个属于 MyGame
的 OmnipresentActor
是个好主意,顾名思义,它出现在每个场景中。所以我修改了 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 是否阻止了这种情况的发生,还是我做错了什么?
回答非常感谢!干杯
一个演员只能是一个舞台的成员:感谢@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:更改设计,这样您就不需要无所不在的演员,也不需要 changing/reimplementing 库。 目前这就是我所做的基于 的回答,它不是很干净,但目前可以使用:
1) 在MyScreen
class 中添加了以下字段:
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...));
}
希望对您有所帮助!
我正在使用令人惊叹的 libGDX
+scene2d API 制作一个程序,我将其结构化如下:
- 我有一个
MyGame
个实例,持有一个PolygonSpriteBatch
个实例。 - 有摘要
MyScreen
class,持有MyStage
class(见下文) - 然后有很多不同的screen class继承自
MyScreen
,并随意实例化。
(在所有情况下,删除“My
”将为您提供它扩展的相应库 class 的名称)
这个模型运行良好,直到我在使用 Action
系统在屏幕之间执行操作时遇到一些问题。那时我决定拥有一个属于 MyGame
的 OmnipresentActor
是个好主意,顾名思义,它出现在每个场景中。所以我修改了 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 是否阻止了这种情况的发生,还是我做错了什么?
回答非常感谢!干杯
一个演员只能是一个舞台的成员:感谢@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:更改设计,这样您就不需要无所不在的演员,也不需要 changing/reimplementing 库。 目前这就是我所做的基于
1) 在MyScreen
class 中添加了以下字段:
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...));
}
希望对您有所帮助!