Don't show selection cursor when help is being displayed.
[supertux.git] / src / special.cpp
1 //  $Id$
2 //
3 //  SuperTux -  A Jump'n Run
4 //  Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <assert.h>
21 #include <iostream>
22 #include "SDL.h"
23 #include "defines.h"
24 #include "special.h"
25 #include "gameloop.h"
26 #include "screen.h"
27 #include "sound.h"
28 #include "scene.h"
29 #include "globals.h"
30 #include "player.h"
31 #include "sprite_manager.h"
32 #include "resources.h"
33
34 Sprite* img_bullet;
35 Sprite* img_star;
36 Sprite* img_growup;
37 Sprite* img_iceflower;
38 Sprite* img_1up;
39
40 #define GROWUP_SPEED 1.0f
41
42 #define BULLET_STARTING_YM 0
43 #define BULLET_XM 6
44
45 void
46 Bullet::init(float x, float y, float xm, Direction dir)
47 {
48   life_count = 3;
49   base.width = 4;
50   base.height = 4;
51
52   if (dir == RIGHT)
53     {
54       base.x = x + 32;
55       base.xm = BULLET_XM + xm;
56     }
57   else
58     {
59       base.x = x;
60       base.xm = -BULLET_XM + xm;
61     }
62
63   base.y = y;
64   base.ym = BULLET_STARTING_YM;
65   old_base = base;
66 }
67
68 void
69 Bullet::remove_me()
70 {
71   std::vector<Bullet>& bullets = World::current()->bullets;
72   for(std::vector<Bullet>::iterator i = bullets.begin();
73          i != bullets.end(); ++i) {
74     if( & (*i) == this) {
75       bullets.erase(i);
76       return;
77     }
78   }
79
80   assert(false);
81 }
82
83 void
84 Bullet::action(double frame_ratio)
85 {
86   frame_ratio *= 0.5f;
87
88   float old_y = base.y;
89
90   base.x = base.x + base.xm * frame_ratio;
91   base.y = base.y + base.ym * frame_ratio;
92
93   collision_swept_object_map(&old_base,&base);
94       
95   if (issolid(base.x, base.y + 4) || issolid(base.x, base.y))
96     {
97       base.y  = old_y;
98       base.ym = -base.ym;     
99       if (base.ym > 9)
100         base.ym = 9;
101       else if (base.ym < -9)
102         base.ym = -9;
103       life_count -= 1;
104     }
105
106   base.ym = base.ym + 0.5 * frame_ratio;
107
108   if (base.x < scroll_x ||
109       base.x > scroll_x + screen->w ||
110       base.y > screen->h ||
111       issolid(base.x + 4, base.y + 2) ||
112       issolid(base.x, base.y + 2) ||
113       life_count <= 0)
114     {
115       remove_me();
116     }
117
118 }
119
120 void 
121 Bullet::draw()
122 {
123   if (base.x >= scroll_x - base.width &&
124       base.x <= scroll_x + screen->w)
125     {
126       img_bullet->draw(base.x - scroll_x, base.y);
127     }
128 }
129
130 void
131 Bullet::collision(int c_object)
132 {
133   if(c_object == CO_BADGUY) {
134     remove_me();
135   }
136 }
137
138 void
139 Upgrade::init(float x_, float y_, Direction dir_, UpgradeKind kind_)
140 {
141   kind = kind_;
142   dir = dir_;
143
144   base.width = 32;
145   base.height = 0;
146   base.x = x_;
147   base.y = y_;
148   old_base = base;
149
150   physic.reset();
151   physic.enable_gravity(false);
152
153   if(kind == UPGRADE_1UP || kind == UPGRADE_HERRING) {
154     physic.set_velocity(dir == LEFT ? -1 : 1, 4);
155     physic.enable_gravity(true);
156     base.height = 32;
157   } else if (kind == UPGRADE_ICEFLOWER) {
158     // nothing
159   } else if (kind == UPGRADE_GROWUP) {
160     physic.set_velocity(dir == LEFT ? -GROWUP_SPEED : GROWUP_SPEED, 0);
161   } else {
162     physic.set_velocity(dir == LEFT ? -2 : 2, 0);
163   }
164 }
165
166 void
167 Upgrade::remove_me()
168 {
169   std::vector<Upgrade>& upgrades = World::current()->upgrades;
170   for(std::vector<Upgrade>::iterator i = upgrades.begin();
171          i != upgrades.end(); ++i) {
172     if( & (*i) == this) {
173       upgrades.erase(i);
174       return;
175     }
176   }
177
178   assert(false);
179 }
180
181 void
182 Upgrade::action(double frame_ratio)
183 {
184   if (kind == UPGRADE_ICEFLOWER || kind == UPGRADE_GROWUP) {
185     if (base.height < 32) {
186       /* Rise up! */
187       base.height = base.height + 0.7 * frame_ratio;
188       if(base.height > 32)
189         base.height = 32;
190
191       return;
192     }
193   }
194
195   /* Away from the screen? Kill it! */
196   if(base.x < scroll_x - OFFSCREEN_DISTANCE) {
197       remove_me();
198       return;
199   }
200   if(base.y > screen->h) {
201     remove_me();
202     return;
203   }
204
205   /* Move around? */
206   physic.apply(frame_ratio, base.x, base.y);
207   if(kind == UPGRADE_GROWUP) {
208     collision_swept_object_map(&old_base, &base);
209   }
210
211   // fall down?
212   if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) {
213     // falling?
214     if(physic.get_velocity_y() != 0) {
215       if(issolid(base.x, base.y + base.height)) {
216         base.y = int(base.y / 32) * 32;
217         old_base = base;                         
218         if(kind == UPGRADE_GROWUP) {
219           physic.enable_gravity(false);
220           physic.set_velocity(dir == LEFT ? -GROWUP_SPEED : GROWUP_SPEED, 0);
221         } else if(kind == UPGRADE_HERRING) {
222           physic.set_velocity(dir == LEFT ? -2 : 2, 3);
223         }
224       }
225     } else {
226       if((physic.get_velocity_x() < 0
227             && !issolid(base.x+base.width, base.y + base.height))
228         || (physic.get_velocity_x() > 0
229             && !issolid(base.x, base.y + base.height))) {
230         physic.enable_gravity(true);
231       }
232     }
233   }
234
235   // horizontal bounce?
236   if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) {
237     if (  (physic.get_velocity_x() < 0
238           && issolid(base.x, (int) base.y + base.height/2)) 
239         ||  (physic.get_velocity_x() > 0
240           && issolid(base.x + base.width, (int) base.y + base.height/2))) {
241         physic.set_velocity(-physic.get_velocity_x(),physic.get_velocity_y());
242         dir = dir == LEFT ? RIGHT : LEFT;
243     }
244   }
245 }
246
247 void
248 Upgrade::draw()
249 {
250   SDL_Rect dest;
251   if (base.height < 32)
252     {
253       /* Rising up... */
254
255       dest.x = (int)(base.x - scroll_x);
256       dest.y = (int)(base.y + 32 - base.height);
257       dest.w = 32;
258       dest.h = (int)base.height;
259
260       if (kind == UPGRADE_GROWUP)
261         img_growup->draw_part(0,0,dest.x,dest.y,dest.w,dest.h);
262       else if (kind == UPGRADE_ICEFLOWER)
263         img_iceflower->draw_part(0,0,dest.x,dest.y,dest.w,dest.h);
264       else if (kind == UPGRADE_HERRING)
265         img_star->draw_part(0,0,dest.x,dest.y,dest.w,dest.h);
266       else if (kind == UPGRADE_1UP)
267         img_1up->draw_part( 0, 0, dest.x, dest.y, dest.w, dest.h);
268     }
269   else
270     {
271       if (kind == UPGRADE_GROWUP)
272         {
273           img_growup->draw(
274                        base.x - scroll_x, base.y);
275         }
276       else if (kind == UPGRADE_ICEFLOWER)
277         {
278           img_iceflower->draw(
279                        base.x - scroll_x, base.y);
280         }
281       else if (kind == UPGRADE_HERRING)
282         {
283           img_star->draw(
284                        base.x - scroll_x, base.y);
285         }
286       else if (kind == UPGRADE_1UP)
287         {
288           img_1up->draw( base.x - scroll_x, base.y);
289         }
290     }
291 }
292
293 void
294 Upgrade::bump(Player* )
295 {
296   // these can't be bumped
297   if(kind != UPGRADE_GROWUP)
298     return;
299
300   play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
301   
302   // do a little jump and change direction
303   physic.set_velocity(-physic.get_velocity_x(), 3);
304   dir = dir == LEFT ? RIGHT : LEFT;
305   physic.enable_gravity(true);
306 }
307
308 void
309 Upgrade::collision(void* p_c_object, int c_object, CollisionType type)
310 {
311   Player* pplayer = NULL;
312
313   if(type == COLLISION_BUMP) {
314     if(c_object == CO_PLAYER)
315       pplayer = (Player*) p_c_object;
316     bump(pplayer);
317     return;
318   }
319
320   switch (c_object)
321     {
322     case CO_PLAYER:
323       /* Remove the upgrade: */
324
325       /* p_c_object is CO_PLAYER, so assign it to pplayer */
326       pplayer = (Player*) p_c_object;
327
328       /* Affect the player: */
329
330       if (kind == UPGRADE_GROWUP)
331         {
332           play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
333           pplayer->grow();
334         }
335       else if (kind == UPGRADE_ICEFLOWER)
336         {
337           play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
338           pplayer->grow();
339           pplayer->got_coffee = true;
340         }
341       else if (kind == UPGRADE_HERRING)
342         {
343           play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
344           pplayer->invincible_timer.start(TUX_INVINCIBLE_TIME);
345           World::current()->play_music(HERRING_MUSIC);
346         }
347       else if (kind == UPGRADE_1UP)
348         {
349           if(player_status.lives < MAX_LIVES) {
350             player_status.lives++;
351             play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
352           }
353         }
354
355       remove_me();
356       return;
357     }
358 }
359
360 void load_special_gfx()
361 {
362   img_growup    = sprite_manager->load("egg");
363   img_iceflower = sprite_manager->load("iceflower");
364   img_star      = sprite_manager->load("star");
365   img_1up       = sprite_manager->load("1up");
366
367   img_bullet    = sprite_manager->load("bullet");
368 }
369
370 void free_special_gfx()
371 {
372 }
373