moved some sprites to separate files
[supertux.git] / src / object / 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 <config.h>
22
23 #include <algorithm>
24 #include <iostream>
25 #include <cmath>
26
27 #include "tile.hpp"
28 #include "tile_manager.hpp"
29 #include "game_session.hpp"
30 #include "gameobjs.hpp"
31 #include "sprite/sprite_manager.hpp"
32 #include "sprite/sprite.hpp"
33 #include "resources.hpp"
34 #include "sector.hpp"
35 #include "tilemap.hpp"
36 #include "video/drawing_context.hpp"
37 #include "camera.hpp"
38 #include "main.hpp"
39
40 BouncyCoin::BouncyCoin(const Vector& pos)
41   : position(pos)
42 {
43   timer.start(.3);
44   sprite = sprite_manager->create("coin");
45   sprite->set_action("still");
46 }
47
48 BouncyCoin::~BouncyCoin()
49 {
50   delete sprite;
51 }
52
53 void
54 BouncyCoin::update(float elapsed_time)
55 {
56   position.y += -200 * elapsed_time;
57
58   if(timer.check())
59     remove_me();
60 }
61
62 void
63 BouncyCoin::draw(DrawingContext& context)
64 {
65   sprite->draw(context, position, LAYER_OBJECTS);
66 }
67
68 //---------------------------------------------------------------------------
69
70 BrokenBrick::BrokenBrick(Sprite* nsprite,
71     const Vector& pos, const Vector& nmovement)
72   : sprite(new Sprite(*nsprite)), position(pos), movement(nmovement)
73 {
74   timer.start(.2);
75 }
76
77 BrokenBrick::~BrokenBrick()
78 {
79   delete sprite;
80 }
81
82 void
83 BrokenBrick::update(float elapsed_time)
84 {
85   position += movement * elapsed_time;
86
87   if (timer.check())
88     remove_me();
89 }
90
91 void
92 BrokenBrick::draw(DrawingContext& context)
93 {
94   sprite->draw_part(context,
95       Vector(rand() % 16, rand() % 16), Vector(16, 16),
96       position, LAYER_OBJECTS + 1);
97 }
98
99 //---------------------------------------------------------------------------
100
101 FloatingText::FloatingText(const Vector& pos, const std::string& text_)
102   : position(pos), text(text_)
103 {
104   timer.start(.1);
105   position.x -= text.size() * 8;
106 }
107
108 FloatingText::FloatingText(const Vector& pos, int score)
109   : position(pos)
110 {
111   timer.start(.1);
112
113   // turn int into a string
114   char str[10];
115   snprintf(str, 10, "%d", score);
116   text = str;
117
118   position.x -= text.size() * 8;
119 }
120
121 void
122 FloatingText::update(float elapsed_time)
123 {
124   position.y -= 1.4 * elapsed_time;
125
126   if(timer.check())
127     remove_me();
128 }
129
130 #define FADING_TIME .350
131
132 void
133 FloatingText::draw(DrawingContext& context)
134 {
135   // make an alpha animation when disapearing
136   int alpha;
137   if(timer.get_timeleft() < FADING_TIME)
138     alpha = int(timer.get_timeleft() * 255 / FADING_TIME);
139   else
140     alpha = 255;
141
142   context.push_transform();
143   context.set_alpha(alpha);
144
145   context.draw_text(gold_text, text, position, LEFT_ALLIGN, LAYER_OBJECTS+1);
146
147   context.pop_transform();
148 }
149
150 Sprite *img_smoke_cloud = 0;
151
152 SmokeCloud::SmokeCloud(const Vector& pos)
153   : position(pos)
154 {
155   timer.start(.3);
156 }
157
158 void
159 SmokeCloud::update(float elapsed_time)
160 {
161   position.y -= 120 * elapsed_time;
162
163   if(timer.check())
164     remove_me();
165 }
166
167 void
168 SmokeCloud::draw(DrawingContext& context)
169 {
170   img_smoke_cloud->draw(context, position, LAYER_OBJECTS+1);
171 }
172
173 Particles::Particles(const Vector& epicenter, int min_angle, int max_angle,
174         const Vector& initial_velocity, const Vector& acceleration, int number,
175         Color color_, int size_, float life_time, int drawing_layer_)
176   : accel(acceleration), color(color_), size(size_), drawing_layer(drawing_layer_)
177 {
178   if(life_time == 0) {
179     live_forever = true;
180   } else {
181     live_forever = false;
182     timer.start(life_time);
183   }
184
185   // create particles
186   for(int p = 0; p < number; p++)
187     {
188     Particle* particle = new Particle;
189     particle->pos = epicenter;
190
191     float angle = ((rand() % (max_angle-min_angle))+min_angle)
192                       * (M_PI / 180);  // convert to radius
193     particle->vel.x = /*fabs*/(sin(angle)) * initial_velocity.x;
194 //    if(angle >= M_PI && angle < M_PI*2)
195 //      particle->vel.x *= -1;  // work around to fix signal
196     particle->vel.y = /*fabs*/(cos(angle)) * initial_velocity.y;
197 //    if(angle >= M_PI_2 && angle < 3*M_PI_2)
198 //      particle->vel.y *= -1;
199
200     particles.push_back(particle);
201     }
202 }
203
204 Particles::~Particles()
205 {
206   // free particles
207   for(std::vector<Particle*>::iterator i = particles.begin();
208       i < particles.end(); i++)
209     delete (*i);
210 }
211
212 void
213 Particles::update(float elapsed_time)
214 {
215   Vector camera = Sector::current()->camera->get_translation();
216
217   // update particles
218   for(std::vector<Particle*>::iterator i = particles.begin();
219       i != particles.end(); ) {
220     (*i)->pos.x += (*i)->vel.x * elapsed_time;
221     (*i)->pos.y += (*i)->vel.y * elapsed_time;
222
223     (*i)->vel.x += accel.x * elapsed_time;
224     (*i)->vel.y += accel.y * elapsed_time;
225
226     if((*i)->pos.x < camera.x || (*i)->pos.x > SCREEN_WIDTH + camera.x ||
227        (*i)->pos.y < camera.y || (*i)->pos.y > SCREEN_HEIGHT + camera.y) {
228       delete (*i);
229       i = particles.erase(i);
230     } else {
231       ++i;
232     }
233   }
234
235   if((timer.check() && !live_forever) || particles.size() == 0)
236     remove_me();
237 }
238
239 void
240 Particles::draw(DrawingContext& context)
241 {
242   // draw particles
243   for(std::vector<Particle*>::iterator i = particles.begin();
244       i != particles.end(); i++) {
245     context.draw_filled_rect((*i)->pos, Vector(size,size), color,drawing_layer);
246   }
247 }
248
249 void load_object_gfx()
250 {
251 #if 0
252   img_trampoline = sprite_manager->load("trampoline");
253   img_trampoline->start_animation(0);
254   img_flying_platform = sprite_manager->load("flying_platform");
255 #endif
256   img_smoke_cloud = sprite_manager->create("stomp");
257 }
258
259 void free_object_gfx()
260 {
261   delete img_smoke_cloud;
262 }
263