2e5a05a011273caa1e1344ef14ee308e9b361773
[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       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     for(i = bullets.begin(); i != bullets.end(); ++i) {
95       if(& (*i) == pbullet) {
96         bullets.erase(i);
97         return;
98       }
99     }
100   }
101 }
102
103 void upgrade_init(upgrade_type *pupgrade, float x, float y, int dir, int kind)
104 {
105   pupgrade->base.width = 32;
106   pupgrade->base.height = 0;
107   pupgrade->kind = kind;
108   pupgrade->base.x = x;
109   pupgrade->base.y = y;
110   if(dir == LEFT)
111     pupgrade->base.xm = -2;
112   else
113     pupgrade->base.xm = 2;
114   pupgrade->base.ym = -2;
115   pupgrade->base.height = 0;
116   pupgrade->old_base = pupgrade->base;
117 }
118
119 void upgrade_action(upgrade_type *pupgrade)
120 {
121
122
123   if (pupgrade->base.height < 32)
124     {
125       /* Rise up! */
126
127       pupgrade->base.height = pupgrade->base.height + 0.7 * frame_ratio;
128       if(pupgrade->base.height > 32)
129         pupgrade->base.height = 32;
130     }
131   else
132     {
133       /* Move around? */
134
135       if (pupgrade->kind == UPGRADE_MINTS ||
136           pupgrade->kind == UPGRADE_HERRING)
137         {
138           pupgrade->base.x = pupgrade->base.x + pupgrade->base.xm * frame_ratio;
139           pupgrade->base.y = pupgrade->base.y + pupgrade->base.ym * frame_ratio;
140
141           collision_swept_object_map(&pupgrade->old_base,&pupgrade->base);
142
143           /* Off the screen?  Kill it! */
144
145           if (pupgrade->base.x < scroll_x - pupgrade->base.width)
146             upgrades.erase(static_cast<std::vector<upgrade_type>::iterator>(pupgrade));
147           if (pupgrade->base.y > screen->h)
148             upgrades.erase(static_cast<std::vector<upgrade_type>::iterator>(pupgrade));
149
150           if (issolid(pupgrade->base.x + 1, pupgrade->base.y + 32.) ||
151               issolid(pupgrade->base.x + 31., pupgrade->base.y + 32.))
152             {
153               if (pupgrade->base.ym > 0)
154                 {
155                   if (pupgrade->kind == UPGRADE_MINTS)
156                     {
157                       pupgrade->base.ym = 0;
158                     }
159                   else if (pupgrade->kind == UPGRADE_HERRING)
160                     {
161                       pupgrade->base.ym = -8;
162                     }
163
164                   pupgrade->base.y = (int)(pupgrade->base.y / 32) * 32;
165                 }
166             }
167           else
168             pupgrade->base.ym = pupgrade->base.ym + GRAVITY * frame_ratio;
169
170           if (issolid(pupgrade->base.x - 1, (int) pupgrade->base.y))
171             {
172               if(pupgrade->base.xm < 0)
173                 pupgrade->base.xm = -pupgrade->base.xm;
174             }
175           else if (issolid(pupgrade->base.x + pupgrade->base.width, (int) pupgrade->base.y))
176             {
177               if(pupgrade->base.xm > 0)
178                 pupgrade->base.xm = -pupgrade->base.xm;
179             }
180         }
181
182     }
183 }
184
185 void upgrade_draw(upgrade_type* pupgrade)
186 {
187   SDL_Rect dest;
188   if (pupgrade->base.height < 32)
189     {
190       /* Rising up... */
191
192       dest.x = (int)(pupgrade->base.x - scroll_x);
193       dest.y = (int)(pupgrade->base.y + 32 - pupgrade->base.height);
194       dest.w = 32;
195       dest.h = (int)pupgrade->base.height;
196
197       if (pupgrade->kind == UPGRADE_MINTS)
198         texture_draw_part(&img_mints,0,0,dest.x,dest.y,dest.w,dest.h);
199       else if (pupgrade->kind == UPGRADE_COFFEE)
200         texture_draw_part(&img_coffee,0,0,dest.x,dest.y,dest.w,dest.h);
201       else if (pupgrade->kind == UPGRADE_HERRING)
202         texture_draw_part(&img_golden_herring,0,0,dest.x,dest.y,dest.w,dest.h);
203     }
204   else
205     {
206       if (pupgrade->kind == UPGRADE_MINTS)
207         {
208           texture_draw(&img_mints,
209                        pupgrade->base.x - scroll_x, pupgrade->base.y);
210         }
211       else if (pupgrade->kind == UPGRADE_COFFEE)
212         {
213           texture_draw(&img_coffee,
214                        pupgrade->base.x - scroll_x, pupgrade->base.y);
215         }
216       else if (pupgrade->kind == UPGRADE_HERRING)
217         {
218           texture_draw(&img_golden_herring,
219                        pupgrade->base.x - scroll_x, pupgrade->base.y);
220         }
221     }
222 }
223
224 void upgrade_collision(upgrade_type* pupgrade, void* p_c_object, int c_object)
225 {
226   Player* pplayer = NULL;
227
228   switch (c_object)
229     {
230     case CO_PLAYER:
231       /* Remove the upgrade: */
232
233       /* p_c_object is CO_PLAYER, so assign it to pplayer */
234       pplayer = (Player*) p_c_object;
235
236       upgrades.erase(static_cast<std::vector<upgrade_type>::iterator>(pupgrade));
237
238       /* Affect the player: */
239
240       if (pupgrade->kind == UPGRADE_MINTS)
241         {
242           play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
243           pplayer->size = BIG;
244           pplayer->base.height = 64;
245           pplayer->base.y -= 32;
246           if(collision_object_map(&pplayer->base))
247             {
248               pplayer->base.height = 32;
249               pplayer->base.y += 32;
250               pplayer->duck = true;
251             }
252           timer_start(&super_bkgd_timer, 350);
253         }
254       else if (pupgrade->kind == UPGRADE_COFFEE)
255         {
256           play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
257           pplayer->got_coffee = true;
258           timer_start(&super_bkgd_timer, 250);
259         }
260       else if (pupgrade->kind == UPGRADE_HERRING)
261         {
262           play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
263           timer_start(&pplayer->invincible_timer,TUX_INVINCIBLE_TIME);
264           timer_start(&super_bkgd_timer, 250);
265           /* play the herring song ^^ */
266           if (get_current_music() != HURRYUP_MUSIC)
267             {
268               set_current_music(HERRING_MUSIC);
269               play_current_music();
270             }
271         }
272       break;
273     }
274 }
275