1 /* FloboPuyo
2 * Copyright (C) 2004
3 * Florent Boudet <flobo@ios-software.com>,
4 * Jean-Christophe Hoelt <jeko@ios-software.com>,
5 * Guillaume Borios <gyom@ios-software.com>
6 *
7 * iOS Software <http://www.ios-software.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 *
24 */
25
26 #include "PuyoAnimations.h"
27 #include "AnimatedPuyo.h"
28 #include "PuyoView.h"
29 #include "IosImgProcess.h"
30 #include "SDL_Painter.h"
31 #include "audio.h"
32
33 /* not clean, but basta */
34 extern SDL_Painter painter;
35 extern IIM_Surface *puyoEyes;
36 extern IIM_Surface *puyoEye[3];
37 extern IIM_Surface *puyoEyesSwirl[4];
38 extern IIM_Surface *shrinkingPuyo[5][5];
39 extern IIM_Surface *explodingPuyo[5][5];
40
41 /* Base class implementation */
Animation()42 Animation::Animation()
43 {
44 finishedFlag = false;
45 enabled = true;
46 }
47
isFinished() const48 bool Animation::isFinished() const
49 {
50 return finishedFlag;
51 }
52
isEnabled() const53 bool Animation::isEnabled() const
54 {
55 return enabled;
56 }
57
58
59 /* Neutral falling animation */
60 IIM_Surface *NeutralAnimation::neutral = NULL;
NeutralAnimation(AnimatedPuyo & puyo,int delay)61 NeutralAnimation::NeutralAnimation(AnimatedPuyo &puyo, int delay) : PuyoAnimation(puyo)
62 {
63 if (neutral == NULL)
64 neutral = PuyoView::getSurfaceForState(PUYO_NEUTRAL);
65 this->X = attachedPuyo.getScreenCoordinateX();
66 this->Y = attachedPuyo.getScreenCoordinateY();
67 this->currentY = attachedPuyo.getAttachedView()->getScreenCoordinateY(0);
68 step = 0;
69 this->delay = delay;
70 attachedPuyo.getAttachedView()->disallowCycle();
71 }
72
cycle()73 void NeutralAnimation::cycle()
74 {
75 if (delay >=0) {
76 delay--;
77 }
78 else {
79 currentY += (int)step;
80 step += 0.5;
81 if (currentY >= Y) {
82 audio_sound_play(sound_bim[random() % 2]);
83 finishedFlag = true;
84 attachedPuyo.getAttachedView()->allowCycle();
85 }
86 }
87 }
88
draw(int semiMove)89 void NeutralAnimation::draw(int semiMove)
90 {
91 SDL_Rect drect;
92 drect.x = X;
93 drect.y = currentY;
94 drect.w = neutral->w;
95 drect.h = neutral->h;
96 painter.requestDraw(neutral, &drect);
97 }
98
99 /* Animation synchronization helper */
AnimationSynchronizer()100 AnimationSynchronizer::AnimationSynchronizer()
101 {
102 currentCounter = 0;
103 currentUsage = 0;
104 }
105
push()106 void AnimationSynchronizer::push()
107 {
108 currentCounter++;
109 }
110
pop()111 void AnimationSynchronizer::pop()
112 {
113 currentCounter--;
114 }
115
isSynchronized()116 bool AnimationSynchronizer::isSynchronized()
117 {
118 return (currentCounter <= 0);
119 }
120
incrementUsage()121 void AnimationSynchronizer::incrementUsage()
122 {
123 currentUsage++;
124 }
125
decrementUsage()126 void AnimationSynchronizer::decrementUsage()
127 {
128 currentUsage--;
129 if (currentUsage == 0)
130 delete this;
131 }
132
133 /* Companion turning around main puyo animation */
TurningAnimation(AnimatedPuyo & companionPuyo,int vector,bool counterclockwise)134 TurningAnimation::TurningAnimation(AnimatedPuyo &companionPuyo, int vector,
135 bool counterclockwise) : PuyoAnimation(companionPuyo)
136 {
137 this->counterclockwise = counterclockwise;
138 companionVector = vector;
139 targetSurface = attachedPuyo.getAttachedView()->getSurfaceForPuyo(&attachedPuyo);
140 cpt = 0;
141 angle = 0;
142 step = (3.14 / 2) / 4;
143 }
144
cycle()145 void TurningAnimation::cycle()
146 {
147 if (cpt == 0) {
148 audio_sound_play(sound_fff);
149 }
150 cpt++;
151 angle += step;
152 if (cpt == 4)
153 finishedFlag = true;
154 }
155
draw(int semiMove)156 void TurningAnimation::draw(int semiMove)
157 {
158 if (targetSurface == NULL)
159 return;
160 X = attachedPuyo.getScreenCoordinateX();
161 Y = attachedPuyo.getScreenCoordinateY();
162
163 float offsetA = sin(angle) * TSIZE;
164 float offsetB = cos(angle) * TSIZE * (counterclockwise ? -1 : 1);
165 SDL_Rect drect, drect2;
166 drect.w = targetSurface->w;
167 drect.h = targetSurface->h;
168 drect.y = -semiMove * TSIZE / 2;
169 switch (companionVector) {
170 case 0:
171 drect.x = (short)(X - offsetB);
172 drect.y += (short)(Y + offsetA - TSIZE);
173 break;
174 case 1:
175 drect.x = (short)(X - offsetA + TSIZE);
176 drect.y += (short)(Y - offsetB);
177 break;
178 case 2:
179 drect.x = (short)(X + offsetB);
180 drect.y += (short)(Y - offsetA + TSIZE);
181 break;
182 case 3:
183 drect.x = (short)(X + offsetA - TSIZE);
184 drect.y += (short)(Y + offsetB);
185 break;
186
187 case -3:
188 drect.x = (short)(X + offsetB);
189 drect.y += (short)(Y + offsetA - TSIZE);
190 break;
191 }
192 drect2 = drect;
193 painter.requestDraw(targetSurface, &drect);
194 painter.requestDraw(puyoEyes, &drect2);
195 }
196
197 /* Puyo falling and bouncing animation */
198
199 const int FallingAnimation::BOUNCING_OFFSET_NUM = 12;
200 const int FallingAnimation::BOUNCING_OFFSET[] = { -1, -3, -5, -4, -2, 0, -6, -9, -11, -9, -6, 0 };
201
FallingAnimation(AnimatedPuyo & puyo,int originY,int xOffset,int yOffset,int step)202 FallingAnimation::FallingAnimation(AnimatedPuyo &puyo, int originY, int xOffset, int yOffset, int step) : PuyoAnimation(puyo)
203 {
204 this->xOffset = xOffset;
205 this->yOffset = yOffset;
206 this->step = 0/*step*/;
207 this->X = (attachedPuyo.getPuyoX()*TSIZE) + xOffset;
208 this->Y = (originY*TSIZE) + yOffset;
209 puyoFace = PuyoView::getSurfaceForState(attachedPuyo.getPuyoState());
210 bouncing = BOUNCING_OFFSET_NUM - 1;
211 if (originY == attachedPuyo.getPuyoY()) {
212 bouncing = -1;
213 }
214 attachedPuyo.getAttachedView()->disallowCycle();
215 }
216
cycle()217 void FallingAnimation::cycle()
218 {
219 Y += step++;
220 if (Y >= (attachedPuyo.getPuyoY()*TSIZE) + yOffset)
221 {
222 bouncing--;
223 if (bouncing < 0) {
224 finishedFlag = true;
225 audio_sound_play(sound_bam1);
226 attachedPuyo.getAttachedView()->allowCycle();
227 }
228 else {
229 if (BOUNCING_OFFSET[bouncing] == 0)
230 audio_sound_play(sound_bam1);
231 }
232 Y = (attachedPuyo.getPuyoY()*TSIZE) + yOffset;
233 }
234 }
235
draw(int semiMove)236 void FallingAnimation::draw(int semiMove)
237 {
238 if (puyoFace) {
239 SDL_Rect drect;
240 drect.x = X;
241 drect.y = Y + (bouncing>=0?BOUNCING_OFFSET[bouncing]:0);
242 // drect.y = -semiMove() * TSIZE / 2;
243 drect.w = puyoFace->w;
244 drect.h = puyoFace->h;
245 painter.requestDraw(puyoFace, &drect);
246 if (attachedPuyo.getPuyoState() != PUYO_NEUTRAL)
247 painter.requestDraw(puyoEyesSwirl[(bouncing/2)%4], &drect);
248 }
249 }
250
251 /* Puyo exploding and vanishing animation */
VanishAnimation(AnimatedPuyo & puyo,int delay,int xOffset,int yOffset,AnimationSynchronizer * synchronizer)252 VanishAnimation::VanishAnimation(AnimatedPuyo &puyo, int delay, int xOffset, int yOffset, AnimationSynchronizer *synchronizer) : PuyoAnimation(puyo)
253 {
254 puyoFace = PuyoView::getSurfaceForState(attachedPuyo.getPuyoState());
255 this->xOffset = xOffset;
256 this->yOffset = yOffset;
257 this->X = (attachedPuyo.getPuyoX()*TSIZE) + xOffset;
258 this->Y = (attachedPuyo.getPuyoY()*TSIZE) + yOffset;
259 this->color = attachedPuyo.getPuyoState();
260 if (color > PUYO_EMPTY)
261 color -= PUYO_BLUE;
262 iter = 0;
263 once = false;
264 enabled = false;
265 this->synchronizer = synchronizer;
266 synchronizer->incrementUsage();
267 synchronizer->push();
268 this->delay = delay;
269 attachedPuyo.getAttachedView()->disallowCycle();
270 }
271
~VanishAnimation()272 VanishAnimation::~VanishAnimation()
273 {
274 synchronizer->decrementUsage();
275 }
276
cycle()277 void VanishAnimation::cycle()
278 {
279 if (once == false) {
280 once = true;
281 synchronizer->pop();
282 }
283 else if (synchronizer->isSynchronized()) {
284 enabled = true;
285 iter ++;
286 if (iter == 20 + delay) {
287 attachedPuyo.getAttachedView()->allowCycle();
288 }
289 else if (iter == 50 + delay) {
290 finishedFlag = true;
291 attachedPuyo.setVisible(false);
292 }
293 }
294 }
295
draw(int semiMove)296 void VanishAnimation::draw(int semiMove)
297 {
298 if (iter < (10 + delay)) {
299 if (puyoFace && (iter % 2 == 0)) {
300 SDL_Rect drect;
301 drect.x = X;
302 drect.y = Y;
303 drect.w = puyoFace->w;
304 drect.h = puyoFace->h;
305 painter.requestDraw(puyoFace, &drect);
306 if (color != PUYO_NEUTRAL)
307 painter.requestDraw(puyoEyes, &drect);
308 }
309 }
310 else {
311 if (puyoFace) {
312 SDL_Rect drect, xrect;
313 drect.x = X;
314 drect.y = Y;// + (2.5 * pow(iter - 16, 2) - 108);
315 drect.w = puyoFace->w;
316 drect.h = puyoFace->h;
317 int iter2 = iter - 10 - delay;
318 int shrinkingImage = (iter - 10 - delay) / 4;
319 if (shrinkingImage < 4) {
320 painter.requestDraw(shrinkingPuyo[shrinkingImage][color], &drect);
321 int xrectY = Y + (int)(2.5 * pow(iter - 16 - delay, 2) - 108);
322 xrect.w = explodingPuyo[shrinkingImage][color]->w;
323 xrect.h = explodingPuyo[shrinkingImage][color]->h;
324 xrect.x = X - iter2 * iter2;
325 xrect.y = xrectY;
326 painter.requestDraw(explodingPuyo[shrinkingImage][color], &xrect);
327 xrect.x = X - iter2;
328 xrect.y = xrectY + iter2;
329 painter.requestDraw(explodingPuyo[shrinkingImage][color], &xrect);
330 xrect.x = X + iter2;
331 xrect.y = xrectY + iter2;
332 painter.requestDraw(explodingPuyo[shrinkingImage][color], &xrect);
333 xrect.x = X + iter2 * iter2;
334 xrect.y = xrectY;
335 painter.requestDraw(explodingPuyo[shrinkingImage][color], &xrect);
336 }
337 }
338 }
339 }
340
VanishSoundAnimation(int phase,AnimationSynchronizer * synchronizer)341 VanishSoundAnimation::VanishSoundAnimation(int phase, AnimationSynchronizer *synchronizer)
342 {
343 once = false;
344 step = 0;
345 this->phase = phase;
346 this->synchronizer = synchronizer;
347 synchronizer->incrementUsage();
348 synchronizer->push();
349 }
350
~VanishSoundAnimation()351 VanishSoundAnimation::~VanishSoundAnimation()
352 {
353 synchronizer->decrementUsage();
354 }
355
cycle()356 void VanishSoundAnimation::cycle()
357 {
358 if (once == false) {
359 once = true;
360 synchronizer->pop();
361 }
362 else if (synchronizer->isSynchronized()) {
363 step++;
364 if (step == 1) {
365 audio_sound_play(sound_splash[phase>7?7:phase]);
366 finishedFlag = true;
367 }
368 }
369 }
370
draw(int semiMove)371 void VanishSoundAnimation::draw(int semiMove)
372 {
373 // do nothing
374 }
375