Re-using actions in LibGDX

 

A question came up in a comment in the Scene2D part of the LibGDX tutorial series about re-using actions.  You very much can re-use actions, so I decided to do it in post form here.  This entire post is mostly just one large code sample.  It’s just easier to do it here than in comments.  For a greater context of what this code is doing, see the earlier linked tutorial section.

 

Here is a sample showing action re-use.

package com.gamefromscratch;    import com.badlogic.gdx.ApplicationListener;  import com.badlogic.gdx.Gdx;  import com.badlogic.gdx.Input;  import com.badlogic.gdx.InputProcessor;  import com.badlogic.gdx.graphics.GL20;  import com.badlogic.gdx.graphics.Texture;  import com.badlogic.gdx.graphics.g2d.Batch;  import com.badlogic.gdx.scenes.scene2d.Actor;  import com.badlogic.gdx.scenes.scene2d.Stage;  import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction;      public class Scenetest implements ApplicationListener, InputProcessor {         public class MyActor extends Actor {        Texture texture = new Texture(Gdx.files.internal("badlogic.jpg"));          public MyActor(){           setBounds(getX(),getY(),texture.getWidth(),texture.getHeight());        }          @Override        public void draw(Batch batch, float alpha){           batch.draw(texture,this.getX(),getY());        }     }            private Stage stage;     private MyActor myActor;     MoveToAction moveToOrigin,moveToCenter;       @Override     public void create() {        stage = new Stage();        myActor = new MyActor();          myActor.setPosition(Gdx.graphics.getWidth()/2 - myActor.getWidth()/2,              Gdx.graphics.getHeight()/2 - myActor.getHeight()/2);                moveToOrigin = new MoveToAction();        moveToOrigin.setPosition(0f, 0f);        moveToOrigin.setDuration(2f);                  moveToCenter = new MoveToAction();        moveToCenter.setPosition(Gdx.graphics.getWidth()/2 - myActor.getWidth()/2,              Gdx.graphics.getHeight()/2 - myActor.getHeight()/2);        moveToCenter.setDuration(2f);          myActor.addAction(moveToOrigin);        stage.addActor(myActor);        Gdx.input.setInputProcessor(this);     }       @Override     public void dispose() {     }       @Override     public void render() {        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);        stage.act(Gdx.graphics.getDeltaTime());        stage.draw();     }       @Override     public void resize(int width, int height) {     }       @Override     public void pause() {     }       @Override     public void resume() {     }         @Override     public boolean keyDown(int keycode) {        if(keycode == Input.Keys.NUM_1)           if(myActor.getActions().contains(moveToOrigin,true)) {              // this is "A" currently running action, do nothing              // If you wanted you could restart the action which               // would cause the duration to start over, like so:              moveToOrigin.restart();              // This action will now have a 2 second tween between               // its current location and target           }           else {              moveToOrigin.reset();              myActor.addAction(moveToOrigin);           }        if(keycode == Input.Keys.NUM_2)           if(myActor.getActions().contains(moveToCenter,true)) {              // this is "A" currently running action so do nothing           }           else {              moveToCenter.reset();              myActor.addAction(moveToCenter);           }        return false;     }       @Override     public boolean keyUp(int keycode) {        return false;     }       @Override     public boolean keyTyped(char character) {        return false;     }       @Override     public boolean touchDown(int screenX, int screenY, int pointer, int button) {        return false;     }       @Override     public boolean touchUp(int screenX, int screenY, int pointer, int button) {        return false;     }       @Override     public boolean touchDragged(int screenX, int screenY, int pointer) {        return false;     }       @Override     public boolean mouseMoved(int screenX, int screenY) {        return false;     }       @Override     public boolean scrolled(int amount) {        return false;     }    }

When you run this code, the graphic will start at the center of the screen and move towards the origin, with a total duration of 2 seconds.  If you press the 2 key, it will start an action to move back to the center of the screen.  Pressing 1 will move back to the origin.  Pressing 1 while a moveToOrigin is active will cause that action to restart, basically resetting the total duration back to 2 seconds again, just from your current position.

 

The only things to really be aware of here are that an Actor getActions() will only return actions that are currently run.  When the action is finished, it is removed from the Actor.  The other thing of note is, although you can reuse an Action, you will have to reset() it before you can add it again, or it will already be over.  If it is currently run, calling restart() has the same effect as resetting.

Programming


Scroll to Top