Jump to content
  • Advertisement
Sign in to follow this  
fooman_69

Switching Animation Sequences

This topic is 4891 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hiya, In a game where an Entity is in a sequence of animations and switches to another (ex. throwing a ball in my game), how do you handle this? I have an Entity class that has an arrayed list of images for the sequences. But how do I handle the change in my main and keep track of exactly what my Entity should be doing at the time??

Share this post


Link to post
Share on other sites
Advertisement
Are you switching to a specific frame in another squence or just breaking out of the current sequence and into another?

The way you've described things seems to imply you have one master array for all of the entity's images. I wouldn't go this route. Instead, I'd break things up into multiple arrays, or better yet, some sort of collection class to manage the array.

Example:


class Frame{
// Data Members
int length;
String filename;
}

class Sequence{
// Data Members
Frame[] frames;
int currentFrame;
int currentFrameTime;

// Method
void setFrame(int frame){
currentFrame = frame;
}

void draw(){
if(currentFrameTime >= frames[currentFrame].length)
nextFrame();
GameEngine.draw(frames[currentFrame]);
currentFrameTime++;
}

class Player{
// Data Members
Sequence currentSequence;

...

// Methods
void draw(){
currentSequence.draw()
}

void logic(){
if(THROWBUTTONPRESSED)
currentSequence = throwingSequence;
}
}

Share this post


Link to post
Share on other sites
Thats pretty much what I have.... unless I am misunderstanding your logic.

Entity.h
class Entity
{
private:
float mapSpotX;
float mapSpotY;
float *animTime;
float *animTimeLeft;
float lastTime;
char textureID;
bool moveForward;
list<Sprite>::iterator iterate;
list<Sprite> *characterList;
int next;
int currentPlace;
bool iterable;
struct
{
int ammoAmount;
int degree;
int velocity;
}ammoStr;
int score;

bool Resize();
void Iterate();
public:
Entity();
Entity(short x_in, short y_in, char id);
Entity(short x_in, short y_in, char id, Sprite spr, int index);
~Entity();

int GetTextureID();
float GetMapX();
float GetMapY();
Sprite GetImage();
int GetIndex();
int GetAngle();
int GetVelocity();
int GetScore();
bool NewAnimChar(Sprite chr_in);
void UpdateCoords(float x_in, float y_in);
bool NewList(float time);
bool SetIndex(int place);
void SetIterable(bool isIter);
void CheckAnimTime(float time);
void IncreaseAngle();
void DecreaseAngle();
void IncreaseVelocity();
void DecreaseVelocity();
void IncreaseScore();
void DecreaseScore();

void Show();
};



Entity.cpp
#include "entity.h"
#include "globals.h"
#include <fstream>

//=======================================================================
// Name: Constructors and Desctructor
// Desc:
// Types of constructors:
// - Default Entity() -> Really ugly, should not be used often.
// - Entity(short x_in, short y_in, char id)
// -> Takes in map position and texture id, there will be no
// animations.
// - Entity(short x_in, short y_in, char id, Sprite spr, int index)
// -> The same as before, except now a sprite will be added
// into the index taken in.
//========================================================================
Entity::Entity()
{
mapSpotX = -1;
mapSpotY = -1;
textureID = -1;
next = 0;
currentPlace = -1;
characterList = NULL;
iterable = FALSE;
iterate = NULL;
moveForward = TRUE;
animTime = NULL;
animTimeLeft = NULL;
lastTime = 0;

ammoStr.ammoAmount = 0;
ammoStr.degree = 180;
ammoStr.velocity = 50;
score = 0;
}

Entity::Entity(short x_in, short y_in, char id)
{
mapSpotX = x_in;
mapSpotY = y_in;
textureID = id;
next = 0;
currentPlace = -1;
characterList = NULL;
iterable = FALSE;
iterate = NULL;
moveForward = TRUE;
animTime = NULL;
animTimeLeft = NULL;
lastTime = 0;

ammoStr.ammoAmount = 50;
ammoStr.degree = 180;
ammoStr.velocity = 50;
score = 0;
}

Entity::Entity(short x_in, short y_in, char id, Sprite spr, int index)
{
mapSpotX = x_in;
mapSpotY = y_in;
textureID = id;
next = 0;
currentPlace = index;
moveForward = TRUE;

if(!Resize())
characterList[currentPlace].push_back(spr);
iterable = FALSE;
iterate = characterList[currentPlace].begin();

animTime = NULL;
animTimeLeft = NULL;
lastTime = 0;

ammoStr.ammoAmount = 50;
ammoStr.degree = 180;
ammoStr.velocity = 50;
score = 0;
}

Entity::~Entity()
{
if(characterList != NULL)
delete [] characterList;
if(animTime != NULL)
delete [] animTime;
if(animTimeLeft != NULL)
delete [] animTimeLeft;
}

//================================================================
// Name: Get()'s
// Desc: Return basic values used by the Entity.
//================================================================

int Entity::GetTextureID()
{
return textureID;
}

float Entity::GetMapX()
{
return mapSpotX;
}

float Entity::GetMapY()
{
return mapSpotY;
}

Sprite Entity::GetImage()
{
return (*iterate);
}

int Entity::GetIndex()
{
return currentPlace;
}

int Entity::GetAngle()
{
return ammoStr.degree;
}

int Entity::GetVelocity()
{
return ammoStr.velocity;
}

int Entity::GetScore()
{
return score;
}

bool Entity::NewAnimChar(Sprite chr_in)
{
if(currentPlace == -1)
return FALSE;

//if the new image can't be added, send error
characterList[currentPlace].push_back(chr_in);

if(iterate == NULL)
iterate = characterList[currentPlace].begin();
return TRUE;
}

void Entity::UpdateCoords(float x_in, float y_in)
{
mapSpotX = x_in;
mapSpotY = y_in;
}

bool Entity::NewList(float animDelay)
{
//if the time is invalid
if(animDelay < 0)
return FALSE;

if(!Resize())
return FALSE;

//set this section of animations to the specified time
animTime[next - 1] = animDelay;
animTimeLeft[next - 1] = animTime[next - 1];

//if the currentPlace has not been set, this means this is the first
//list of anims. Therefore, automatically they will want the
//this list to be called.
if(currentPlace == -1)
currentPlace = 0;

return TRUE;
}

void Entity::Iterate()
{
//if we aren't spossed to get a new image, return true since
//nothing failed really
if(!iterable)
return;

//if sprite is at the last element, go backwards
if(iterate == characterList[currentPlace].begin())
moveForward = TRUE;
else if(iterate == --characterList[currentPlace].end())
moveForward = FALSE;

//if the tile direction is forward, get next
//otherwise get the previous tile
if(moveForward)
iterate++;
else
iterate--;
}

bool Entity::SetIndex(int place)
{
//if intended index is too large, return error
if(place > next - 1)
return FALSE;

currentPlace = place; //set index
iterate = characterList[currentPlace].begin(); //start at the beginning of list

return TRUE;
}

void Entity::SetIterable(bool isIter)
{
iterable = isIter;
}

//===========================================================================
// Name: CheckAnimTime(float)
// Desc: This function will determine if the Entity should proceed to
// the next image in the animation sequence. If so, it will iterate
// to the next image.
//===========================================================================

void Entity::CheckAnimTime(float time)
{
//find the difference from that last time this function was called
float diff = time - lastTime;
lastTime = time; //assign lastTime it's new value
animTimeLeft[currentPlace] -= diff; //figure out how much time is still left
if(animTimeLeft[currentPlace] < 1)
{
this->Iterate(); //iterate if time is up
animTimeLeft[currentPlace] = animTime[currentPlace];//set timeLeft back to normal
}
}

//=========================================================================
// Name: Increase/Decrease's()
// Desc: Will increase/decrease the angle of the projectile by one unit.
// The angle is only able to go between 0-180 degrees.
// Will also update scores the same way.
// Will increase velocity in the range of 1 - 100.
//=========================================================================

void Entity::IncreaseAngle()
{
//if angle is under 181, add another degree
if(ammoStr.degree < 180)
ammoStr.degree++;

return;
}

void Entity::DecreaseAngle()
{
//if angle is over 0, add another degree
if(ammoStr.degree > 0)
ammoStr.degree--;

return;
}

void Entity::IncreaseVelocity()
{
//if velocity is under 100, add another degree
if(ammoStr.velocity < 100)
ammoStr.velocity++;

return;
}

void Entity::DecreaseVelocity()
{
//if velocity is over 1, add another degree
if(ammoStr.velocity > 1)
ammoStr.velocity--;

return;
}

void Entity::IncreaseScore()
{
score++;
return;
}

void Entity::DecreaseScore()
{
score--;
return;
}

//======================================================================
// Name: Resize()
// Desc: Used for resizing dynamic arrays such as the characterList.
//======================================================================

bool Entity::Resize()
{
//assign old data to holder array for safe keeping
//and then resize array
list<Sprite> *pOld = characterList;
characterList = new list<Sprite>[next + 1];
float *pOldTime = animTime;
animTime = new float[next + 1];
float *pOldTimeLeft = animTimeLeft;
animTimeLeft = new float[next + 1];

//error check
if(characterList == NULL || animTime == NULL || animTimeLeft == NULL)
{
characterList = pOld;
animTime = pOldTime;
animTimeLeft = pOldTimeLeft;
return false;
}

//copy data
for(int i = 0; i < next; i++)
{
characterList = pOld;
animTime = pOldTime;
animTimeLeft = pOldTimeLeft;
}

next++;
delete [] pOld;
delete [] pOldTime;
delete [] pOldTimeLeft;
return true;
}

//=========================================================================
// Name: Show()
// Desc: Used for debugging purposes. It will write to a basic txt file
// anything that I need to know about the Entity. The function is
// always changing.
//=========================================================================

void Entity::Show()
{
ofstream fout4;
fout4.open("Error Logs/EntityShow.txt", ios::out);

fout4 << "Degs: " << ammoStr.degree << endl;

fout4.close();
}


So I have a pointer to a list, which can switch indexes of sequences, just as yours can. But I am having a problem with things such as doing a sequence once, then continuing an ongoing sequence such as breathing or whatever. I get confused when I try to work out an easy way to do it.

Share this post


Link to post
Share on other sites
How about using a stack to manage sequences that overlay looped ones?

So, you've got a character running, and you're looping the running animation.
But then the character throws a ball, so you push the throwing animation onto the stack.
When the ball throwing animation is done, then it gets popped off the stack and back to the looped running animation.

There are problems with this. If the character stops running while he's throwing the ball then when the throw animation gets pushed, the running animation won't be applicable even though it is supposedly the proper animation in the stack.

The trick with this then is to tie your animations into your logic while still maintaining their portability. Have the entity check to see if it's animation is correct rather than the animation check to see if it is correct with the entity. Once things get to the "what if" stage, there arn't any eloquent solutions except to just hack through with logic. By "what if" I mean: What if the character stops while throwing the ball? What if the ball powers up while it is being thrown? What if, what if, what if = if else if else if else, - this is the fun content part of development.

Share this post


Link to post
Share on other sites
Ok thanks for the replies!!
Also, I guess I could set a flag in my Entity for looping the sequence or exiting the sequence after it has its run.
But your idea is also pretty decent answer that I will try out!
Awesome!!!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!