1 #include "Animation.h" 2 3 #include <cmath> 4 5 namespace love_opengl 6 { Animation(pImage image)7 Animation::Animation(pImage image) : image(image), mode(1), current(0), playing(true), 8 timeBuffer(0), direction(1), speed(1.0f) 9 { 10 } 11 Animation(pImage image,float fw,float fh,float delay,int num)12 Animation::Animation(pImage image, float fw, float fh, float delay, int num) : 13 image(image), mode(1), current(0), playing(true), timeBuffer(0), direction(1), speed(1.0f) 14 { 15 // Generate frames. 16 int w = (int)(image->getWidth()/fw); 17 int h = (int)(image->getHeight()/fh); 18 19 int real_num = (num == 0) ? (w * h) : num; 20 if(real_num > (w * h)) real_num = (w * h); 21 22 for(int i = 0;i<real_num;i++) 23 { 24 int x = (int)((i % w)*fw); 25 int y = (int)((i/w)*fh); 26 27 addFrame((float)x, (float)y, fw, fh, delay); 28 } 29 } 30 ~Animation()31 Animation::~Animation() 32 { 33 } 34 addFrame(float x,float y,float w,float h,float delay)35 void Animation::addFrame(float x, float y, float w, float h, float delay) 36 { 37 // Add delay. 38 delays.push_back(delay); 39 40 // Add frame. 41 frame f; 42 f.x = x; f.y = y; 43 f.width = w; 44 f.height = h; 45 f.post_delay = (int)delays.size() - 1; 46 47 float xTex = x/(float)image->getTextureWidth(); 48 float yTex = y/(float)image->getTextureHeight(); 49 50 float wTex = w/(float)image->getTextureWidth(); 51 float hTex = h/(float)image->getTextureHeight(); 52 53 f.vertices[0] = 0; f.vertices[1] = 0; 54 f.vertices[2] = 0; f.vertices[3] = floor(h); 55 f.vertices[4] = floor(w); f.vertices[5] = floor(h); 56 f.vertices[6] = floor(w); f.vertices[7] = 0; 57 58 f.texels[0] = xTex; f.texels[1] = yTex; 59 f.texels[2] = xTex; f.texels[3] = yTex+hTex; 60 f.texels[4] = xTex+wTex; f.texels[5] = yTex+hTex; 61 f.texels[6] = xTex+wTex; f.texels[7] = yTex; 62 63 frames.push_back(f); 64 65 if(frames.size() > 1) 66 { 67 frames.back().pre_delay = frames[frames.size() - 2].post_delay; 68 69 // Update delay of first frame. 70 frames.front().pre_delay = frames.back().post_delay; 71 } 72 73 } 74 setMode(int mode)75 void Animation::setMode(int mode) 76 { 77 this->mode = mode; 78 } 79 play()80 void Animation::play() 81 { 82 playing = true; 83 } 84 stop()85 void Animation::stop() 86 { 87 playing = false; 88 } 89 reset()90 void Animation::reset() 91 { 92 current = 0; 93 timeBuffer = 0; 94 } 95 seek(int frame)96 void Animation::seek(int frame) 97 { 98 if(frame >= 0 && frame < (int)frames.size()) 99 current = frame; 100 } 101 getCurrentFrame() const102 int Animation::getCurrentFrame() const 103 { 104 return current; 105 } 106 getSize() const107 int Animation::getSize() const 108 { 109 return (int)frames.size(); 110 } 111 setDelay(int frame,float delay)112 void Animation::setDelay(int frame, float delay) 113 { 114 if(frame >= 0 && frame < (int)frames.size()) 115 delays[frames[0].post_delay] = delay; 116 } 117 setSpeed(float speed)118 void Animation::setSpeed(float speed) 119 { 120 this->speed = speed; 121 } 122 getSpeed() const123 float Animation::getSpeed() const 124 { 125 return speed; 126 } 127 bind() const128 void Animation::bind() const 129 { 130 image->bind(); 131 } 132 update(float dt)133 void Animation::update(float dt) 134 { 135 if(!playing) 136 return; 137 138 if(frames.size() <= 0) 139 return; 140 141 timeBuffer += (dt * speed); 142 143 int next; 144 float d; 145 146 switch(mode) 147 { 148 case love::ANIMATION_LOOP: 149 next = current; 150 while(timeBuffer >= delays[frames[current].post_delay]) 151 { 152 timeBuffer -= delays[frames[current].post_delay]; 153 if(++next >= (int)frames.size()) 154 next = 0; 155 } 156 current = next; 157 break; 158 case love::ANIMATION_PLAY_ONCE: 159 next = current; 160 while(timeBuffer >= delays[frames[current].post_delay]) 161 { 162 timeBuffer -= delays[frames[current].post_delay]; 163 if(++next >= (int)frames.size()) 164 { 165 next--; 166 playing = false; 167 timeBuffer = 0; 168 } 169 } 170 current = next; 171 break; 172 case love::ANIMATION_BOUNCE: 173 next = current; 174 d = (direction == 1) ? delays[frames[next].post_delay] : delays[frames[next].pre_delay]; 175 176 while(timeBuffer >= d) 177 { 178 timeBuffer -= d; 179 next += direction; 180 if(next < 0 || next >= (int)frames.size()) 181 { 182 direction *= -1; 183 next += direction; 184 } 185 d = (direction == 1) ? delays[frames[next].post_delay] : delays[frames[next].pre_delay]; 186 } 187 current = next; 188 break; 189 } 190 191 // Set the current width/height. 192 this->width = frames[current].width; 193 this->height = frames[current].height; 194 } 195 draw(float x,float y) const196 void Animation::draw(float x, float y) const 197 { 198 if(frames.size() <= 0) 199 return; 200 201 const frame & f = frames[current]; 202 image->draw(f.vertices, f.texels, x, y, 0, 1, 1, -f.width/2.0f + center_x, -f.height/2.0f + center_y, love::FLIP_NONE); 203 } 204 draw(float x,float y,float angle,float sx,float sy,int flip) const205 void Animation::draw(float x, float y, float angle, float sx, float sy, int flip) const 206 { 207 if(frames.size() <= 0) 208 return; 209 210 const frame & f = frames[current]; 211 image->draw(f.vertices, f.texels, x, y, angle, sx, sy, -f.width/2.0f + center_x, -f.height/2.0f + center_y, flip); 212 } 213 } // love_opengl 214