How to continue sequence / parallel actions from cachedActions Libgdx

笑着哭i 提交于 2019-12-11 06:28:57

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!