3c04c05ee2839810470d6f985ef1043c97d3d710
[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 "world.h"
23 #include "tile.h"
24 #include "gameloop.h"
25 #include "gameobjs.h"
26 #include "sprite_manager.h"
27 #include "resources.h"
28
29 void
30 BouncyDistro::init(float x, float y)
31 {
32   base.x = x;
33   base.y = y;
34   base.ym = -2;
35 }
36
37 void
38 BouncyDistro::action(double frame_ratio)
39 {
40   base.y = base.y + base.ym * frame_ratio;
41
42   base.ym += 0.1 * frame_ratio;
43
44   if (base.ym >= 0)
45     {
46       std::vector<BouncyDistro*>::iterator i
47         = std::find(World::current()->bouncy_distros.begin(), 
48                     World::current()->bouncy_distros.end(), 
49                     this);
50       if (i != World::current()->bouncy_distros.end())
51         World::current()->bouncy_distros.erase(i);
52     }
53 }
54
55 void
56 BouncyDistro::draw()
57 {
58   img_distro[0]->draw(base.x - scroll_x,
59                       base.y - scroll_y);
60 }
61
62
63 void
64 BrokenBrick::init(Tile* tile_, float x, float y, float xm, float ym)
65 {
66   tile    = tile_;
67   base.x  = x;
68   base.y  = y;
69   base.xm = xm;
70   base.ym = ym;
71
72   timer.init(true);
73   timer.start(200);
74 }
75
76 void
77 BrokenBrick::action(double frame_ratio)
78 {
79   base.x = base.x + base.xm * frame_ratio;
80   base.y = base.y + base.ym * frame_ratio;
81
82   if (!timer.check())
83     {
84       std::vector<BrokenBrick*>::iterator i
85         = std::find(World::current()->broken_bricks.begin(), 
86                     World::current()->broken_bricks.end(), 
87                     this);
88       if (i != World::current()->broken_bricks.end())
89         World::current()->broken_bricks.erase(i);
90     }
91 }
92
93 void
94 BrokenBrick::draw()
95 {
96   SDL_Rect src, dest;
97   src.x = rand() % 16;
98   src.y = rand() % 16;
99   src.w = 16;
100   src.h = 16;
101
102   dest.x = (int)(base.x - scroll_x);
103   dest.y = (int)(base.y  - scroll_y);
104   dest.w = 16;
105   dest.h = 16;
106   
107   if (tile->images.size() > 0)
108     tile->images[0]->draw_part(src.x,src.y,dest.x,dest.y,dest.w,dest.h);
109 }
110
111 void
112 BouncyBrick::init(float x, float y)
113 {
114   base.x   = x;
115   base.y   = y;
116   offset   = 0;
117   offset_m = -BOUNCY_BRICK_SPEED;
118   shape    = World::current()->get_level()->gettileid(x, y);
119 }
120
121 void
122 BouncyBrick::action(double frame_ratio)
123 {
124   offset = (offset + offset_m * frame_ratio);
125
126   /* Go back down? */
127   if (offset < -BOUNCY_BRICK_MAX_OFFSET)
128     offset_m = BOUNCY_BRICK_SPEED;
129
130
131   /* Stop bouncing? */
132   if (offset >= 0)
133     {
134       std::vector<BouncyBrick*>::iterator i
135         = std::find(World::current()->bouncy_bricks.begin(), 
136                     World::current()->bouncy_bricks.end(), 
137                     this);
138       if (i != World::current()->bouncy_bricks.end())
139         World::current()->bouncy_bricks.erase(i);
140     }
141 }
142
143 void
144 BouncyBrick::draw()
145 {
146   SDL_Rect dest;
147   
148   if (base.x >= scroll_x - 32 &&
149       base.x <= scroll_x + screen->w)
150     {
151       dest.x = (int)(base.x - scroll_x);
152       dest.y = (int)(base.y - scroll_y);
153       dest.w = 32;
154       dest.h = 32;
155
156       Level* plevel = World::current()->get_level();
157
158       // FIXME: overdrawing hack to clean the tile from the screen to
159       // paint it later at on offseted position
160       if(plevel->bkgd_image[0] == '\0')
161         {
162           fillrect(base.x - scroll_x, base.y - scroll_y,
163                    32,32, 
164                    plevel->bkgd_top.red, plevel->bkgd_top.green, plevel->bkgd_top.blue, 0);
165 // FIXME: doesn't respect the gradient, futhermore is this necessary at all??
166         }
167       else
168         {
169           int s = ((int)scroll_x / 2)%640;
170           plevel->img_bkgd->draw_part(dest.x + s, dest.y, 
171                                       dest.x, dest.y,dest.w,dest.h);
172         }
173
174       Tile::draw(base.x - scroll_x,
175                  base.y - scroll_y + offset,
176                  shape);
177     }
178 }
179
180 void
181 FloatingScore::init(float x, float y, int s)
182 {
183   base.x = x;
184   base.y = y - 16;
185   timer.init(true);
186   timer.start(1000);
187   value = s;
188 }
189
190 void
191 FloatingScore::action(double frame_ratio)
192 {
193   base.y = base.y - 2 * frame_ratio;
194
195   if(!timer.check())
196     {
197       std::vector<FloatingScore*>::iterator i
198         = std::find(World::current()->floating_scores.begin(), 
199                     World::current()->floating_scores.end(), 
200                     this);
201       if (i != World::current()->floating_scores.end())
202         World::current()->floating_scores.erase(i);
203     }
204 }
205
206 void
207 FloatingScore::draw()
208 {
209   char str[10];
210   sprintf(str, "%d", value);
211   gold_text->draw(str, (int)base.x + 16 - strlen(str) * 8, (int)base.y, 1);
212 }
213
214 /* Trampoline */
215
216 #define TRAMPOLINE_FRAMES 4
217 Sprite *img_trampoline[TRAMPOLINE_FRAMES];
218
219 void load_trampoline_gfx()
220 {
221   for (int i = 0; i < TRAMPOLINE_FRAMES; i++)
222   {
223     char sprite_name[16];
224     sprintf(sprite_name, "trampoline-%i", i+1);
225     img_trampoline[0] = sprite_manager->load(sprite_name);
226   }
227 }
228
229 void
230 Trampoline::init(float x, float y)
231 {
232   base.x = x;
233   base.y = y;
234 }
235
236 void
237 Trampoline::action(double frame_ratio)
238 {
239   (void) frame_ratio;
240   // TODO:
241   // If HELD
242   //   - move with tux
243   // If jumped on
244   //   - compress springs (reduce height)
245 }
246
247 void
248 Trampoline::draw()
249 {
250   img_trampoline[0]->draw((int)base.x, (int)base.y);
251 }
252
253
254 /* EOF */
255