Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

CSAnimation.cpp

Go to the documentation of this file.
00001 #ifdef WIN32
00002 #pragma warning(disable : 4786 )
00003 #endif
00004 #include "CSAnimation.h"
00005 #include "CSXMLHelper.h"
00006 
00007 CSAnimationLoader CSAnimationLoader::INSTANCE;
00008 const char *CSAnimation::CLASS = "CSAnimation";
00009 
00010 CSAnimation::CSAnimation(const std::string &filename)
00011 {
00012     static char *functionName="CSAnimation";
00013     LOG_ENTER 
00014     CSAnimationData data;
00015     loadAnimationData(filename, data);
00016     initialize(data);
00017     LOG_EXIT
00018 }
00019 
00020 CSAnimation::CSAnimation(const CSAnimation &animation)
00021 {
00022     static char *functionName="CSAnimation";
00023     LOG_ENTER 
00024     mSecsPerFrame = animation.mSecsPerFrame;
00025     mSizePictures = animation.mSizePictures;
00026     mSizePhases = animation.mSizePhases;
00027     mMoveAllowed = animation.mMoveAllowed;
00028     mRepeatable = animation.mRepeatable;
00029     mIsBreakable = animation.mIsBreakable;
00030     mIsSolid = animation.mIsSolid;
00031 
00032     mPhases = new unsigned int[mSizePhases];
00033     for (int i=0; i < mSizePhases; i++)
00034     {
00035         mPhases[i] = animation.mPhases[i];
00036     }
00037 
00038     mPictures = new CSPictures();
00039     mAnimationRates = new float[mSizePictures];
00040     mMoveX = new signed int[mSizePictures];
00041     mMoveY = new signed int[mSizePictures];
00042     i = 0;
00043     CSPictures::iterator iter = animation.mPictures->begin();
00044     while (iter != animation.mPictures->end())
00045     {
00046         CSPicture *pic = *iter;
00047         // picture need not be loaded again->
00048         // we can use the same pointer since it is a singleton anyway!
00049         mPictures->push_back(pic);
00050 
00051         mAnimationRates[i] = animation.mAnimationRates[i];
00052         mMoveX[i] = animation.mMoveX[i];
00053         mMoveY[i] = animation.mMoveY[i];
00054         i++;
00055         iter++;
00056     }
00057     LOG_EXIT
00058 }
00059 
00060 void CSAnimation::initialize(void)
00061 {
00062     static char *functionName="initialize";
00063     LOG_ENTER 
00064     mMoveX = 0;
00065     mMoveY = 0;
00066     mPictures = 0;
00067     mSizePictures = 0;
00068     mSizePhases = 0;
00069     mPhases = 0;
00070     mAnimationRates = 0;
00071     mMoveAllowed = true;
00072     mRepeatable = 0;
00073     mIsBreakable = 0;
00074     mIsSolid = false;;
00075     mSecsPerFrame = 0.01f;
00076     LOG_EXIT
00077 }
00078 
00079 void CSAnimation::initialize(const CSAnimationData &data)
00080 {
00081     static char *functionName="initialize";
00082     LOG_ENTER 
00083     int i = 0;
00084     initialize();
00085     mIsBreakable = data.isBreakable;
00086     mRepeatable = data.repeatable;
00087     mSizePhases = data.sizePhases;
00088     mPhases = new unsigned int[mSizePhases];
00089     for (i; i < mSizePhases; i++)
00090     {
00091         mPhases[i] = data.phases[i];
00092     }
00093 
00094     // how many pictures are there?
00095     // is there a better way, to get the size of a vector?
00096     // data.pictures->size() :-)
00097     CSAnimationPictures::const_iterator iter = data.pictures->begin();
00098     while (iter != data.pictures->end())
00099     {
00100         iter++;
00101         mSizePictures++;
00102     }
00103 
00104     mPictures = new CSPictures();
00105     mAnimationRates = new float[mSizePictures];
00106     mMoveX = new signed int[mSizePictures];
00107     mMoveY = new signed int[mSizePictures];
00108     i = 0;
00109     iter = data.pictures->begin();
00110     while (iter != data.pictures->end())
00111     {
00112         // picture must be loaded
00113         CSPicture *pic = CSPictureLoader::INSTANCE.load((*iter)->filename);
00114 
00115         mPictures->push_back(pic);
00116         mAnimationRates[i] = (*iter)->animationRate;
00117         // negative animation rates are not in animtions per second
00118         // but aniamtion each # of seconds!
00119         if (mAnimationRates[i]<0)
00120         {
00121             mAnimationRates[i] *= -1;
00122             mAnimationRates[i] = (float) (1.0f/mAnimationRates[i]);
00123         }
00124         mMoveX[i] = (*iter)->moveX;
00125         mMoveY[i] = (*iter)->moveY;
00126         i++;
00127         iter++;
00128     }
00129     LOG_EXIT
00130 }
00131 
00132 CSAnimation::~CSAnimation()
00133 {
00134     static char *functionName="~CSAnimation";
00135     LOG_ENTER 
00136     if (mPictures != 0)
00137     {
00138         // CSPictures are deleted by CSPictureLoader!
00139         delete mPictures;
00140         mPictures = 0;
00141     }   
00142     if (mPhases != 0)
00143     {
00144         delete []mPhases;
00145         mPhases = 0;
00146     }
00147     if (mAnimationRates != 0)
00148     {
00149         delete []mAnimationRates;
00150         mAnimationRates = 0;
00151     }
00152     if (mMoveX !=0)
00153     {
00154         delete []mMoveX;
00155         mMoveX = 0;
00156     }
00157     if (mMoveY !=0)
00158     {
00159         delete []mMoveY;
00160         mMoveY = 0;
00161     }
00162     LOG_EXIT
00163 }
00164 
00165 void CSAnimation::setSecPerFrame(float secPerFrame)
00166 {
00167     static char *functionName="setSecPerFrame";
00168     LOG_ENTER 
00169     mSecsPerFrame = secPerFrame;
00170     LOG_EXIT
00171 }
00172 
00173 void CSAnimation::setSolid(bool b)
00174 {
00175     static char *functionName="setSolid";
00176     LOG_ENTER 
00177     mIsSolid = b;
00178     for (CSPictures::iterator iter = mPictures->begin(); iter != mPictures->end(); iter++)
00179     {
00180         CSPicture *pic = *iter;
00181         pic->setSolid(b);
00182     }
00183     LOG_EXIT
00184 }
00185 
00186 void CSAnimation::setAlpha(int alpha)
00187 {
00188     static char *functionName="setAlpha";
00189     LOG_ENTER 
00190     for (CSPictures::iterator iter = mPictures->begin(); iter != mPictures->end(); iter++)
00191     {
00192         CSPicture *pic = *iter;
00193         pic->setAlpha(alpha);
00194     }
00195     LOG_EXIT
00196 }
00197 
00198 //! build an initial state for this aniamtion, sets variables to defaults
00199 AnimationState CSAnimation::buildState()
00200 {
00201     static char *functionName="buildState";
00202     AnimationState state;
00203     state.mXPos = 0;
00204     state.mYPos = 0;
00205     state.mCurrentPhase = 0;
00206     state.mCurrentPicture = mPhases[state.mCurrentPhase];
00207     state.mPicture = mPictures->at(state.mCurrentPicture);
00208     state.mAnimationRateCounter = 0;
00209     state.mForward = true;
00210     state.mFinished = false;
00211     return state;
00212 }
00213 
00214 //! resets a state to default values
00215 //! doesn't  update mDisplayParams! 
00216 //! (this position and mDisplayPicture do not change!)
00217 void CSAnimation::resetState(AnimationState& state)
00218 {
00219     static char *functionName="resetState";
00220     state.mCurrentPhase = 0;
00221     state.mCurrentPicture = mPhases[state.mCurrentPhase];
00222     state.mPicture = mPictures->at(state.mCurrentPicture);
00223     state.mAnimationRateCounter = 0;
00224     state.mSpeedX = ANIMATION_SPEED;
00225     state.mSpeedY = ANIMATION_SPEED;
00226     state.mForward = true;
00227     state.mFinished = false;
00228     state.mXPos = 0;
00229     state.mYPos = 0;
00230 }
00231 
00232 //! resets a state to start values of this animations mDisplayParams!  -> immediately
00233 //! THIS will be displayed during next display() call
00234 //! happens when an event for another action occurs or so
00235 void CSAnimation::startAnimation(AnimationState& state)
00236 {
00237     static char *functionName="startAnimation";
00238     state.mCurrentPhase = 0;
00239     state.mCurrentPicture = mPhases[state.mCurrentPhase];
00240     state.mPicture = mPictures->at(state.mCurrentPicture);
00241     state.mAnimationRateCounter = 0;
00242     state.mForward = true;
00243     state.mFinished = false;
00244     state.mDisplayParams.mXPos = state.mXPos;
00245     state.mDisplayParams.mYPos = state.mYPos;
00246     state.mDisplayPicture = state.mPicture;
00247 }
00248 
00249 //! resets a state to start values of this animation
00250 //! this will not be displayed during next display() call
00251 //! happens when one animation ends during update, and a next
00252 //! animation is initiated - this means the next animation is
00253 //! active from the start of next update, doesn't interfere with
00254 //! current mDisplayParams!
00255 void CSAnimation::startNextAnimation(AnimationState& state)
00256 {
00257     static char *functionName="startNextAnimation";
00258     state.mCurrentPhase = 0;
00259     state.mCurrentPicture = mPhases[state.mCurrentPhase];
00260     state.mPicture = mPictures->at(state.mCurrentPicture);
00261     state.mAnimationRateCounter = 0;
00262     state.mForward = true;
00263     state.mFinished = false;
00264 }
00265 
00266 //! of all pictures belonging to this animation 
00267 //! return the largest width
00268 unsigned int CSAnimation::getMaxX()
00269 {
00270     static char *functionName="getMaxX";
00271     unsigned int maxX = 0;
00272     unsigned int x;
00273     for (CSPictures::iterator iter = mPictures->begin(); iter != mPictures->end(); iter++)
00274     {
00275         CSPicture *pic = *iter;
00276         x = pic->getMaxX(); if (maxX < x) maxX = x;
00277     }
00278     return maxX;
00279 }
00280 
00281 //! of all pictures belonging to this animation 
00282 //! return the largest height
00283 unsigned int CSAnimation::getMaxY()
00284 {
00285     static char *functionName="getMaxY";
00286     unsigned int maxY = 0;
00287     unsigned int y;
00288     for (CSPictures::iterator iter = mPictures->begin(); iter != mPictures->end(); iter++)
00289     {
00290         CSPicture *pic = *iter;
00291         y = pic->getMaxY(); if (maxY < y) maxY = y;
00292     }
00293     return maxY;
00294 }
00295 
00296 //! if finished and not repeat -> false, true otherwise
00297 //! does not display anything, but prepares (update) for next displaying
00298 bool CSAnimation::next(AnimationState& state)
00299 {
00300     static char *functionName="next";
00301     if (state.mFinished)
00302     {
00303         return !state.mFinished;
00304     }
00305 
00306     // if an animation has only one picture, it is not really
00307     // much of an aniamtion -> display it, regardless
00308     // of any counters,
00309     // thus an aniamtion with only one picture never ends!
00310     if (mSizePictures <= 1)
00311     {
00312         if (mMoveAllowed)
00313         {
00314             // speed calculated vi frame per second
00315             if (state.mSpeedX == ANIMATION_SPEED)
00316             {
00317                 state.mXPos += (float) (mMoveX[state.mCurrentPicture]*mSecsPerFrame);
00318             }
00319             else if (state.mSpeedX == ADJUST_SPEED)
00320             {
00321                 int speed = 0;
00322                 if (mMoveX[state.mCurrentPicture] < 0) 
00323                     speed = -state.mAdjustSpeed;
00324                 if (mMoveX[state.mCurrentPicture] > 0) 
00325                     speed = state.mAdjustSpeed;
00326                 state.mXPos += (float) (speed*mSecsPerFrame);
00327             }
00328             else 
00329             {
00330                 state.mXPos += (float) (state.mSpeedX*mSecsPerFrame);
00331             }
00332 
00333             if (state.mSpeedY == ANIMATION_SPEED)
00334             {
00335                 state.mYPos += (float) (mMoveY[state.mCurrentPicture]*mSecsPerFrame);
00336             }
00337             else if (state.mSpeedY == ADJUST_SPEED)
00338             {
00339                 int speed = 0;
00340                 if (mMoveY[state.mCurrentPicture] < 0) 
00341                     speed = -state.mAdjustSpeed;
00342                 if (mMoveY[state.mCurrentPicture] > 0) 
00343                     speed = state.mAdjustSpeed;
00344                 state.mYPos += (float) (speed*mSecsPerFrame);
00345             }
00346             else
00347             {
00348                 state.mYPos += (float) (state.mSpeedY*mSecsPerFrame);
00349             }
00350         }
00351 
00352         state.mDisplayParams.mXPos = state.mXPos;
00353         state.mDisplayParams.mYPos = state.mYPos;
00354         state.mDisplayPicture = state.mPicture;
00355         return true;
00356     }
00357 
00358     // animation rate calculated vi frame per second
00359     state.mAnimationRateCounter += (float) (mAnimationRates[state.mCurrentPicture] * mSecsPerFrame);
00360     // if animation frame should change
00361     if (state.mAnimationRateCounter >= 1)
00362     {
00363         state.mAnimationRateCounter = 0;
00364         if (mRepeatable == CS_RANDOM)
00365         {
00366             // TODO
00367         }
00368         else
00369         {
00370             if (state.mForward)
00371             {
00372                 state.mCurrentPhase++;
00373                 if (state.mCurrentPhase == mSizePhases)
00374                 {
00375                     if (mRepeatable == CS_INVERSE_REPEATABLE)
00376                     {
00377                         state.mForward = !state.mForward;
00378                         if (mSizePhases > 1)
00379                         {
00380                             state.mCurrentPhase-=2;
00381                         }
00382                         else
00383                         {
00384                             state.mCurrentPhase--;
00385                         }
00386                     }
00387                     else
00388                     if (mRepeatable == CS_INVERSE_ONCE)
00389                     {
00390                         state.mForward = !state.mForward;
00391                         if (mSizePhases > 1)
00392                         {
00393                             state.mCurrentPhase-=2;
00394                         }
00395                         else
00396                         {
00397                             state.mCurrentPhase--;
00398                         }
00399                     }
00400                     else
00401                     {
00402                         if (mRepeatable == CS_NOT_REPEATABLE)
00403                         {
00404                             state.mFinished = true;
00405                             return !state.mFinished;
00406                         }
00407                         state.mCurrentPhase = 0;
00408                     }
00409                 }
00410             }
00411             else // mForward
00412             {
00413                 state.mCurrentPhase--;
00414                 if (state.mCurrentPhase == -1)
00415                 {
00416                     if (mRepeatable == CS_INVERSE_REPEATABLE)
00417                     {
00418                         state.mForward = !state.mForward;
00419                         if (mSizePhases > 1)
00420                         {
00421                             state.mCurrentPhase+=2;
00422                         }
00423                         else
00424                         {
00425                             state.mCurrentPhase++;
00426                         }
00427                     }
00428                     else
00429                     {
00430                         if (mRepeatable == CS_INVERSE_ONCE)
00431                         {
00432                             state.mFinished = true;
00433                             return !state.mFinished;
00434                         }
00435                         state.mCurrentPhase = 0;
00436                     }
00437                 }
00438             }
00439         } // else (mRepeatable == CS_RANDOM)
00440         state.mCurrentPicture = mPhases[state.mCurrentPhase];
00441         state.mPicture = mPictures->at(state.mCurrentPicture);
00442     } // (state.mDelayCounter == mDelays[mPhases[state.mCurrentPhase]])
00443 
00444     if (mMoveAllowed)
00445     {
00446         // speed calculated vi frame per second
00447         if (state.mSpeedX == ANIMATION_SPEED)
00448         {
00449             state.mXPos += (float) (mMoveX[state.mCurrentPicture]*mSecsPerFrame);
00450         }
00451         else if (state.mSpeedX == ADJUST_SPEED)
00452         {
00453             int speed = 0;
00454             if (mMoveX[state.mCurrentPicture] < 0) 
00455                 speed = -state.mAdjustSpeed;
00456             if (mMoveX[state.mCurrentPicture] > 0) 
00457                 speed = state.mAdjustSpeed;
00458             state.mXPos += (float) (speed*mSecsPerFrame);
00459         }
00460         else 
00461         {
00462             state.mXPos += (float) (state.mSpeedX*mSecsPerFrame);
00463         }
00464 
00465         if (state.mSpeedY == ANIMATION_SPEED)
00466         {
00467             state.mYPos += (float) (mMoveY[state.mCurrentPicture]*mSecsPerFrame);
00468         }
00469         else if (state.mSpeedY == ADJUST_SPEED)
00470         {
00471             int speed = 0;
00472             if (mMoveY[state.mCurrentPicture] < 0) 
00473                 speed = -state.mAdjustSpeed;
00474             if (mMoveY[state.mCurrentPicture] > 0) 
00475                 speed = state.mAdjustSpeed;
00476             state.mYPos += (float) (speed*mSecsPerFrame);
00477         }
00478         else
00479         {
00480             state.mYPos += (float) (state.mSpeedY*mSecsPerFrame);
00481         }
00482 
00483         state.mDisplayParams.mXPos = state.mXPos;
00484         state.mDisplayParams.mYPos = state.mYPos;
00485     }
00486     state.mDisplayPicture = state.mPicture;
00487     return true;
00488 }
00489 
00490 //! not much to do here, to display a picture
00491 void CSAnimation::display(AnimationState& state)
00492 {
00493     static char *functionName="display";
00494     state.mDisplayPicture->display(&(state.mDisplayParams));
00495 }
00496 
00497 void CSAnimation::loadAnimationData(const std::string &filename, CSAnimationData &data)
00498 {
00499     static char *functionName="loadAnimationData";
00500     LOG_ENTER 
00501     char tmp[10];
00502     
00503     CSXMLHelper xmlSupport(filename, "ANIMATION");
00504     try
00505     {
00506         if (xmlSupport.getError())
00507         {
00508             LOG_EXIT
00509             throw "error";
00510         }
00511 
00512         data.id = strdup(xmlSupport.getString("ID").c_str());
00513         data.isBreakable = xmlSupport.getInt("IS_BREAKABLE") == 1;
00514         data.repeatable = xmlSupport.getInt("REPEATABLE");
00515 
00516         data.sizePhases = xmlSupport.getInt("count(/ANIMATION/PHASE)");
00517         data.phases = new unsigned int[data.sizePhases];
00518         for (int i=0; i<data.sizePhases; i++)
00519         {
00520             // i+1, predicates in xpath start with 1
00521             data.phases[i] = xmlSupport.getInt((std::string)"/ANIMATION/PHASE["+itoa(i+1,tmp,10)+"]");
00522         }
00523         CSAnimationPictures *pictures = new CSAnimationPictures();          // above data for animation pictures
00524         data.pictures = pictures;
00525         int imageCount = xmlSupport.getInt("count(/ANIMATION/IMAGE_DATA)");
00526         for (i = 0; i<imageCount; i++)
00527         {
00528             CSAnimationPicture *picStruct = new CSAnimationPicture();
00529             if (picStruct==NULL)
00530             {
00531                 LOG_EXIT
00532                 SDLMain::shutdown((std::string)"Out of memory in XML-Loading: ", 1);
00533             }
00534             // i+1, predicates in xpath start with 1
00535             picStruct->filename = strdup(xmlSupport.getString((std::string)"/ANIMATION/IMAGE_DATA["+itoa(i+1,tmp,10)+"]/PICTURE").c_str());
00536             picStruct->animationRate = xmlSupport.getInt((std::string)"/ANIMATION/IMAGE_DATA["+itoa(i+1,tmp,10)+"]/ANIMATION_RATE");
00537             picStruct->moveX = xmlSupport.getInt((std::string)"/ANIMATION/IMAGE_DATA["+itoa(i+1,tmp,10)+"]/MOVE_X");
00538             picStruct->moveY = xmlSupport.getInt((std::string)"/ANIMATION/IMAGE_DATA["+itoa(i+1,tmp,10)+"]/MOVE_Y");
00539             pictures->push_back(picStruct);
00540         }
00541     }
00542     catch(...)
00543     {
00544         LOG_EXIT
00545         SDLMain::shutdown((std::string)"XML error \"" + filename + "\": " + xmlSupport.getErrorMessage().c_str(), 1);
00546     }
00547     LOG_EXIT
00548 }
00549 
00550 /////////////////////////////////////////////////////////
00551 void CSAnimation::scale(int width, int tilesX, int height, int tilesY)
00552 {
00553     static char *functionName="scale";
00554     LOG_ENTER 
00555     for (CSPictures::iterator iter = mPictures->begin(); iter != mPictures->end(); iter++)
00556     {
00557         CSPicture *pic = *iter;
00558         pic->scale(width, tilesX, height, tilesY);;
00559     }
00560     LOG_EXIT
00561 }

Generated on Wed Jul 14 00:43:28 2004 for CSLib by doxygen 1.3.6