- renamed *.c to *.cxx
[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   pbullet->base.alive = YES;
37
38   if (dir == RIGHT)
39     {
40       pbullet->base.x = x + 32;
41       pbullet->base.xm = BULLET_XM + xm;
42     }
43   else
44     {
45       pbullet->base.x = x;
46       pbullet->base.xm = -BULLET_XM + xm;
47     }
48
49   pbullet->base.y = y;
50   pbullet->base.ym = BULLET_STARTING_YM;
51   pbullet->old_base = pbullet->base;
52 }
53
54 void bullet_action(bullet_type* pbullet)
55 {
56   if (pbullet->base.alive)
57     {
58       pbullet->base.x = pbullet->base.x + pbullet->base.xm * frame_ratio;
59       pbullet->base.y = pbullet->base.y + pbullet->base.ym * frame_ratio;
60
61       collision_swept_object_map(&pbullet->old_base,&pbullet->base);
62       
63       if (issolid(pbullet->base.x, pbullet->base.y + 4) || issolid(pbullet->base.x, pbullet->base.y))
64         {
65               pbullet->base.ym = -pbullet->base.ym;
66               pbullet->base.y = (int)(pbullet->base.y / 32) * 32;
67         }
68
69       pbullet->base.ym = pbullet->base.ym + GRAVITY;
70
71       if (pbullet->base.x < scroll_x ||
72           pbullet->base.x > scroll_x + screen->w ||
73           pbullet->base.y < 0 ||
74           pbullet->base.y > screen->h ||
75           issolid(pbullet->base.x + 4, pbullet->base.y + 2) ||
76           issolid(pbullet->base.x, pbullet->base.y + 2))
77         {
78           pbullet->base.alive = NO;
79         }
80     }
81
82 }
83
84 void bullet_draw(bullet_type* pbullet)
85 {
86   if (pbullet->base.alive  &&
87       pbullet->base.x >= scroll_x - pbullet->base.width &&
88       pbullet->base.x <= scroll_x + screen->w)
89     {
90       texture_draw(&img_bullet, pbullet->base.x - scroll_x, pbullet->base.y,
91                    NO_UPDATE);
92     }
93 }
94
95 void bullet_collision(bullet_type* pbullet, int c_object)
96 {
97
98   if(c_object == CO_BADGUY)
99     pbullet->base.alive = NO;
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->base.alive = YES;
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   if (pupgrade->base.alive)
124     {
125       if (pupgrade->base.height < 32)
126         {
127           /* Rise up! */
128
129           pupgrade->base.height = pupgrade->base.height + 0.7 * frame_ratio;
130           if(pupgrade->base.height > 32)
131             pupgrade->base.height = 32;
132         }
133       else
134         {
135           /* Move around? */
136
137           if (pupgrade->kind == UPGRADE_MINTS ||
138               pupgrade->kind == UPGRADE_HERRING)
139             {
140               pupgrade->base.x = pupgrade->base.x + pupgrade->base.xm * frame_ratio;
141               pupgrade->base.y = pupgrade->base.y + pupgrade->base.ym * frame_ratio;
142
143               collision_swept_object_map(&pupgrade->old_base,&pupgrade->base);
144
145               /* Off the screen?  Kill it! */
146
147               if (pupgrade->base.x < scroll_x - pupgrade->base.width)
148                 pupgrade->base.alive = NO;
149               if (pupgrade->base.y > screen->h)
150                 pupgrade->base.alive = NO;
151
152               if (issolid(pupgrade->base.x + 1, pupgrade->base.y + 32.) ||
153                   issolid(pupgrade->base.x + 31., pupgrade->base.y + 32.))
154                 {
155                   if (pupgrade->base.ym > 0)
156                     {
157                       if (pupgrade->kind == UPGRADE_MINTS)
158                         {
159                           pupgrade->base.ym = 0;
160                         }
161                       else if (pupgrade->kind == UPGRADE_HERRING)
162                         {
163                           pupgrade->base.ym = -8;
164                         }
165
166                       pupgrade->base.y = (int)(pupgrade->base.y / 32) * 32;
167                     }
168                 }
169               else
170                 pupgrade->base.ym = pupgrade->base.ym + GRAVITY * frame_ratio;
171
172               if (issolid(pupgrade->base.x - 1, (int) pupgrade->base.y))
173                 {
174                   if(pupgrade->base.xm < 0)
175                     pupgrade->base.xm = -pupgrade->base.xm;
176                 }
177               else if (issolid(pupgrade->base.x + pupgrade->base.width, (int) pupgrade->base.y))
178                 {
179                   if(pupgrade->base.xm > 0)
180                     pupgrade->base.xm = -pupgrade->base.xm;
181                 }
182             }
183
184         }
185     }
186 }
187
188 void upgrade_draw(upgrade_type* pupgrade)
189 {
190   SDL_Rect dest;
191   if (pupgrade->base.alive)
192     {
193       if (pupgrade->base.height < 32)
194         {
195           /* Rising up... */
196
197           dest.x = (int)(pupgrade->base.x - scroll_x);
198           dest.y = (int)(pupgrade->base.y + 32 - pupgrade->base.height);
199           dest.w = 32;
200           dest.h = (int)pupgrade->base.height;
201
202           if (pupgrade->kind == UPGRADE_MINTS)
203             texture_draw_part(&img_mints,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE);
204           else if (pupgrade->kind == UPGRADE_COFFEE)
205             texture_draw_part(&img_coffee,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE);
206           else if (pupgrade->kind == UPGRADE_HERRING)
207             texture_draw_part(&img_golden_herring,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE);
208         }
209       else
210         {
211           if (pupgrade->kind == UPGRADE_MINTS)
212             {
213               texture_draw(&img_mints,
214                            pupgrade->base.x - scroll_x, pupgrade->base.y,
215                            NO_UPDATE);
216             }
217           else if (pupgrade->kind == UPGRADE_COFFEE)
218             {
219               texture_draw(&img_coffee,
220                            pupgrade->base.x - scroll_x, pupgrade->base.y,
221                            NO_UPDATE);
222             }
223           else if (pupgrade->kind == UPGRADE_HERRING)
224             {
225               texture_draw(&img_golden_herring,
226                            pupgrade->base.x - scroll_x, pupgrade->base.y,
227                            NO_UPDATE);
228             }
229         }
230     }
231 }
232
233 void upgrade_collision(upgrade_type* pupgrade, void* p_c_object, int c_object)
234 {
235   player_type* pplayer = NULL;
236
237   switch (c_object)
238     {
239     case CO_PLAYER:
240       /* Remove the upgrade: */
241
242       /* p_c_object is CO_PLAYER, so assign it to pplayer */
243       pplayer = (player_type*) p_c_object;
244
245       pupgrade->base.alive = NO;
246
247       /* Affect the player: */
248
249       if (pupgrade->kind == UPGRADE_MINTS)
250         {
251           play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
252           pplayer->size = BIG;
253           pplayer->base.height = 64;
254           pplayer->base.y -= 32;
255           if(collision_object_map(&pplayer->base))
256           {
257           pplayer->base.height = 32;
258           pplayer->base.y += 32;
259           pplayer->duck = YES;
260           }
261           timer_start(&super_bkgd_timer, 350);
262         }
263       else if (pupgrade->kind == UPGRADE_COFFEE)
264         {
265           play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
266           pplayer->got_coffee = YES;
267           timer_start(&super_bkgd_timer, 250);
268         }
269       else if (pupgrade->kind == UPGRADE_HERRING)
270         {
271           play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
272           timer_start(&pplayer->invincible_timer,TUX_INVINCIBLE_TIME);
273           timer_start(&super_bkgd_timer, 250);
274           /* play the herring song ^^ */
275           if (get_current_music() != HURRYUP_MUSIC)
276             {
277               set_current_music(HERRING_MUSIC);
278               play_current_music();
279             }
280         }
281       break;
282     }
283 }
284