6
\$\begingroup\$

I used to extend my Player/Entity class with Sprite, that way I could create a walking animation using SetRegion and super(stilldown.getKeyFrame(0));

I've recently started porting everything over to Scene2D and I use Actors now. I do not know how to use this way of animation anymore, does anybody have a guess how I could do this?

        animationtime += delta;
    if(dir == Direction.DOWN){
        setRegion(velocity.y == 0 ? stilldown.getKeyFrame(animationtime) : walking.getKeyFrame(animationtime));
    }else if (dir == Direction.UP){
        setRegion(velocity.y == 0 ? stillup.getKeyFrame(animationtime) : walkingup.getKeyFrame(animationtime));
    }else if (dir == Direction.RIGHT){
        setRegion(velocity.x == 0 ? stillright.getKeyFrame(animationtime) : walkingright.getKeyFrame(animationtime));
    }else if (dir == Direction.LEFT){
        setRegion(velocity.x == 0 ? stillleft.getKeyFrame(animationtime) : walkingleft.getKeyFrame(animationtime));
    }   

This is how I'd initialise the animation

    playeratlas = new TextureAtlas("overworld/player/playersheet.pack");

    Animation walking;
    Animation walkingup;
    Animation walkingright;
    Animation walkingleft;

    Animation stilldown;
    Animation stillup;
    Animation stillright;
    Animation stillleft;

    walking = new Animation(1 / 4f, playeratlas.findRegions("walkingdown"));
    walkingup = new Animation(1 / 4f, playeratlas.findRegions("walkingup"));
    walkingright = new Animation(1 / 4f, playeratlas.findRegions("walkingright"));
    walkingleft = new Animation(1 / 4f, playeratlas.findRegions("walkingleft"));

    stilldown = new Animation(1 / 4f, playeratlas.findRegions("stilldown"));
    stillup = new Animation(1 / 4f, playeratlas.findRegions("stillup"));
    stillright = new Animation(1 / 4f, playeratlas.findRegions("stillright"));
    stillleft = new Animation(1 / 4f, playeratlas.findRegions("stillleft"));


    walking.setPlayMode(Animation.PlayMode.LOOP);
    walkingup.setPlayMode(Animation.PlayMode.LOOP);
    walkingright.setPlayMode(Animation.PlayMode.LOOP);
    walkingleft.setPlayMode(Animation.PlayMode.LOOP);

    stilldown.setPlayMode(Animation.PlayMode.LOOP);
    stillup.setPlayMode(Animation.PlayMode.LOOP);
    stillright.setPlayMode(Animation.PlayMode.LOOP);
    stillleft.setPlayMode(Animation.PlayMode.LOOP);

For now I only use a static image for my Actor

Sprite text = new Sprite(new Texture(Gdx.files.internal("overworld/player/placeholder.png")));

Now I draw it like this

public void draw(Batch batch, float ParentAlpha){
    text.draw(batch);
}

I would greatly appreciate help, I'm new to Scene2D and I can't find much on it.

\$\endgroup\$
  • \$\begingroup\$ Don't use Scene2d for your game objects. Scene2d is a UI package and is not supposed to be used for anything else. What made you change to Actors? \$\endgroup\$ – Charanor Aug 5 '16 at 18:10
1
\$\begingroup\$

If I understand correctly, your are wondering how to draw from the animation when using an Actor. It is very similar to how you were doing it before.

The getKeyFrame() method in the Animation class returns a TextureRegion so, rather than passing this to setRegion(), you have to draw it yourself. Don't worry, its pretty simple:

public void draw(Batch batch, float ParentAlpha){
    TextureRegion currentFrame = currentAnimation.getKeyFrame(animationtime);
    batch.draw(currentFrame, x, y, width, height);
}

It is probably worth looking into the Batch class to see all of the overloads of draw(), you can add other parameters such as rotation and scaling.

The best place to update your animation time variable is by overriding the Actor's act() method

@Override 
public void act(float deltaTime)
{
    super.act(deltaTime);
    animationTime += deltaTime;
}

make sure that you are calling act on your stage in the render loop, otherwise, the Actor's act wont be called.

\$\endgroup\$
  • \$\begingroup\$ I have an undefined amount of actors in my map, is there a way I can call act outside of the render loop, like only when an actor is walking? \$\endgroup\$ – GigaNova Dec 1 '15 at 19:27
  • \$\begingroup\$ With Scene2d, any time you call stage.act(float deltaTime) it will forward this call to all actors it contains. I guess that instead of calling stage.act() you could keep a list of actors that you want to act and manually go through them and call act on them, but I would still do this in the render loop. Since all act does is update the animationTime value it really isn't going to cost you much in terms of performance. Remember though, having sprites animate even when they are just standing there can add life to the sprite (you can make them look like they are breathing, etc..). \$\endgroup\$ – spectacularbob Dec 1 '15 at 19:50
0
\$\begingroup\$
// Take your **animation** created for your sprite batch and call this:
public class AnimatedActor extends Image
{    
  private float stateTime = 0;
  Animation animation;
  public AnimatedActor(Animation animation) {
    super(animation.getKeyFrame(0));
    this.animation = animation;
  }
  @Override
  public void act(float delta)
  {
 ((TextureRegionDrawable)getDrawable()).setRegion(animation.getKeyFrame(stateTime+=delta, true));
    super.act(delta);
  }
}
/* Render with:
    // if you change direction you will need logic for myAnimatedActor.remove and stage.addActor(myAnimatedActor);
    animationFrames = walkSheetArray[moveDirection];
    animation = new Animation(1f / 5f, animationFrames);
    myAnimatedActor = new AnimatedActor(animation);
    // stage.addActor(myAnimatedActor);
    myAnimatedActor.setPosition(posX, posY);
    stage.act(Gdx.graphics.getDeltaTime());
    stage.draw();
*/
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.