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
00048
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
00095
00096
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
00113 CSPicture *pic = CSPictureLoader::INSTANCE.load((*iter)->filename);
00114
00115 mPictures->push_back(pic);
00116 mAnimationRates[i] = (*iter)->animationRate;
00117
00118
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
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
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
00215
00216
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
00233
00234
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
00250
00251
00252
00253
00254
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
00267
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
00282
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
00297
00298 bool CSAnimation::next(AnimationState& state)
00299 {
00300 static char *functionName="next";
00301 if (state.mFinished)
00302 {
00303 return !state.mFinished;
00304 }
00305
00306
00307
00308
00309
00310 if (mSizePictures <= 1)
00311 {
00312 if (mMoveAllowed)
00313 {
00314
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
00359 state.mAnimationRateCounter += (float) (mAnimationRates[state.mCurrentPicture] * mSecsPerFrame);
00360
00361 if (state.mAnimationRateCounter >= 1)
00362 {
00363 state.mAnimationRateCounter = 0;
00364 if (mRepeatable == CS_RANDOM)
00365 {
00366
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
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 }
00440 state.mCurrentPicture = mPhases[state.mCurrentPhase];
00441 state.mPicture = mPictures->at(state.mCurrentPicture);
00442 }
00443
00444 if (mMoveAllowed)
00445 {
00446
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
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
00521 data.phases[i] = xmlSupport.getInt((std::string)"/ANIMATION/PHASE["+itoa(i+1,tmp,10)+"]");
00522 }
00523 CSAnimationPictures *pictures = new CSAnimationPictures();
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
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 }