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