问题
I have a clicklistener extended class which aims to cached any current actions of the actor during touchDown, and assigns it back when touchUp is triggered. However, it does not works for sequence or parallel actions.
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;
}
}
My buttons testing:
// 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)
Is it possible to continue sequence/parallel actions at where it stop at myClickListener class?
回答1:
Here's an alternate idea. Rather than deal with removing and restoring actions, and subsequently dealing with the pools issue, you can wrap your actions in a new type of pausable action.
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;
}
}
Now when getting your actions, wrap them in a pausable, for example:
btn1.addAction(PausableAction.pausable(Actions.scaleBy(1,1,3)));
And pause/unpause actions when you need to, like:
//...
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);
回答2:
The default behavior of actions that came from a pool (like from the Actions class) is to restart themselves when they are removed from an actor. It's actually not safe for you to be reusing these instances because they have also been returned to the pool and might get attached to some other actor unexpectedly.
So before you remove them from your actor, you need to set their pools to 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());
Then, when you add them back to the actor, you'll want to add their pools back so they can go back to the Actions pools and be reused later to avoid GC churn.
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);
来源:https://stackoverflow.com/questions/56390264/how-to-continue-sequence-parallel-actions-from-cachedactions-libgdx