- added UpgradeKind name to nameless enum
[supertux.git] / src / special.cpp
1 //
2 // C Implementation: special
3 //
4 // Description:
5 //
6 //
7 // Author: Tobias Glaesser <tobi.web@gmx.de> & Bill Kendrick, (C) 2004
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12
13 #include <assert.h>
14 #include "SDL.h"
15 #include "defines.h"
16 #include "special.h"
17 #include "gameloop.h"
18 #include "screen.h"
19 #include "sound.h"
20 #include "scene.h"
21 #include "globals.h"
22 #include "player.h"
23 #include "resources.h"
24
25 Surface* img_bullet;
26 Surface* img_golden_herring;
27 Surface* img_growup;
28 Surface* img_iceflower;
29 Surface* img_1up;
30
31 #define GROWUP_SPEED 1.0f
32
33 void
34 Bullet::init(float x, float y, float xm, int dir)
35 {
36   base.width = 4;
37   base.height = 4;
38
39   if (dir == RIGHT)
40     {
41       base.x = x + 32;
42       base.xm = BULLET_XM + xm;
43     }
44   else
45     {
46       base.x = x;
47       base.xm = -BULLET_XM + xm;
48     }
49
50   base.y = y;
51   base.ym = BULLET_STARTING_YM;
52   old_base = base;
53 }
54
55 void
56 Bullet::remove_me()
57 {
58   std::vector<Bullet>& bullets = World::current()->bullets;
59   for(std::vector<Bullet>::iterator i = bullets.begin();
60          i != bullets.end(); ++i) {
61     if( & (*i) == this) {
62       bullets.erase(i);
63       return;
64     }
65   }
66
67   assert(false);
68 }
69
70 void
71 Bullet::action(double frame_ratio)
72 {
73   base.x = base.x + base.xm * frame_ratio;
74   base.y = base.y + base.ym * frame_ratio;
75
76   collision_swept_object_map(&old_base,&base);
77       
78   if (issolid(base.x, base.y + 4) || issolid(base.x, base.y))
79     {
80       base.ym = -base.ym;
81       base.y = (int)(base.y / 32) * 32;
82     }
83
84   base.ym = base.ym + GRAVITY;
85
86   if (base.x < scroll_x ||
87       base.x > scroll_x + screen->w ||
88       base.y < 0 ||
89       base.y > screen->h ||
90       issolid(base.x + 4, base.y + 2) ||
91       issolid(base.x, base.y + 2))
92     {
93       remove_me();
94     }
95
96 }
97
98 void 
99 Bullet::draw()
100 {
101   if (base.x >= scroll_x - base.width &&
102       base.x <= scroll_x + screen->w)
103     {
104       img_bullet->draw( base.x - scroll_x, base.y, 255,
105                    NO_UPDATE);
106     }
107 }
108
109 void
110 Bullet::collision(int c_object)
111 {
112   if(c_object == CO_BADGUY) {
113     remove_me();
114   }
115 }
116
117 void
118 Upgrade::init(float x_, float y_, int dir_, UpgradeKind kind_)
119 {
120   kind = kind_;
121   dir = dir_;
122
123   base.width = 32;
124   base.height = 0;
125   base.x = x_;
126   base.y = y_;
127   old_base = base;
128
129   physic.reset();
130   physic.enable_gravity(false);
131
132   if(kind == UPGRADE_1UP || kind == UPGRADE_HERRING) {
133     physic.set_velocity(dir == LEFT ? -1 : 1, 4);
134     physic.enable_gravity(true);
135     base.height = 32;
136   } else if (kind == UPGRADE_ICEFLOWER) {
137     // nothing
138   } else if (kind == UPGRADE_GROWUP) {
139     physic.set_velocity(dir == LEFT ? -GROWUP_SPEED : GROWUP_SPEED, 0);
140   } else {
141     physic.set_velocity(dir == LEFT ? -2 : 2, 0);
142   }
143 }
144
145 void
146 Upgrade::remove_me()
147 {
148   std::vector<Upgrade>& upgrades = World::current()->upgrades;
149   for(std::vector<Upgrade>::iterator i = upgrades.begin();
150          i != upgrades.end(); ++i) {
151     if( & (*i) == this) {
152       upgrades.erase(i);
153       return;
154     }
155   }
156
157   assert(false);
158 }
159
160 void
161 Upgrade::action(double frame_ratio)
162 {
163   if (kind == UPGRADE_ICEFLOWER || kind == UPGRADE_GROWUP) {
164     if (base.height < 32) {
165       /* Rise up! */
166       base.height = base.height + 0.7 * frame_ratio;
167       if(base.height > 32)
168         base.height = 32;
169
170       return;
171     }
172   }
173
174   /* Off screen? Kill it! */
175   if(base.x < scroll_x - base.width || base.y > screen->h) {
176     remove_me();
177     return;
178   }
179
180   /* Move around? */
181   physic.apply(frame_ratio, base.x, base.y);
182   if(kind == UPGRADE_GROWUP) {
183     collision_swept_object_map(&old_base, &base);
184   }
185
186   // fall down?
187   if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) {
188     // falling?
189     if(physic.get_velocity_y() != 0) {
190       if(issolid(base.x, base.y + base.height)) {
191         base.y = int(base.y / 32) * 32;
192         old_base = base;                         
193         if(kind == UPGRADE_GROWUP) {
194           physic.enable_gravity(false);
195           physic.set_velocity(dir == LEFT ? -GROWUP_SPEED : GROWUP_SPEED, 0);
196         } else if(kind == UPGRADE_HERRING) {
197           physic.set_velocity(dir == LEFT ? -2 : 2, 3);
198         }
199       }
200     } else {
201       if((physic.get_velocity_x() < 0
202             && !issolid(base.x+base.width, base.y + base.height))
203         || (physic.get_velocity_x() > 0
204             && !issolid(base.x, base.y + base.height))) {
205         physic.enable_gravity(true);
206       }
207     }
208   }
209
210   // horizontal bounce?
211   if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) {
212     if (  (physic.get_velocity_x() < 0
213           && issolid(base.x, (int) base.y + base.height/2)) 
214         ||  (physic.get_velocity_x() > 0
215           && issolid(base.x + base.width, (int) base.y + base.height/2))) {
216         physic.set_velocity(-physic.get_velocity_x(),physic.get_velocity_y());
217         dir = dir == LEFT ? RIGHT : LEFT;
218     }
219   }
220 }
221
222 void
223 Upgrade::draw()
224 {
225   SDL_Rect dest;
226   if (base.height < 32)
227     {
228       /* Rising up... */
229
230       dest.x = (int)(base.x - scroll_x);
231       dest.y = (int)(base.y + 32 - base.height);
232       dest.w = 32;
233       dest.h = (int)base.height;
234
235       if (kind == UPGRADE_GROWUP)
236         img_growup->draw_part(0,0,dest.x,dest.y,dest.w,dest.h);
237       else if (kind == UPGRADE_ICEFLOWER)
238         img_iceflower->draw_part(0,0,dest.x,dest.y,dest.w,dest.h);
239       else if (kind == UPGRADE_HERRING)
240         img_golden_herring->draw_part(0,0,dest.x,dest.y,dest.w,dest.h);
241       else if (kind == UPGRADE_1UP)
242         img_1up->draw_part( 0, 0, dest.x, dest.y, dest.w, dest.h);
243     }
244   else
245     {
246       if (kind == UPGRADE_GROWUP)
247         {
248           img_growup->draw(
249                        base.x - scroll_x, base.y);
250         }
251       else if (kind == UPGRADE_ICEFLOWER)
252         {
253           img_iceflower->draw(
254                        base.x - scroll_x, base.y);
255         }
256       else if (kind == UPGRADE_HERRING)
257         {
258           img_golden_herring->draw(
259                        base.x - scroll_x, base.y);
260         }
261       else if (kind == UPGRADE_1UP)
262         {
263           img_1up->draw( base.x - scroll_x, base.y);
264         }
265     }
266 }
267
268 void
269 Upgrade::collision(void* p_c_object, int c_object)
270 {
271   Player* pplayer = NULL;
272
273   switch (c_object)
274     {
275     case CO_PLAYER:
276       /* Remove the upgrade: */
277
278       /* p_c_object is CO_PLAYER, so assign it to pplayer */
279       pplayer = (Player*) p_c_object;
280
281       /* Affect the player: */
282
283       if (kind == UPGRADE_GROWUP)
284         {
285           play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
286           pplayer->size = BIG;
287           pplayer->base.height = 64;
288           pplayer->base.y -= 32;
289           if(collision_object_map(&pplayer->base))
290             {
291               pplayer->base.height = 32;
292               pplayer->base.y += 32;
293               pplayer->duck = true;
294             }
295         }
296       else if (kind == UPGRADE_ICEFLOWER)
297         {
298           play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
299           pplayer->got_coffee = true;
300         }
301       else if (kind == UPGRADE_HERRING)
302         {
303           play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
304           pplayer->invincible_timer.start(TUX_INVINCIBLE_TIME);
305           /* play the herring song ^^ */
306           if (get_current_music() != HURRYUP_MUSIC)
307             {
308               set_current_music(HERRING_MUSIC);
309               play_current_music();
310             }
311         }
312       else if (kind == UPGRADE_1UP)
313         {
314           if(player_status.lives < MAX_LIVES) {
315             player_status.lives++;
316             play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
317           }
318         }
319
320       remove_me();
321       return;
322     }
323 }
324
325 void load_special_gfx()
326 {
327     img_growup = new Surface(datadir + "/images/shared/egg.png", USE_ALPHA);
328     img_iceflower = new Surface(datadir + "/images/shared/iceflower.png",
329             USE_ALPHA);
330     img_golden_herring = new Surface(datadir + "/images/shared/star.png", USE_ALPHA);
331     img_1up = new Surface(datadir + "/images/shared/1up.png",
332             USE_ALPHA);
333
334     img_bullet = new Surface(datadir + "/images/shared/bullet.png",
335             USE_ALPHA);
336 }
337
338 void free_special_gfx()
339 {
340     delete img_growup;
341     delete img_iceflower;
342     delete img_1up;
343     delete img_golden_herring;
344     delete img_bullet;
345 }
346