huge CVS merge, see ChangeLog for details.
[supertux.git] / src / special.c
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 }
52
53 void bullet_action(bullet_type* pbullet)
54 {
55   if (pbullet->base.alive)
56     {
57       pbullet->base.x = pbullet->base.x + pbullet->base.xm * frame_ratio;
58       pbullet->base.y = pbullet->base.y + pbullet->base.ym * frame_ratio;
59
60       if (issolid(pbullet->base.x, pbullet->base.y))
61         {
62           if (issolid(pbullet->base.x, pbullet->base.y - pbullet->base.ym))
63             pbullet->base.alive = NO;
64           else
65             {
66               if (pbullet->base.ym >= 0)
67                 {
68                   pbullet->base.y = (int)(pbullet->base.y / 32) * 32 - 8;
69                 }
70               pbullet->base.ym = -pbullet->base.ym;
71             }
72         }
73
74       pbullet->base.ym = pbullet->base.ym + GRAVITY;
75
76       if (pbullet->base.x < scroll_x ||
77           pbullet->base.x > scroll_x + screen->w)
78         {
79           pbullet->base.alive = NO;
80         }
81     }
82
83 }
84
85 void bullet_draw(bullet_type* pbullet)
86 {
87   if (pbullet->base.alive  &&
88       pbullet->base.x >= scroll_x - pbullet->base.width &&
89       pbullet->base.x <= scroll_x + screen->w)
90     {
91       texture_draw(&img_bullet, pbullet->base.x - scroll_x, pbullet->base.y,
92                    NO_UPDATE);
93     }
94 }
95
96 void bullet_collision(bullet_type* pbullet, int c_object)
97 {
98
99   if(c_object == CO_BADGUY)
100     pbullet->base.alive = NO;
101
102 }
103
104 void upgrade_init(upgrade_type *pupgrade, float x, float y, int kind)
105 {
106   pupgrade->base.width = 32;
107   pupgrade->base.height = 0;
108   pupgrade->base.alive = YES;
109   pupgrade->kind = kind;
110   pupgrade->base.x = x;
111   pupgrade->base.y = y;
112   pupgrade->base.xm = 2;
113   pupgrade->base.ym = -2;
114   pupgrade->base.height = 0;
115 }
116
117 void upgrade_action(upgrade_type *pupgrade)
118 {
119
120   if (pupgrade->base.alive)
121     {
122       if (pupgrade->base.height < 32)
123         {
124           /* Rise up! */
125
126           pupgrade->base.height = pupgrade->base.height + 0.7 * frame_ratio;
127           if(pupgrade->base.height > 32)
128           pupgrade->base.height = 32;
129         }
130       else
131         {
132           /* Move around? */
133
134           if (pupgrade->kind == UPGRADE_MINTS ||
135               pupgrade->kind == UPGRADE_HERRING)
136             {
137               pupgrade->base.x = pupgrade->base.x + pupgrade->base.xm * frame_ratio;
138               pupgrade->base.y = pupgrade->base.y + pupgrade->base.ym * frame_ratio;
139
140               if (issolid(pupgrade->base.x, pupgrade->base.y + 31.) ||
141                   issolid(pupgrade->base.x + 31., pupgrade->base.y + 31.))
142                 {
143                   if (pupgrade->base.ym > 0)
144                     {
145                       if (pupgrade->kind == UPGRADE_MINTS)
146                         {
147                           pupgrade->base.ym = 0;
148                         }
149                       else if (pupgrade->kind == UPGRADE_HERRING)
150                         {
151                           pupgrade->base.ym = -8;
152                         }
153
154                       pupgrade->base.y = (int)(pupgrade->base.y / 32) * 32;
155                     }
156                 }
157               else
158                 pupgrade->base.ym = pupgrade->base.ym + GRAVITY;
159
160                   if (issolid(pupgrade->base.x - 1, (int) pupgrade->base.y))
161                     {
162                       if(pupgrade->base.xm < 0)
163                       pupgrade->base.xm = -pupgrade->base.xm;
164                     }
165                     else if (issolid(pupgrade->base.x + pupgrade->base.width-1, (int) pupgrade->base.y))
166                     {
167                       if(pupgrade->base.xm > 0)
168                       pupgrade->base.xm = -pupgrade->base.xm;
169                     }
170             }
171
172
173           /* Off the screen?  Kill it! */
174
175           if (pupgrade->base.x < scroll_x - pupgrade->base.width)
176             pupgrade->base.alive = NO;
177
178         }
179     }
180 }
181
182 void upgrade_draw(upgrade_type* pupgrade)
183 {
184 SDL_Rect dest;
185   if (pupgrade->base.alive)
186     {
187       if (pupgrade->base.height < 32)
188         {
189           /* Rising up... */
190
191           dest.x = (int)(pupgrade->base.x - scroll_x);
192           dest.y = (int)(pupgrade->base.y + 32 - pupgrade->base.height);
193           dest.w = 32;
194           dest.h = (int)pupgrade->base.height;
195
196           if (pupgrade->kind == UPGRADE_MINTS)
197             texture_draw_part(&img_mints,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE);
198           else if (pupgrade->kind == UPGRADE_COFFEE)
199             texture_draw_part(&img_coffee,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE);
200           else if (pupgrade->kind == UPGRADE_HERRING)
201             texture_draw_part(&img_golden_herring,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE);
202         }
203       else
204         {
205           if (pupgrade->kind == UPGRADE_MINTS)
206             {
207               texture_draw(&img_mints,
208                            pupgrade->base.x - scroll_x, pupgrade->base.y,
209                            NO_UPDATE);
210             }
211           else if (pupgrade->kind == UPGRADE_COFFEE)
212             {
213               texture_draw(&img_coffee,
214                            pupgrade->base.x - scroll_x, pupgrade->base.y,
215                            NO_UPDATE);
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                            NO_UPDATE);
222             }
223         }
224     }
225 }
226
227 void upgrade_collision(upgrade_type* pupgrade, void* p_c_object, int c_object)
228 {
229   player_type* pplayer = NULL;
230
231   switch (c_object)
232     {
233     case CO_PLAYER:
234       /* Remove the upgrade: */
235
236       /* p_c_object is CO_PLAYER, so assign it to pplayer */
237       pplayer = (player_type*) p_c_object;
238
239       pupgrade->base.alive = NO;
240
241       /* Affect the player: */
242
243       if (pupgrade->kind == UPGRADE_MINTS)
244         {
245           play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
246           pplayer->size = BIG;
247           pplayer->base.height = 64;
248           timer_start(&super_bkgd_timer, 350);
249         }
250       else if (pupgrade->kind == UPGRADE_COFFEE)
251         {
252           play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
253           pplayer->got_coffee = YES;
254           timer_start(&super_bkgd_timer, 250);
255         }
256       else if (pupgrade->kind == UPGRADE_HERRING)
257         {
258           play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
259           timer_start(&pplayer->invincible_timer,TUX_INVINCIBLE_TIME);
260           timer_start(&super_bkgd_timer, 250);
261           /* play the herring song ^^ */
262           if (current_music != HURRYUP_MUSIC)
263             {
264               current_music = HERRING_MUSIC;
265               if (playing_music())
266                 halt_music();
267             }
268         }
269       break;
270     }
271 }
272