Frame Animation manager – 2D

This week at university we have covered 2D frame animation – simple idea every frame is separate image.

what we need are two classes:

  • Animation
  • AnimationManager
// Animation.h
#pragma once
#ifndef ANIMATION_H
#define ANIMATION_H

#include 

class Animation
{
private: 
  IDirect3DTexture9* texture;
  int frameWidth;
  int frameHeight;
  int startFrame;
  int endFrame;
  int frameCount;
  float frameTime;
  bool isLooping;
public:
  Animation(IDirect3DTexture9* texture);
  Animation(IDirect3DTexture9* texture, float frameTime, bool isLooping);
  Animation(IDirect3DTexture9* texture, float frameTime, bool isLooping, int startFrame, int endFrame,int frameWidth, int frameHeight);
  ~Animation();

  void setTexture(IDirect3DTexture9* newTexture){ texture = newTexture; }
  IDirect3DTexture9* getTexture(){ return texture;}

  void setFrameTime(float newFrameTime){ frameTime = newFrameTime;};
  float getFrameTime(){return frameTime;}

  void setIsLooping(bool newIsLooping){ isLooping = newIsLooping; }
  bool getIsLooping() { return isLooping; }

  void setStartFrame(int newStartFrame) { startFrame = newStartFrame;}
  int getStartFrame() { return startFrame;}

  void setEndFrame(int newEndFrame) { endFrame = newEndFrame; }
  int getEndFrame() { return endFrame; }

  void setFrameCount(int newFrameCount) { frameCount = newFrameCount; }
  int getFrameCount() { return frameCount;}

  void setFrameWidth(int newFrameWidht) { frameWidth = newFrameWidht; }
  int getFrameWidth() { return frameWidth; }

  void setFrameHeight(int newFrameHeight) { frameHeight = newFrameHeight; } 
  int getFrameHeight() { return frameHeight; }
};
#endif

as we can see just bunch of attributes and geters/seters

// Animation.cpp
#include "Animation.h"

Animation::Animation(IDirect3DTexture9* texture): texture(texture){
  frameTime = 1.0f/ 30.0f;
  isLooping = true;
  D3DSURFACE_DESC desc;
  texture->GetLevelDesc(0, &desc);
  startFrame = 0;
  endFrame = desc.Width / desc.Height;
  frameCount = endFrame - startFrame;
  frameWidth = desc.Height; 
  frameHeight = desc.Height;
}

Animation::Animation(IDirect3DTexture9* texture, float frameTime, bool isLooping)
: texture(texture), frameTime(frameTime),isLooping(isLooping){
  D3DSURFACE_DESC desc;
  texture->GetLevelDesc(0, &desc);
  startFrame = 0;
  endFrame = desc.Width / desc.Height;
  frameCount = endFrame - startFrame;
  frameWidth = desc.Height; 
  frameHeight = desc.Height;
}

Animation::Animation(IDirect3DTexture9* texture, float frameTime, bool isLooping, int startFrame, int endFrame,int frameWidth, int frameHeight)
: texture(texture),
frameTime(frameTime),
isLooping(isLooping),
startFrame(startFrame),
endFrame(endFrame),
frameWidth(frameWidth),
frameHeight(frameHeight) {
  frameCount = endFrame - startFrame;
}

Animation::~Animation(){}
// AnimationManager.h
#pragma once
#ifndef ANIMATIONPLAYER_H
#define ANIMATIONPLAYER_H

#include "Animation.h"
[...]
class AnimationPlayer
{
private:
  Animation* currentAnimation;
  std::string playing;
  std::map animations;
  int frameIndex;
  float time;
public:
  AnimationPlayer();
  void playAnimation(std::string name);
  void addAnimation(std::string name, Animation* anim);
  void update(float frameTime);
  void draw(ID3DXSprite* spriteBatch, D3DXVECTOR3 position, D3DXMATRIX transform);

  ~AnimationPlayer();
  Animation* getCurrentAnimation(){return currentAnimation;}

  std::string getPlaying(){ return playing; }
  int getFrameIndes() { return frameIndex;}
};
#endif

Animation manager keeps all animations in map, pointer to current animation, playing are easy to guess.

same with methods: playAnimation, addAnimation, draw and getCurrentAnimation but why there is an update method?
well code should make that clear.

// AnimationManager.cpp
#include "AnimationPlayer.h"

AnimationPlayer::AnimationPlayer(){}

AnimationPlayer::~AnimationPlayer(){
  std::map::iterator iter = animations.begin();
  for(; iter != animations.end(); ++iter){
    delete iter->second;
  }
  animations.clear();
}

void AnimationPlayer::playAnimation(std::string name){
  Animation* anim = animations[name];
  if(anim == currentAnimation)
    return;

  currentAnimation = anim;
  playing = name;
  frameIndex = 0;
  time = 0.0f;
}

void AnimationPlayer::update(float frameTime){
  if(currentAnimation == 0)
    return;

  time += frameTime;

  while(time > currentAnimation->getFrameTime()){
    time -=currentAnimation->getFrameTime();
    if(currentAnimation->getIsLooping())
      frameIndex = (++frameIndex) % currentAnimation->getFrameCount();
    else
      frameIndex = min(++frameIndex, currentAnimation->getFrameCount() - 1);
  }
}

void AnimationPlayer::draw(ID3DXSprite* sprite, D3DXVECTOR3 position, D3DXMATRIX transform){
  if(currentAnimation == 0)
    return;
  D3DXMATRIX currentTransform;
  sprite->GetTransform(¤tTransform);
  sprite->SetTransform(&transform);

  int frameX = (frameIndex + currentAnimation->getStartFrame());
  frameX *= currentAnimation->getFrameWidth();

  int frameY = (frameIndex + currentAnimation->getStartFrame());
  frameY *= currentAnimation->getFrameWidth();
  frameY %= currentAnimation->getFrameWidth();

  RECT rect;
  rect.left = frameX;
  rect.right = frameX + currentAnimation->getFrameWidth();
  rect.top = frameY;
  rect.bottom = frameY + currentAnimation->getFrameHeight();

  sprite->Draw(currentAnimation->getTexture(), &rect, 0, &position, D3DCOLOR_XRGB(255,255,255));
  sprite->SetTransform(¤tTransform);
}

I am bit worried because all stuff we do leads us – students to develop 2D based platformer game.. next week we are going to do simple 2d physics and particles.. which is not really necessary in my game.

but good news is.. I have managed to get back on track with my 3D Zombeesh.. some tech demo should be ready by end of the week!! can’t wait!

Published by

Luke Iwanski

Senior Graphics Programmer @ CD Projekt RED

2 thoughts on “Frame Animation manager – 2D”

  1. Cool, I like the way you write ; )
    In the beginning you could add some more general explanations how the code works, that will be very nice.

    So, i will wait for some more difficult stuff 🙂

    *Added blog to favourites*

Leave a Reply to Lukasz Iwanski Cancel reply

Your email address will not be published. Required fields are marked *