如何从 cachedActions Libgdx 继续序列/并行操作
How to continue sequence / parallel actions from cachedActions Libgdx
我有一个扩展的 clicklistener class,它旨在缓存 actor 在 touchDown 期间的所有当前动作,并在触发 touchUp 时将其分配回来。但是,它不适用于序列或并行操作。
public class MyClickListener extends ClickListener {
public Actor actor;
private final Array<Action> cachedActions = new Array<Action>();
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
actor = event.getListenerActor();
actor.addAction(btnScaleBackActions());
for(Action action:cachedActions)
{
//action.reset(); // i wants the actor to continue at where it stop
action.setTarget(actor);
action.setActor(actor);
actor.addAction(action);
}
cachedActions.clear();
}
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if(pointer==0)
{
actor = event.getListenerActor();
actor.setScale(0.9f);
cachedActions.addAll(actor.getActions());
actor.clearActions();
return super.touchDown(event, x, y, pointer, button);
}
else
{
return false;
}
}
我的按钮测试:
// button touchUp continue its previous action at where it stop
btn1.addAction(Actions.scaleBy(1,1,3));
// button touchUp not continue it previous actions and complete stop
btn2.addAction(sequence(Actions.scaleBy(1,1,3)));
// button touchUp give nullException error
btn3.addAction(forever(Actions.scaleBy(1,1,3)));
//error :
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.badlogic.gdx.scenes.scene2d.actions.RepeatAction.delegate(RepeatAction.java:29)
at com.badlogic.gdx.scenes.scene2d.actions.DelegateAction.act(DelegateAction.java:43)
是否可以在 myClickListener class 停止的地方继续 sequence/parallel 操作?
来自池(如来自 Actions class)的动作的默认行为是当它们从 actor 中移除时重新启动它们自己。重用这些实例实际上并不安全,因为它们也已返回到池中,并且可能会意外地附加到其他参与者。
因此,在将它们从 actor 中移除之前,您需要将它们的池设置为 null。
private static void clearPools (Array<Action> actions){
for (Action action : actions){
action.setPool(null);
if (action instanceof ParallelAction) //SequenceActions are also ParallelActions
clearPools(((ParallelAction)action).getActions());
else if (action instanceof DelegateAction)
((DelegateAction)action).getAction().setPool(null);
}
}
//And right before actor.clearActions();
clearPools(actor.getActions());
然后,当您将它们添加回 actor 时,您需要将它们的池添加回来,以便它们可以返回到 Actions 池并在以后重用以避免 GC 流失。
private static void assignPools (Array<Action> actions){
for (Action action : actions){
action.setPool(Pools.get(action.getClass()));
if (action instanceof ParallelAction)
assignPools(((ParallelAction)action).getActions());
else if (action instanceof DelegateAction){
Action innerAction = ((DelegateAction)action).getAction();
innerAction.setPool(Pools.get(innerAction.getClass()));
}
}
}
//And call it on your actor right after adding the actions back:
assignPools(actor.getActions);
这是另一个想法。您可以将您的操作包装在一种新型的可暂停操作中,而不是处理删除和恢复操作以及随后处理池问题。
public class PausableAction extends DelegateAction {
public static PausableAction pausable(Action wrappedAction){
PausableAction action = Actions.action(PausableAction.class);
action.setAction(wrappedAction);
return action;
}
boolean paused = false;
public void pause (){
paused = true;
}
public void unpause (){
paused = false;
}
protected boolean delegate (float delta){
if (paused)
return false;
return action.act(delta);
}
public void restart () {
super.restart();
paused = false;
}
}
现在,在获取您的操作时,将它们包装在一个暂停符中,例如:
btn1.addAction(PausableAction.pausable(Actions.scaleBy(1,1,3)));
并且 pause/unpause 在需要时采取行动,例如:
//...
actor = event.getListenerActor();
actor.setScale(0.9f);
for (Action action : actor.getActions())
if (action instanceof PausableAction)
((PausableAction)action).pause();
return super.touchDown(event, x, y, pointer, button);
我有一个扩展的 clicklistener class,它旨在缓存 actor 在 touchDown 期间的所有当前动作,并在触发 touchUp 时将其分配回来。但是,它不适用于序列或并行操作。
public class MyClickListener extends ClickListener {
public Actor actor;
private final Array<Action> cachedActions = new Array<Action>();
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
actor = event.getListenerActor();
actor.addAction(btnScaleBackActions());
for(Action action:cachedActions)
{
//action.reset(); // i wants the actor to continue at where it stop
action.setTarget(actor);
action.setActor(actor);
actor.addAction(action);
}
cachedActions.clear();
}
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if(pointer==0)
{
actor = event.getListenerActor();
actor.setScale(0.9f);
cachedActions.addAll(actor.getActions());
actor.clearActions();
return super.touchDown(event, x, y, pointer, button);
}
else
{
return false;
}
}
我的按钮测试:
// button touchUp continue its previous action at where it stop
btn1.addAction(Actions.scaleBy(1,1,3));
// button touchUp not continue it previous actions and complete stop
btn2.addAction(sequence(Actions.scaleBy(1,1,3)));
// button touchUp give nullException error
btn3.addAction(forever(Actions.scaleBy(1,1,3)));
//error :
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.badlogic.gdx.scenes.scene2d.actions.RepeatAction.delegate(RepeatAction.java:29)
at com.badlogic.gdx.scenes.scene2d.actions.DelegateAction.act(DelegateAction.java:43)
是否可以在 myClickListener class 停止的地方继续 sequence/parallel 操作?
来自池(如来自 Actions class)的动作的默认行为是当它们从 actor 中移除时重新启动它们自己。重用这些实例实际上并不安全,因为它们也已返回到池中,并且可能会意外地附加到其他参与者。
因此,在将它们从 actor 中移除之前,您需要将它们的池设置为 null。
private static void clearPools (Array<Action> actions){
for (Action action : actions){
action.setPool(null);
if (action instanceof ParallelAction) //SequenceActions are also ParallelActions
clearPools(((ParallelAction)action).getActions());
else if (action instanceof DelegateAction)
((DelegateAction)action).getAction().setPool(null);
}
}
//And right before actor.clearActions();
clearPools(actor.getActions());
然后,当您将它们添加回 actor 时,您需要将它们的池添加回来,以便它们可以返回到 Actions 池并在以后重用以避免 GC 流失。
private static void assignPools (Array<Action> actions){
for (Action action : actions){
action.setPool(Pools.get(action.getClass()));
if (action instanceof ParallelAction)
assignPools(((ParallelAction)action).getActions());
else if (action instanceof DelegateAction){
Action innerAction = ((DelegateAction)action).getAction();
innerAction.setPool(Pools.get(innerAction.getClass()));
}
}
}
//And call it on your actor right after adding the actions back:
assignPools(actor.getActions);
这是另一个想法。您可以将您的操作包装在一种新型的可暂停操作中,而不是处理删除和恢复操作以及随后处理池问题。
public class PausableAction extends DelegateAction {
public static PausableAction pausable(Action wrappedAction){
PausableAction action = Actions.action(PausableAction.class);
action.setAction(wrappedAction);
return action;
}
boolean paused = false;
public void pause (){
paused = true;
}
public void unpause (){
paused = false;
}
protected boolean delegate (float delta){
if (paused)
return false;
return action.act(delta);
}
public void restart () {
super.restart();
paused = false;
}
}
现在,在获取您的操作时,将它们包装在一个暂停符中,例如:
btn1.addAction(PausableAction.pausable(Actions.scaleBy(1,1,3)));
并且 pause/unpause 在需要时采取行动,例如:
//...
actor = event.getListenerActor();
actor.setScale(0.9f);
for (Action action : actor.getActions())
if (action instanceof PausableAction)
((PausableAction)action).pause();
return super.touchDown(event, x, y, pointer, button);