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