turn-based animation

Hi,
I am working on small turn-based game and now thinking about some easy way to animate objects. What I want to achive is to let for example player character to animate from one tile to other (so if I press RIGHT key, it will not only jump eg. 32 pixels to the right but slowly slide there with animation). Something like in dungeons of dremor but not so fancy of course:

I know how to run animation but don’t know how to fit it in the turn-based model. I do something like this in my hero class:


public void act() {
	if (control.action == Actions.RIGHT) {
		hero1.setCurrentFrame(frame);  //hero1 is instance of Animation
 		x=x+32;
		frame ^= 1;   // switch between two frames

Then render() and update() methods do just following:


public void render(GameContainer container, StateBasedGame game, Graphics g)
		throws SlickException {
     hero.hero1.draw(hero.x, hero.y);
		
			}

@Override
public void update(GameContainer container, StateBasedGame game, int delta)
		throws SlickException {
	hero.act();

I would normaly put this slide/animation code to update/render methods but it does not seem to be a good idea with my turn-based design (need to keep track if player’s instance already played and/or can play again, etc.).
Is there some way to render animation outside the GameState’s render() method? I tried to call hero1.draw(x,y) method in a loop in my hero’s class but it did not draw anything at all.
Thank you…hope my question is clear.

Okay, it’s pretty simple what you do.

Since your animation is going to happen only once your action has been determined, correct? Make it so that when you’re shifting between units/characters/monsters what-ever, there is a timer that is set up between when an action is made and the next action is decided on. This can be as simple as setting an int to a value > 0, then decreasing that value on every frame until it equals 0 before another action can be taken.

Really, if you can’t figure out a place to put your animation in your turn management system, then you probably need to rewrite it.

Sorry, can you elaborate it a little bit (maybe with small code sample) as I do not get it. Maybe I am mising the basic point of update()/render()/draw() methods. I tried to add something like this to slicks update() method just for testing if the image will be at least somehow moved slowly but it did not work:


for (int i=10000; i>=0; i--) {
	hero.x += i*0.000001f;
	hero.hero1.draw(hero.x, hero.y); //does not draw anything actually
}

Loop updates hero.x slowly but does not draw anything during any of these 10000 steps. Image is just drawn in the render method after the whole loop finishes (so it is “jumping” and not “sliding to the next position”).
Thanks

Well, off the top of my head:
Make a Move-class, which can contain an animation, a start and end point (or a length to travel and a direction, depending on how you’ve built your engine) and perhaps even a timeToSpendMoving.

When you select a move, you fetch the appropriate animation, the current position and the desired position, and use them to create an instance of the Move-class. Hero can have a “Move currentMove” variable.

Then in your hero.update(deltaTime) method, if his currentMove != null, do the part of the movement for the deltaTime, update the animation, and when you call hero.draw(g), if he has a currentMove, you draw the current image in the animation, and if he doesn’t have a currentMove, you draw the player image at his position.

If you’re not married to slick2d, you could use the scene2d stuff in libgdx, where the API would look something like

hero.addAction(moveBy(dx,dy,ms));

And everything is taken care of for you, you just call stage.act(delta) on every render() call. It even has several different easing effects for tweening, but I can’t recall the API offhand, other than that it’s dead simple. Decent (and recent) documentation for scene2d is hard to come by, but the source is very easy to understand.

Assuming you’re using a pixel-perfect projection, that whole loop will move the hero right by about 1/10 of a pixel. Try a bigger multiplier. Even then, you’ve got the draw in totally the wrong place, since that will draw 10000 copies of the hero overlaid on each other. Do one movement per frame, that’s it. If calculating all this stuff is too much of a hassle, I really have to recommend again using scene2d from libgdx.

I am actually working on a turn-based game like that and had similar problems at first.

The input is only setting up the target destination and gets “blocked” until the movement is complete and it’s player’s turn again.


if (playersTurn && !moving) {
  if (control.action == Actions.RIGHT) {
       targetX = x + TILESIZE; // set the destination
       currentAnimation = animationRight; // set the animation to the animation for moving to the right
       moving = true; // tell update it should be moving the character
  //some more input
  }
}

Now the update() moves x towards the targetX until the destination is reached. I use something like:


public void update(GameContainer container, StateBasedGame game, int delta)
      throws SlickException {
  if (moving && x + delta * .1f < targetX) {
    x += delta * .1f;
    currentAnimation.update(delta);
  } else if (x + delta * .1f >= targetX) {
    x = targetX;
    currentAnimation = idleAnimation;
    moving = false;
  }
}

And the renderer draws as usual. Everything should’ve been set up in the update() and where ever you accept your input:


public void render(GameContainer container, StateBasedGame game, Graphics g)
      throws SlickException {
     currentAnimation.draw(x,y); // don't know the exact syntax, haven't used slick in a while
}

Now you have prevented the player from flying through the tiles and clipping the animations because he has to wait for each animation to finish and until it is his turn. The factor for delta should of course be adjusted to fit the length of your animation. What kind of flags you set up for blocking the input is up to you. The code as is will probably not work since I just wrote it and don’t know the actual syntax of slick by heart but you should get the picture. I hope it is somewhat understandable and I could help. Good luck!

Yes, this is actually the same principle I came to after few days of trying different approaches and hitting various dead ends :slight_smile: Hope it will be solid as more and more features will be added in…
Thanks