00001 #ifndef CSAnimation_h 00002 #define CSAnimation_h 00003 00004 // USES SDL_Surface 00005 00006 #include <string> 00007 #include <vector> 00008 #include "CSTypes.h" 00009 #include "SDLMain.h" 00010 #include "CSPicture.h" 00011 #include "CSLoadable.h" 00012 #include "CSLog.h" 00013 00014 class CSAnimation; 00015 class CSAnimationLoader; 00016 class CSAnimationPicture; 00017 00018 typedef std::vector<CSAnimationPicture *> CSAnimationPictures; 00019 typedef std::vector<CSAnimation *> CSAnimations; 00020 00021 static const int CS_NOT_REPEATABLE = 0; 00022 static const int CS_REPEATABLE = 1; 00023 static const int CS_INVERSE_ONCE = 2; 00024 static const int CS_INVERSE_REPEATABLE = 3; 00025 static const int CS_RANDOM = 4; //!< (not implemented) 00026 static const int ANIMATION_SPEED = 65536; 00027 static const int ADJUST_SPEED = 65535; 00028 00029 00030 //! class to define a single animated picture-frame, data wise -> see below 00031 class CSAnimationPicture 00032 { 00033 public: 00034 char *filename; //!< defining picture filename! 00035 int animationRate; //!< delay for one update of the animation (per picture) 00036 signed int moveX; //!< delta X to move (after delay) (per picture) 00037 signed int moveY; //!< delta Y to move (after delay) (per picture) 00038 CSAnimationPicture() 00039 { 00040 filename = 0; 00041 } 00042 ~CSAnimationPicture() 00043 { 00044 if (filename != 0) 00045 { 00046 free(filename); 00047 filename = 0; 00048 } 00049 } 00050 }; 00051 00052 //! data classes are used for loading a loadable class 00053 //! first the data is loaded via xml into this "DATA"-class 00054 //! from this data - the actual animation is created 00055 //! the data can be reused to create another instance of a 00056 //! animation class - though probably not needed... 00057 class CSAnimationData 00058 { 00059 public: 00060 char *id; //!< defining picture filename! 00061 bool isBreakable; //!< cann animation be stopped while 00062 //!< in between 00063 unsigned int repeatable; //!< see above definition 00064 unsigned int sizePhases; //!< how many phases? 00065 unsigned int *phases; //!< arrayPointer # sizePhases 00066 CSAnimationPictures *pictures; //!< above data for animation pictures 00067 00068 CSAnimationData() 00069 { 00070 phases = 0; 00071 id = 0; 00072 pictures = 0; 00073 } 00074 00075 ~CSAnimationData() 00076 { 00077 if (id != 0) 00078 { 00079 free (id); 00080 id = 0; 00081 } 00082 if (pictures != 0) 00083 { 00084 CSAnimationPictures::iterator iter = pictures->begin(); 00085 00086 while (iter != pictures->end()) 00087 { 00088 CSAnimationPicture *pic = *iter; 00089 delete pic; 00090 iter++; 00091 } 00092 delete pictures; 00093 pictures = 0; 00094 } 00095 if (phases != 0) 00096 { 00097 delete []phases; 00098 phases = 0; 00099 } 00100 } 00101 00102 }; 00103 00104 /** a phase is a sequence of pictures. Same pictures can occur at different stages 00105 during an animation. 00106 Example: 00107 pictures a1, a2, a3, a4 (pictures actually belonging to animation 00108 phases a1, a2, a1, a2, a3, a1, a2, a3, a4 00109 The phases defines "sequences" of pictures during one animation. 00110 00111 the states hold all variable parts needed for printing the animation on screen 00112 putting these in a state class, enables us to 00113 reuse the memory expensive animation class! 00114 */ 00115 class AnimationState 00116 { 00117 public: 00118 float mXPos; //!< current x position on screen 00119 float mYPos; //!< current y position on screen 00120 int mSpeedX; //!< current x speed, pixels per frame 00121 int mSpeedY; //!< current y speed, pixels per frame 00122 unsigned int mAdjustSpeed; 00123 float mAnimationRateCounter; //!< "speed" of anaimtion 00124 signed int mCurrentPhase; //!< current "active" phaseNo 00125 unsigned int mCurrentPicture; //!< current active pictureNo, corresponse to 00126 //!< picture selected by active phase 00127 bool mForward; //!< in animation sequence going ++ or -- 00128 bool mFinished; //!< if a NOT_REPEATABLE animation, 00129 CSPicture *mPicture; //!< currenct active CSPicture, corresponse to 00130 //!< picture selected by active phase 00131 //!< this need not be the picture to be displayed 00132 //!< this round, since update and display 00133 //!< are two different methods 00134 //!< the mDisplayPicture will be set during 00135 //!< update to display the picture that belongs to 00136 //!< the "current" frame 00137 //!< at the end of the update method the 00138 //!< the current picture of the state 00139 //!< can differ, because the update can 00140 //!< sets the picture to the NEXT picture 00141 //!< (animation counter reaches 0, next frame 00142 //!< will be selected, but the old frame 00143 //!< should still be displayed) 00144 //!< !NOT TO BE FREED! 00145 CSPicture *mDisplayPicture; //!< picture that will be displayed when calling display() 00146 //!< !NOT TO BE FREED! 00147 CSDisplayParams mDisplayParams; //!< position on screen and in world of the current mDisplaypicture 00148 00149 AnimationState() 00150 { 00151 mXPos = 0; 00152 mYPos = 0; 00153 mSpeedX = ANIMATION_SPEED; 00154 mSpeedY = ANIMATION_SPEED; 00155 mAdjustSpeed = 0; 00156 mAnimationRateCounter = 0; 00157 mCurrentPhase = 0; 00158 mCurrentPicture = 0; 00159 mForward = true; 00160 mFinished = false; 00161 mPicture = 0; 00162 mDisplayPicture = 0; 00163 00164 mDisplayParams.mXDisplayStart = 0; 00165 mDisplayParams.mYDisplayStart = 0; 00166 mDisplayParams.mXWorldStart = 0; 00167 mDisplayParams.mYWorldStart = 0; 00168 mDisplayParams.mXPos = 0; 00169 mDisplayParams.mYPos = 0; 00170 } 00171 virtual ~AnimationState() {} 00172 }; 00173 00174 /*! 00175 CSAnimation 00176 CSAnimation can only be created thru a loader (CSAnimationLoader). 00177 CSAnimation are defined by (now ONLY thru) an xml-File, like: 00178 DTD: 00179 \verbatim 00180 00181 <!ENTITY % types SYSTEM "types.dtd"> %types; 00182 00183 <!ELEMENT ANIMATION (ID,IS_BREAKABLE,REPEATABLE,(PHASE)+,(IMAGE_DATA)+)> 00184 <!ELEMENT ID (#PCDATA)> 00185 <!ELEMENT IS_BREAKABLE (#PCDATA)> 00186 <!ELEMENT REPEATABLE (#PCDATA)> 00187 <!ELEMENT PHASE (#PCDATA)> 00188 <!ELEMENT IMAGE_DATA (PICTURE,ANIMATION_RATE,MOVE_X,MOVE_Y)> 00189 <!ELEMENT PICTURE (#PCDATA)> 00190 <!ELEMENT ANIMATION_RATE (#PCDATA)> 00191 <!ELEMENT MOVE_X (#PCDATA)> 00192 <!ELEMENT MOVE_Y (#PCDATA)> 00193 \endverbatim 00194 00195 Example: 00196 \verbatim 00197 <ANIMATION> 00198 <ID>PAC_DOWN</ID> 00199 <IS_BREAKABLE>&true;</IS_BREAKABLE> 00200 <REPEATABLE>&INVERSE_ONCE;</REPEATABLE> 00201 <PHASE>0</PHASE> 00202 <PHASE>1</PHASE> 00203 <PHASE>2</PHASE> 00204 <PHASE>3</PHASE> 00205 <PHASE>4</PHASE> 00206 <IMAGE_DATA> 00207 <PICTURE>picture\\pac_down1.xml</PICTURE> 00208 <ANIMATION_RATE>&A_RATE;</ANIMATION_RATE> 00209 <MOVE_X>0</MOVE_X> 00210 <MOVE_Y>&SPEED;</MOVE_Y> 00211 </IMAGE_DATA> 00212 <IMAGE_DATA> 00213 <PICTURE>picture\\pac_down2.xml</PICTURE> 00214 <ANIMATION_RATE>&A_RATE;</ANIMATION_RATE> 00215 <MOVE_X>0</MOVE_X> 00216 <MOVE_Y>&SPEED;</MOVE_Y> 00217 </IMAGE_DATA> 00218 ... 00219 </ANIMATION> 00220 \endverbatim 00221 <PRE> 00222 ID - supposed a unique identifier 00223 IS_BREAKABLE - if an animation can be interrupted by some action 00224 REAPEATABLE - one of: 00225 CS_NOT_REPEATABLE = 0; 00226 CS_REPEATABLE = 1; 00227 CS_INVERSE_ONCE = 2; 00228 CS_INVERSE_REPEATABLE = 3; 00229 CS_RANDOM = 4; // (not implemented) 00230 00231 PHASES - many phases, each phase is represented by a number 00232 the number corresponse to the IMAGE_DATA that is 00233 loaded with the ini - file (numbered from top to 00234 bottom. 00235 NOTE: 00236 REAPEATABLE CS_INVERSE_ONCE 00237 PHASES 0 00238 PHASES 1 00239 PHASES 2 00240 PHASES 3 00241 PHASES 4 00242 00243 gives the same result as: 00244 REAPEATABLE CS_NOT_REPEATABLE 00245 PHASES 0 00246 PHASES 1 00247 PHASES 2 00248 PHASES 3 00249 PHASES 4 00250 PHASES 3 00251 PHASES 2 00252 PHASES 1 00253 PHASES 0 00254 00255 if an animation has only one image, it is not really 00256 much of an aniamtion -> 00257 thus an aniamtion with only one picture never uses aniamtion rate, 00258 and never uses the repeatable flag 00259 IMAGE_DATA - many image_data's are possible 00260 describes the image to be loaded, 00261 PICTURE parameter gives the ini-file for a CSPicture, 00262 ANIMATION_RATE parameter gives the delay between two animation phases 00263 negative animation rates are not in animtions per second 00264 but aniamtion each # of seconds! 00265 MOVE_X parameter gives the value (speed) with which the 00266 the x-coordinates wil be updated (negative and positive) pixels per second 00267 MOVE_Y parameter gives the value (speed) with which the 00268 the y-coordinates wil be updated (negative and positive) pixels per second 00269 00270 CSAnimation are singletons in the sense, that two "loaded" CSAnimations of 00271 the same "ini" file ARE the same instances. 00272 00273 </PRE> 00274 the animation class has no instance relevant data (state independant) 00275 thus one instance can be reused 00276 - one aniamtion can be (re) used severall times 00277 the data used for printing must come from the outside (AnimationState) 00278 */ 00279 class CSAnimation 00280 { 00281 friend CSAnimationLoader; 00282 private: 00283 bool mIsBreakable; //!< can animation be interrupted? 00284 //!< by events 00285 unsigned int mRepeatable; //!< above const definitions 00286 unsigned int mSizePictures; //!< how many pictures 00287 unsigned int mSizePhases; //!< how many phases 00288 float *mAnimationRates; //!< arrayPointer # mSizePictures 00289 unsigned int *mPhases; //!< arrayPointer # mSizePhases 00290 signed int *mMoveX; //!< arrayPointer # mSizePictures 00291 signed int *mMoveY; //!< arrayPointer # mSizePictures 00292 00293 CSPictures *mPictures; //!< all pictures in a vector (stl) 00294 00295 bool mMoveAllowed; //!< may at some stage be forbidden 00296 //!< from outside (hits a wall...) 00297 //!< this is false upon "one round" 00298 bool mIsSolid; //!< has transparent pixels 00299 float mSecsPerFrame; //!< set from outside, to provide speed independent movement 00300 00301 //! constructor using "*.xml" file 00302 CSAnimation(const std::string &filename); 00303 static void loadAnimationData(const std::string &filename, CSAnimationData &data); 00304 00305 virtual void initialize(const CSAnimationData &data); 00306 virtual void initialize(); 00307 00308 public: 00309 static const char *CLASS; 00310 virtual std::string getType() {return (std::string) CLASS;} 00311 00312 CSAnimation(const CSAnimation &animation); 00313 virtual ~CSAnimation(); 00314 00315 unsigned int getMaxX(); 00316 unsigned int getMaxY(); 00317 void setSolid(bool b); 00318 void scale(int width, int tilesX, int height, int tilesY); 00319 00320 AnimationState buildState(); 00321 void resetState(AnimationState& state); 00322 void startAnimation(AnimationState& state); 00323 void startNextAnimation(AnimationState& state); //!< comment 00324 bool next(AnimationState& state); //!< if finished and not repeat -> false, true otherwise 00325 void display(AnimationState& state); 00326 void setAlpha(int alpha); 00327 SDL_Surface *getScaledAnimation(AnimationState &mAnimationState, double factor) 00328 { 00329 //! \todo: do all animation states beforehand 00330 return mAnimationState.mPicture->getScaledPicture(factor); 00331 } 00332 00333 00334 bool isSolid() {return mIsSolid;} 00335 bool isBreakable() {return mIsBreakable;} 00336 void setSecPerFrame(float secPerFrame); 00337 void setSpeedX(int speed, AnimationState& state) {state.mSpeedX = speed;} 00338 void setSpeedY(int speed, AnimationState& state) {state.mSpeedY = speed;} 00339 void adjustSpeed(int speed, AnimationState& state) 00340 {state.mSpeedX = state.mSpeedY = ADJUST_SPEED;state.mAdjustSpeed = speed;} 00341 void resetSpeed(AnimationState& state) {state.mSpeedX = state.mSpeedY = ANIMATION_SPEED;} 00342 }; 00343 00344 //! factory - class 00345 //! that is used to create CSAniamtion 00346 //! uses xml - data-files, produces "singletons" 00347 class CSAnimationLoader : public Loadable<CSAnimation> 00348 { 00349 protected: 00350 virtual CSAnimation *create(const std::string &filename) 00351 { 00352 return new CSAnimation(filename); 00353 } 00354 00355 public: 00356 static CSAnimationLoader INSTANCE; 00357 }; 00358 00359 #endif // CSAnimation_h 00360