Sign in to follow this  
Delfi

texture animation trough time

Recommended Posts

hi, i am working on a little game and this is a math question: from one specific time when i start the game simulation the textures animate, the texture animation system cycles every frame and it rotates trough all animated textures when certain amout of frames are passed it changes to next texture in the list. but this is fixed to FPS number.. but i'd like to calculate which frame should be shown for fixed time distances so the game works correct on most pc's with different hardware but i have no idea how to do that.. i hope you understand what i mean ;)

Share this post


Link to post
Share on other sites
Here is a class I use in my engine

#define KANI_TYPE_STATIC 1
#define KANI_TYPE_CONTINUOUS 2
#define KANI_TYPE_SINGLEPASS 3

/********************************************************************/
/* Declaration of the K3DANIMATIONCONTROLLER */
/* An animation is a sequence frames which define movement. */
/* The K3DANIMATIONCONTROLLER holds information that define movement*/
/* like the animation start frame, number of animation frames, */
/* time required to play all the frames of the animation, */
/* and the animation type. (STATIC for a single frame, CONTINUOUS */
/* for a periodic movement and SINGLEPASS for a movement that */
/* should be played only once. */
/********************************************************************/
class KGRAPHICS3D_API K3DANIMATIONCONTROLLER{
public:
WORD ID;
BYTE iStartFrame;
BYTE iFrames; //Number of frames in the animation
float fFrames; //Number of frames in the animation (for floating operations)
float fAnimTime; //time to complete all the animation
BYTE iType; //Tipo de animacion

K3DANIMATIONCONTROLLER(WORD iID, BYTE iStartFrame, BYTE iFrames, float fAnimTime, BYTE iType);
~K3DANIMATIONCONTROLLER();

//para evitar el conflicto de pasar punteros de EXE a DLL
void* operator new( size_t tSize );
void operator delete( void* p );

virtual HRESULT FlushAll();
float GetAnimationTime();
BYTE GetAnimationType();
float GetWeight(float eTime); //Returns the weight for the assigned time. The weight is a midpoint in the [0,1[ range. The weight is computed by interpolating the eTIme between the frame time after and before the eTime.
float Move(float actTime, float eTime, float *uTime, float *lTime); //Compute the time time index if we add a eTime into the current time
int GetFrame(float eTime);
int GetNextFrame(float eTime);
};
typedef K3DANIMATIONCONTROLLER* LPK3DANIMATIONCONTROLLER;



/********************************************************************/
/* */
/* Implementacion de la clase K3DANIMATIONCONTROLLER */
/* */
/********************************************************************/
K3DANIMATIONCONTROLLER::K3DANIMATIONCONTROLLER(WORD iID, BYTE iiStartFrame, BYTE iiFrames,
float ifAnimTime, BYTE iiType)
{
ID=iID;
iStartFrame = iiStartFrame;
iFrames = iiFrames;
fFrames = (float)iFrames;
fAnimTime = ifAnimTime;
iType = iiType;
};

K3DANIMATIONCONTROLLER::~K3DANIMATIONCONTROLLER()
{ FlushAll();
};

void* K3DANIMATIONCONTROLLER::operator new( size_t tSize ) { void* p=malloc(tSize); return p; };
void K3DANIMATIONCONTROLLER::operator delete( void* p ) { free(p); };

//Nothing
HRESULT K3DANIMATIONCONTROLLER::FlushAll()
{ return S_OK;
}

//Returns the animation time
float K3DANIMATIONCONTROLLER::GetAnimationTime()
{ return fAnimTime; }

BYTE K3DANIMATIONCONTROLLER::GetAnimationType()
{ return iType; }

//Returns the weight for the assigned time. The weight is a midpoint in the [0,1[ range.
//The weight is computed by interpolating the eTIme between the frame time after and before the eTime.
float K3DANIMATIONCONTROLLER::GetWeight(float eTime)
{ float frameTime=(float)fAnimTime/fFrames;
if(frameTime==0) return 0;
return (float)fmod(eTime,frameTime)/frameTime; //retorna el resto
}

//Computes the time index for the animatian after we add a time (eTime) into the current time (actTime)
// the uTime and lTime parameters return the values of the used time and the time left after the movement
float K3DANIMATIONCONTROLLER::Move(float actTime, float eTime, float *uTime, float *lTime)
{
//Corte inicial, si mi tipo de animacion es estatica, entonces ignoro todo
if(iType==KANI_TYPE_STATIC)
{ actTime=0;
*uTime=(float)fabs(eTime);
*lTime=0;
return actTime;
}

float destTick;

switch(iType)
{ case KANI_TYPE_CONTINUOUS:
{ //Mi animacion es continua, entonces debo regresar por el otro lado
destTick=actTime+eTime;
//Si sali por el inicio, regreso por el final
if(eTime>0)
{ while(destTick>fAnimTime)
{ destTick-=fAnimTime; }
}
else //eTime<0
{ while(destTick<0)
{ destTick+=fAnimTime; }
};

//la animacion continua consume todo el tiempo
actTime=destTick;
*lTime=0;
*uTime=(float)fabs(eTime);
//listo
} break;

case KANI_TYPE_SINGLEPASS:
{ //Esta animacion solo tiene una pasada
actTime+=eTime;
if(eTime>0)
{ //La animacion va hacia adelante
//avanzo y si no hay mas devuelvo el maximo
if(actTime>fAnimTime)
actTime=fAnimTime;
else
*uTime=(float)fabs(eTime);
}
else //eTime<0
{ //La animacion va hacia atras
//retrocedo y si no hay mas, devuelvo 0
if(actTime<0)
actTime=0;
else
*uTime=(float)fabs(eTime);
};

*lTime=0;

} break;
}; //de SWITCH TYPE

return actTime;

}


//Returns the frame for the selected time index
int K3DANIMATIONCONTROLLER::GetFrame(float eTime)
{ if(fAnimTime==0) return iStartFrame;
float cTime=(float)fmod(eTime,fAnimTime); //retorna el resto
return ( iStartFrame + (DWORD)(cTime*iFrames/fAnimTime) );
}

//Returns the frame that follows an animation on the selected time index
int K3DANIMATIONCONTROLLER::GetNextFrame(float eTime)
{ if(fAnimTime==0) return iStartFrame;
float cTime=(float)fmod(eTime,fAnimTime); //retorna el resto
return ( iStartFrame + ((DWORD)(cTime*iFrames/fAnimTime)+1)%iFrames );
}



Sorry if the code is messy... I dont know how to send code in this forum. The idea is simple, you create an object and provide the initial parameters. IE... create a controller with id 5, starts in frame 0, has 32 frames and the total animation time is 2000 millisecs. The animation is continuous so the frame 31 continues in frame 0
K3DANIMATIONCONTROLLER c(5, 0, 32, 2000, KANI_TYPE_CONTINUOUS);

Now, consider you are in time 3000, after that you want to get the frame located in msec 5000. You just query:
int f=GetFrame(5000);
this will return the appropiate frame in our 0-31 range for that time. You can also query the next frame
int nf=GetNextFrame(5000);

note that nf is not just f+1... if you are in frame 31 the next frame will be 0. Its just a simple operation but this class makes it easier.

Now, you can compute the frame weight. This is an interpolation factor between frames. Say, i.e. if frame f1 is in time 1000 and f2 is in time 1100, then if you query the weight for time 1040:
float w = GetWeight(1040);

It will return 0.4... that is 40/1100-1000. Good for interpolated animation.

If you play a little with this class you may find some other things.

Luck!
Guimo

Share this post


Link to post
Share on other sites
thanx, now that will take me a while to convert
to delphi and to use records instead objects..

now i at least understand how i need to calculate
frame and i need for such thing :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this