- trampoline stuff
[supertux.git] / src / gameobjs.cpp
1 //  $Id$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
5 //  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 // 
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 //  02111-1307, USA.
21 #include <algorithm>
22 #include <iostream>
23 #include "world.h"
24 #include "tile.h"
25 #include "gameloop.h"
26 #include "gameobjs.h"
27 #include "sprite_manager.h"
28 #include "resources.h"
29
30 void
31 BouncyDistro::init(float x, float y)
32 {
33   base.x = x;
34   base.y = y;
35   base.ym = -2;
36 }
37
38 void
39 BouncyDistro::action(double frame_ratio)
40 {
41   base.y = base.y + base.ym * frame_ratio;
42
43   base.ym += 0.1 * frame_ratio;
44
45   if (base.ym >= 0)
46     {
47       std::vector<BouncyDistro*>::iterator i
48         = std::find(World::current()->bouncy_distros.begin(), 
49                     World::current()->bouncy_distros.end(), 
50                     this);
51       if (i != World::current()->bouncy_distros.end())
52         World::current()->bouncy_distros.erase(i);
53     }
54 }
55
56 void
57 BouncyDistro::draw()
58 {
59   img_distro[0]->draw(base.x - scroll_x,
60                       base.y - scroll_y);
61 }
62
63
64 void
65 BrokenBrick::init(Tile* tile_, float x, float y, float xm, float ym)
66 {
67   tile    = tile_;
68   base.x  = x;
69   base.y  = y;
70   base.xm = xm;
71   base.ym = ym;
72
73   timer.init(true);
74   timer.start(200);
75 }
76
77 void
78 BrokenBrick::action(double frame_ratio)
79 {
80   base.x = base.x + base.xm * frame_ratio;
81   base.y = base.y + base.ym * frame_ratio;
82
83   if (!timer.check())
84     {
85       std::vector<BrokenBrick*>::iterator i
86         = std::find(World::current()->broken_bricks.begin(), 
87                     World::current()->broken_bricks.end(), 
88                     this);
89       if (i != World::current()->broken_bricks.end())
90         World::current()->broken_bricks.erase(i);
91     }
92 }
93
94 void
95 BrokenBrick::draw()
96 {
97   SDL_Rect src, dest;
98   src.x = rand() % 16;
99   src.y = rand() % 16;
100   src.w = 16;
101   src.h = 16;
102
103   dest.x = (int)(base.x - scroll_x);
104   dest.y = (int)(base.y  - scroll_y);
105   dest.w = 16;
106   dest.h = 16;
107   
108   if (tile->images.size() > 0)
109     tile->images[0]->draw_part(src.x,src.y,dest.x,dest.y,dest.w,dest.h);
110 }
111
112 void
113 BouncyBrick::init(float x, float y)
114 {
115   base.x   = x;
116   base.y   = y;
117   offset   = 0;
118   offset_m = -BOUNCY_BRICK_SPEED;
119   shape    = World::current()->get_level()->gettileid(x, y);
120 }
121
122 void
123 BouncyBrick::action(double frame_ratio)
124 {
125   offset = (offset + offset_m * frame_ratio);
126
127   /* Go back down? */
128   if (offset < -BOUNCY_BRICK_MAX_OFFSET)
129     offset_m = BOUNCY_BRICK_SPEED;
130
131
132   /* Stop bouncing? */
133   if (offset >= 0)
134     {
135       std::vector<BouncyBrick*>::iterator i
136         = std::find(World::current()->bouncy_bricks.begin(), 
137                     World::current()->bouncy_bricks.end(), 
138                     this);
139       if (i != World::current()->bouncy_bricks.end())
140         World::current()->bouncy_bricks.erase(i);
141     }
142 }
143
144 void
145 BouncyBrick::draw()
146 {
147   SDL_Rect dest;
148   
149   if (base.x >= scroll_x - 32 &&
150       base.x <= scroll_x + screen->w)
151     {
152       dest.x = (int)(base.x - scroll_x);
153       dest.y = (int)(base.y - scroll_y);
154       dest.w = 32;
155       dest.h = 32;
156
157       Level* plevel = World::current()->get_level();
158
159       // FIXME: overdrawing hack to clean the tile from the screen to
160       // paint it later at on offseted position
161       if(plevel->bkgd_image[0] == '\0')
162         {
163           fillrect(base.x - scroll_x, base.y - scroll_y,
164                    32,32, 
165                    plevel->bkgd_top.red, plevel->bkgd_top.green, plevel->bkgd_top.blue, 0);
166 // FIXME: doesn't respect the gradient, futhermore is this necessary at all??
167         }
168       else
169         {
170           int s = ((int)scroll_x / 2)%640;
171           plevel->img_bkgd->draw_part(dest.x + s, dest.y, 
172                                       dest.x, dest.y,dest.w,dest.h);
173         }
174
175       Tile::draw(base.x - scroll_x,
176                  base.y - scroll_y + offset,
177                  shape);
178     }
179 }
180
181 void
182 FloatingScore::init(float x, float y, int s)
183 {
184   base.x = x;
185   base.y = y - 16;
186   timer.init(true);
187   timer.start(1000);
188   value = s;
189 }
190
191 void
192 FloatingScore::action(double frame_ratio)
193 {
194   base.y = base.y - 2 * frame_ratio;
195
196   if(!timer.check())
197     {
198       std::vector<FloatingScore*>::iterator i
199         = std::find(World::current()->floating_scores.begin(), 
200                     World::current()->floating_scores.end(), 
201                     this);
202       if (i != World::current()->floating_scores.end())
203         World::current()->floating_scores.erase(i);
204     }
205 }
206
207 void
208 FloatingScore::draw()
209 {
210   char str[10];
211   sprintf(str, "%d", value);
212   gold_text->draw(str, (int)base.x + 16 - strlen(str) * 8, (int)base.y, 1);
213 }
214
215 /* Trampoline */
216
217 #define TRAMPOLINE_FRAMES 4
218 Sprite *img_trampoline[TRAMPOLINE_FRAMES];
219
220 void load_object_gfx()
221 {
222   for (int i = 0; i < TRAMPOLINE_FRAMES; i++)
223   {
224     char sprite_name[16];
225     sprintf(sprite_name, "trampoline-%i", i+1);
226     img_trampoline[i] = sprite_manager->load(sprite_name);
227   }
228 }
229
230 void
231 Trampoline::init(float x, float y)
232 {
233   base.x = x;
234   base.y = y;
235
236   base.width = 32;
237   base.height = 32;
238
239   frame = 0;
240 }
241
242 void
243 Trampoline::draw()
244 {
245   img_trampoline[frame]->draw((int)base.x, (int)base.y);
246
247   frame = 0;
248
249   if (debug_mode)
250     fillrect(base.x - scroll_x, base.y - scroll_y, base.width, base.height, 75, 75, 0, 150);
251 }
252
253 void
254 Trampoline::action(double frame_ratio)
255 {
256   physic.apply(frame_ratio, base.x, base.y);
257
258   // Falling
259   if (issolid(base.x + base.width/2, base.y + base.height))
260   {
261     base.y = int((base.y + base.height)/32) * 32 - base.height;
262
263     physic.enable_gravity(false);
264     physic.set_velocity_y(0.0f);
265   }
266   else
267     physic.enable_gravity(true);
268
269 }
270
271 // TODO:
272 // If HELD
273 //   - move with tux
274 // If jumped on
275 //   - compress springs (reduce height)
276
277 void
278 Trampoline::collision(void *p_c_object, int c_object, CollisionType type)
279 {
280   Player* pplayer_c = NULL;
281   switch (c_object)
282   {
283     case CO_PLAYER:
284       pplayer_c = (Player*) p_c_object;
285
286       if (type == COLLISION_NORMAL)
287       {
288         // TODO: Pick up if HELD
289       }
290
291       else if (type == COLLISION_SQUISH)
292       {
293         // TODO: compress springs
294         // TODO: launch tux, if necessary
295
296         int squish_amount = (32 - (int)pplayer_c->base.y % 32);
297
298         if (squish_amount < 24)
299           frame = 3;
300         else if (squish_amount < 28)
301           frame = 2;
302         else if (squish_amount < 30)
303           frame = 1;
304         else
305           frame = 0;
306
307         if (squish_amount < 24)
308         {
309           pplayer_c->physic.set_velocity_y(8);
310         }
311       }
312
313       break;
314
315     default:
316       break;
317     
318   }
319 }
320
321 /* EOF */
322