/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ /*! \file t_animation.h */ #ifndef _T_ANIMATION_H #define _T_ANIMATION_H #include "animation.h" //! A Class to handle some animation for single floated values. template class tAnimation : public Animation { public: tAnimation(T* object = NULL, void (T::*funcToAnim)(float) = NULL); virtual ~tAnimation(); virtual void rewind(); void setFuncToAnim(T* object, void (T::*funcToAnim)(float)); void addKeyFrame(float value, float duration, ANIM_FUNCTION animFunc = ANIM_LINEAR); virtual void tick(float dt); // animation functions void setAnimFunc(ANIM_FUNCTION animFunc); private: float constant(float timePassed) const; float linear(float timePassed) const; float sine(float timePassed) const; float cosine(float timePassed) const; float exp(float timePassed) const; float negExp(float timePassed) const; float quadratic(float timePassed) const; float random(float timePassed) const; // ANIM_FUNCTION animFunc; float (tAnimation::*animFunc)(float) const; KeyFrameF* currentKeyFrame; KeyFrameF* nextKeyFrame; tList* keyFrameList; float expFactor; T* object; void (T::*funcToAnim)(float); }; /** \brief standard constructor */ template tAnimation::tAnimation (T* object, void (T::*funcToAnim)(float)) { // create a new List this->keyFrameList = new tList(); KeyFrameF* tmpKeyFrame = new KeyFrameF; tmpKeyFrame->value = 0.0; tmpKeyFrame->duration = 1.0; keyFrameList->add(tmpKeyFrame); this->currentKeyFrame = tmpKeyFrame; this->nextKeyFrame = tmpKeyFrame; this->animFunc = &tAnimation::linear; this->setFuncToAnim(object, funcToAnim); } /** \brief standard deconstructor */ template tAnimation::~tAnimation () { // delete all the KeyFrames tIterator* itKF = keyFrameList->getIterator(); KeyFrameF* enumKF = itKF->nextElement(); while (enumKF) { delete enumKF; enumKF = itKF->nextElement(); } delete itKF; delete this->keyFrameList; } template void tAnimation::rewind(void) { this->currentKeyFrame = keyFrameList->firstElement(); this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement()); this->localTime = 0.0; } template void tAnimation::setFuncToAnim(T* object, void (T::*funcToAnim)(float)) { this->baseObject = this->object = object; this->funcToAnim = funcToAnim; } template void tAnimation::addKeyFrame(float value, float duration, ANIM_FUNCTION animFunc) { // some small check if (duration <= 0.0) duration = 1.0; KeyFrameF* tmpKeyFrame; if (bHasKeys) { tmpKeyFrame = new KeyFrameF; if (this->currentKeyFrame == this->nextKeyFrame) this->nextKeyFrame = tmpKeyFrame; this->keyFrameList->add(tmpKeyFrame); } else { tmpKeyFrame = this->keyFrameList->firstElement(); bHasKeys = true; this->setAnimFunc(animFunc); } tmpKeyFrame->value = value; tmpKeyFrame->duration = duration; tmpKeyFrame->animFunc = animFunc; } template void tAnimation::tick(float dt) { if (this->bRunning) { this->localTime += dt; if (localTime >= this->currentKeyFrame->duration) { // switching to the next Key-Frame this->localTime -= this->currentKeyFrame->duration; this->currentKeyFrame = this->nextKeyFrame; // checking, if we should still Play the animation if (this->currentKeyFrame == this->keyFrameList->lastElement()) { switch (this->postInfinity) { case ANIM_INF_CONSTANT: this->bRunning = false; break; case ANIM_INF_REWIND: break; } } this->nextKeyFrame = this->keyFrameList->nextElement(this->nextKeyFrame); printf("%p from:%f to:%f\n", this->currentKeyFrame,this->currentKeyFrame->value, this->nextKeyFrame->value); this->setAnimFunc(this->currentKeyFrame->animFunc); } (this->object->*(funcToAnim))((this->*animFunc)(this->localTime)); } } template void tAnimation::setAnimFunc(ANIM_FUNCTION animFunc) { switch (animFunc) { default: case ANIM_CONSTANT: this->animFunc = &tAnimation::constant; break; case ANIM_LINEAR: this->animFunc = &tAnimation::linear; break; case ANIM_SINE: this->animFunc = &tAnimation::sine; break; case ANIM_COSINE: this->animFunc = &tAnimation::cosine; break; case ANIM_EXP: this->animFunc = &tAnimation::exp; break; case ANIM_NEG_EXP: { this->animFunc = &tAnimation::negExp; float d = fabs(this->currentKeyFrame->value - this->nextKeyFrame->value); expFactor = - 1.0 / this->currentKeyFrame->duration * logf(DELTA_X); break; } case ANIM_QUADRATIC: this->animFunc = &tAnimation::quadratic; break; case ANIM_RANDOM: this->animFunc = &tAnimation::random; break; } } // animation functions template float tAnimation::random(float timePassed) const { return (float)rand()/(float)RAND_MAX; } template float tAnimation::constant(float timePassed) const { return this->currentKeyFrame->value; } template float tAnimation::linear(float timePassed) const { return this->currentKeyFrame->value + (this->nextKeyFrame->value - this->currentKeyFrame->value) * (timePassed / this->currentKeyFrame->duration); // PRINTF(0)("value is %f, %p %p\n", val, this->currentKeyFrame, this->nextKeyFrame); // return val; } template float tAnimation::sine(float timePassed) const { float d = this->currentKeyFrame->value - this->nextKeyFrame->value; float e = 0.5 * d * (1 - cos(M_PI * timePassed / this->currentKeyFrame->duration)); return this->currentKeyFrame->value - e; /* return his->currentKeyFrame->value - (this->nextKeyFrame->value - this->currentKeyFrame->value) * sin(timePassed / this->currentKeyFrame->duration * M_PI); */ } template float tAnimation::cosine(float timePassed) const { float d = this->currentKeyFrame->value - this->nextKeyFrame->value; float e = 0.5 * d * (sin(M_PI * timePassed / this->currentKeyFrame->duration)); if( timePassed > 0.5*this->currentKeyFrame->duration) e = (d - e); return this->currentKeyFrame->value - e; /* return this->currentKeyFrame->value - (this->nextKeyFrame->value - this->currentKeyFrame->value) * cos(timePassed / this->currentKeyFrame->duration * M_PI); */ } template float tAnimation::exp(float timePassed) const { } template float tAnimation::negExp(float timePassed) const { float d = this->currentKeyFrame->value - this->nextKeyFrame->value; float e = d * (1.0 - expf(- timePassed * expFactor)); return this->currentKeyFrame->value - e; } template float tAnimation::quadratic(float timePassed) const { } #endif /* _T_ANIMATION_H */