00001 /****************************************************************************** 00002 * Wormux is a convivial mass murder game. 00003 * Copyright (C) 2001-2004 Lawrence Azzoug. 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 00018 ****************************************************************************** 00019 * Sprite animation control. 00020 ****************************************************************************** 00021 * 2005/09/21: Jean-Christophe Duberga (jcduberga@gmx.de) 00022 * Initial version 00023 *****************************************************************************/ 00024 00025 #include "spriteanimation.h" 00026 #include "../game/time.h" 00027 #include "sprite.h" 00028 00029 SpriteAnimation::SpriteAnimation(Sprite &p_sprite) : 00030 sprite(p_sprite) 00031 { 00032 last_update = Time::GetInstance()->Read(); 00033 speed_factor = 1.0f; 00034 frame_delta = 1; 00035 finished = false; 00036 show_on_finish = show_last_frame; 00037 loop = true; 00038 pingpong = false; 00039 } 00040 00041 SpriteAnimation::SpriteAnimation(const SpriteAnimation &other, Sprite &p_sprite) : 00042 sprite(p_sprite) 00043 { 00044 last_update = other.last_update; 00045 speed_factor = other.speed_factor; 00046 frame_delta = other.frame_delta; 00047 finished = other.finished; 00048 show_on_finish = other.show_on_finish; 00049 loop = other.loop; 00050 pingpong = other.pingpong; 00051 } 00052 00053 void SpriteAnimation::SetSpeedFactor( float nv_speed){ 00054 speed_factor = nv_speed; 00055 } 00056 00057 void SpriteAnimation::Start(){ 00058 finished = false; 00059 last_update = Time::GetInstance()->Read(); 00060 } 00061 00062 void SpriteAnimation::SetPlayBackward(bool enable){ 00063 if (enable) 00064 frame_delta = -1; 00065 else 00066 frame_delta = 1; 00067 } 00068 00069 void SpriteAnimation::Finish() { 00070 finished = true; 00071 } 00072 00073 void SpriteAnimation::Update(){ 00074 if (finished) return; 00075 00076 Time * global_time = Time::GetInstance(); 00077 if (global_time->Read() < (last_update + sprite.GetCurrentFrameObject().delay)) 00078 return; 00079 const unsigned int current_frame = sprite.GetCurrentFrame(); 00080 const unsigned int frame_count = sprite.GetFrameCount(); 00081 00082 //Delta to next frame used to enable frameskip 00083 //if delay between 2 frame is < fps 00084 int delta_to_next_f = (int)((float)((global_time->Read() - last_update) / sprite.GetCurrentFrameObject().delay) * speed_factor); 00085 last_update += (int)((float)(delta_to_next_f * sprite.GetCurrentFrameObject().delay) / speed_factor); 00086 00087 //Animation is finished, when last frame have been fully played 00088 bool finish; 00089 if (frame_delta < 0) 00090 finish = ((int)current_frame + frame_delta * delta_to_next_f) <= -1; 00091 else 00092 finish = frame_count <= (current_frame + frame_delta * delta_to_next_f); 00093 00094 if (finish && !loop && (!pingpong || frame_delta < 0)) 00095 Finish(); 00096 else 00097 { 00098 unsigned int next_frame = ( current_frame + frame_delta * delta_to_next_f ) % frame_count; 00099 00100 if(pingpong) 00101 { 00102 if( frame_delta>0 && ( current_frame + frame_delta * delta_to_next_f ) >= frame_count) 00103 { 00104 next_frame = frame_count - next_frame -2; 00105 frame_delta = - frame_delta; 00106 } 00107 else 00108 if( frame_delta<0 && ( (int)current_frame + frame_delta * delta_to_next_f ) <= -1) 00109 { 00110 next_frame = (-((int)current_frame + frame_delta * delta_to_next_f )) % frame_count; 00111 frame_delta = - frame_delta; 00112 } 00113 } 00114 00115 if(next_frame != current_frame) 00116 { 00117 if(next_frame >= frame_count) 00118 next_frame = 0; 00119 sprite.SetCurrentFrame(next_frame); 00120 } 00121 } 00122 } 00123 00124 void SpriteAnimation::SetShowOnFinish(SpriteShowOnFinish show) { 00125 show_on_finish = show; 00126 loop = false; 00127 } 00128 00129 bool SpriteAnimation::IsFinished() const { 00130 return finished; 00131 } 00132 00133 void SpriteAnimation::SetLoopMode(bool enable) { 00134 loop = enable; 00135 } 00136 00137 void SpriteAnimation::SetPingPongMode(bool enable) { 00138 pingpong = enable; 00139 } 00140 00141 SpriteAnimation::SpriteShowOnFinish SpriteAnimation::GetShowOnFinish() const { 00142 return show_on_finish; 00143 } 00144