- renamed 'world' to 'global_world' to emphasis that it is mainly a temporary hack
[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 "SDL.h"
14 #include "defines.h"
15 #include "special.h"
16 #include "gameloop.h"
17 #include "screen.h"
18 #include "sound.h"
19 #include "scene.h"
20 #include "globals.h"
21 #include "player.h"
22
23 texture_type img_bullet;
24 texture_type img_golden_herring;
25 bitmask* bm_bullet;
26
27 void create_special_bitmasks()
28 {
29   bm_bullet = bitmask_create_SDL(img_bullet.sdl_surface);
30 }
31
32 void bullet_init(bullet_type* pbullet, float x, float y, float xm, int dir)
33 {
34   pbullet->base.width = 4;
35   pbullet->base.height = 4;
36
37   if (dir == RIGHT)
38     {
39       pbullet->base.x = x + 32;
40       pbullet->base.xm = BULLET_XM + xm;
41     }
42   else
43     {
44       pbullet->base.x = x;
45       pbullet->base.xm = -BULLET_XM + xm;
46     }
47
48   pbullet->base.y = y;
49   pbullet->base.ym = BULLET_STARTING_YM;
50   pbullet->old_base = pbullet->base;
51 }
52
53 void bullet_action(bullet_type* pbullet)
54 {
55   pbullet->base.x = pbullet->base.x + pbullet->base.xm * frame_ratio;
56   pbullet->base.y = pbullet->base.y + pbullet->base.ym * frame_ratio;
57
58   collision_swept_object_map(&pbullet->old_base,&pbullet->base);
59       
60   if (issolid(pbullet->base.x, pbullet->base.y + 4) || issolid(pbullet->base.x, pbullet->base.y))
61     {
62       pbullet->base.ym = -pbullet->base.ym;
63       pbullet->base.y = (int)(pbullet->base.y / 32) * 32;
64     }
65
66   pbullet->base.ym = pbullet->base.ym + GRAVITY;
67
68   if (pbullet->base.x < scroll_x ||
69       pbullet->base.x > scroll_x + screen->w ||
70       pbullet->base.y < 0 ||
71       pbullet->base.y > screen->h ||
72       issolid(pbullet->base.x + 4, pbullet->base.y + 2) ||
73       issolid(pbullet->base.x, pbullet->base.y + 2))
74     {
75       World::current()->bullets.erase(static_cast<std::vector<bullet_type>::iterator>(pbullet));
76     }
77
78 }
79
80 void bullet_draw(bullet_type* pbullet)
81 {
82   if (pbullet->base.x >= scroll_x - pbullet->base.width &&
83       pbullet->base.x <= scroll_x + screen->w)
84     {
85       texture_draw(&img_bullet, pbullet->base.x - scroll_x, pbullet->base.y, 255,
86                    NO_UPDATE);
87     }
88 }
89
90 void bullet_collision(bullet_type* pbullet, int c_object)
91 {
92   if(c_object == CO_BADGUY) {
93     std::vector<bullet_type>::iterator i;
94     
95     for(i = World::current()->bullets.begin(); i != World::current()->bullets.end(); ++i) {
96       if(& (*i) == pbullet) {
97         World::current()->bullets.erase(i);
98         return;
99       }
100     }
101   }
102 }
103
104 void upgrade_init(upgrade_type *pupgrade, float x, float y, int dir, int kind)
105 {
106   pupgrade->base.width = 32;
107   pupgrade->base.height = 0;
108   pupgrade->kind = kind;
109   pupgrade->base.x = x;
110   pupgrade->base.y = y;
111   if(dir == LEFT)
112     pupgrade->base.xm = -2;
113   else
114     pupgrade->base.xm = 2;
115   pupgrade->base.ym = -2;
116   pupgrade->base.height = 0;
117   pupgrade->old_base = pupgrade->base;
118 }
119
120 void upgrade_action(upgrade_type *pupgrade)
121 {
122
123
124   if (pupgrade->base.height < 32)
125     {
126       /* Rise up! */
127
128       pupgrade->base.height = pupgrade->base.height + 0.7 * frame_ratio;
129       if(pupgrade->base.height > 32)
130         pupgrade->base.height = 32;
131     }
132   else
133     {
134       /* Move around? */
135
136       if (pupgrade->kind == UPGRADE_MINTS ||
137           pupgrade->kind == UPGRADE_HERRING)
138         {
139           pupgrade->base.x = pupgrade->base.x + pupgrade->base.xm * frame_ratio;
140           pupgrade->base.y = pupgrade->base.y + pupgrade->base.ym * frame_ratio;
141
142           collision_swept_object_map(&pupgrade->old_base,&pupgrade->base);
143
144           /* Off the screen?  Kill it! */
145
146           if (pupgrade->base.x < scroll_x - pupgrade->base.width)
147             World::current()->upgrades.erase(static_cast<std::vector<upgrade_type>::iterator>(pupgrade));
148           if (pupgrade->base.y > screen->h)
149             World::current()->upgrades.erase(static_cast<std::vector<upgrade_type>::iterator>(pupgrade));
150
151           if (issolid(pupgrade->base.x + 1, pupgrade->base.y + 32.) ||
152               issolid(pupgrade->base.x + 31., pupgrade->base.y + 32.))
153             {
154               if (pupgrade->base.ym > 0)
155                 {
156                   if (pupgrade->kind == UPGRADE_MINTS)
157                     {
158                       pupgrade->base.ym = 0;
159                     }
160                   else if (pupgrade->kind == UPGRADE_HERRING)
161                     {
162                       pupgrade->base.ym = -8;
163                     }
164
165                   pupgrade->base.y = (int)(pupgrade->base.y / 32) * 32;
166                 }
167             }
168           else
169             pupgrade->base.ym = pupgrade->base.ym + GRAVITY * frame_ratio;
170
171           if (issolid(pupgrade->base.x - 1, (int) pupgrade->base.y))
172             {
173               if(pupgrade->base.xm < 0)
174                 pupgrade->base.xm = -pupgrade->base.xm;
175             }
176           else if (issolid(pupgrade->base.x + pupgrade->base.width, (int) pupgrade->base.y))
177             {
178               if(pupgrade->base.xm > 0)
179                 pupgrade->base.xm = -pupgrade->base.xm;
180             }
181         }
182
183     }
184 }
185
186 void upgrade_draw(upgrade_type* pupgrade)
187 {
188   SDL_Rect dest;
189   if (pupgrade->base.height < 32)
190     {
191       /* Rising up... */
192
193       dest.x = (int)(pupgrade->base.x - scroll_x);
194       dest.y = (int)(pupgrade->base.y + 32 - pupgrade->base.height);
195       dest.w = 32;
196       dest.h = (int)pupgrade->base.height;
197
198       if (pupgrade->kind == UPGRADE_MINTS)
199         texture_draw_part(&img_mints,0,0,dest.x,dest.y,dest.w,dest.h);
200       else if (pupgrade->kind == UPGRADE_COFFEE)
201         texture_draw_part(&img_coffee,0,0,dest.x,dest.y,dest.w,dest.h);
202       else if (pupgrade->kind == UPGRADE_HERRING)
203         texture_draw_part(&img_golden_herring,0,0,dest.x,dest.y,dest.w,dest.h);
204     }
205   else
206     {
207       if (pupgrade->kind == UPGRADE_MINTS)
208         {
209           texture_draw(&img_mints,
210                        pupgrade->base.x - scroll_x, pupgrade->base.y);
211         }
212       else if (pupgrade->kind == UPGRADE_COFFEE)
213         {
214           texture_draw(&img_coffee,
215                        pupgrade->base.x - scroll_x, pupgrade->base.y);
216         }
217       else if (pupgrade->kind == UPGRADE_HERRING)
218         {
219           texture_draw(&img_golden_herring,
220                        pupgrade->base.x - scroll_x, pupgrade->base.y);
221         }
222     }
223 }
224
225 void upgrade_collision(upgrade_type* pupgrade, void* p_c_object, int c_object)
226 {
227   Player* pplayer = NULL;
228
229   switch (c_object)
230     {
231     case CO_PLAYER:
232       /* Remove the upgrade: */
233
234       /* p_c_object is CO_PLAYER, so assign it to pplayer */
235       pplayer = (Player*) p_c_object;
236
237       World::current()->upgrades.erase(static_cast<std::vector<upgrade_type>::iterator>(pupgrade));
238
239       /* Affect the player: */
240
241       if (pupgrade->kind == UPGRADE_MINTS)
242         {
243           play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
244           pplayer->size = BIG;
245           pplayer->base.height = 64;
246           pplayer->base.y -= 32;
247           if(collision_object_map(&pplayer->base))
248             {
249               pplayer->base.height = 32;
250               pplayer->base.y += 32;
251               pplayer->duck = true;
252             }
253           timer_start(&super_bkgd_timer, 350);
254         }
255       else if (pupgrade->kind == UPGRADE_COFFEE)
256         {
257           play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
258           pplayer->got_coffee = true;
259           timer_start(&super_bkgd_timer, 250);
260         }
261       else if (pupgrade->kind == UPGRADE_HERRING)
262         {
263           play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
264           timer_start(&pplayer->invincible_timer,TUX_INVINCIBLE_TIME);
265           timer_start(&super_bkgd_timer, 250);
266           /* play the herring song ^^ */
267           if (get_current_music() != HURRYUP_MUSIC)
268             {
269               set_current_music(HERRING_MUSIC);
270               play_current_music();
271             }
272         }
273       break;
274     }
275 }
276