4 // Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
5 // Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
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.
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.
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
27 #include "app/globals.h"
29 #include "tile_manager.h"
32 #include "special/sprite_manager.h"
33 #include "resources.h"
36 #include "video/drawing_context.h"
39 BouncyCoin::BouncyCoin(const Vector& pos)
43 sprite = sprite_manager->create("coin");
44 sprite->set_action("still");
47 BouncyCoin::~BouncyCoin()
53 BouncyCoin::action(float elapsed_time)
55 position.y += -200 * elapsed_time;
62 BouncyCoin::draw(DrawingContext& context)
64 sprite->draw(context, position, LAYER_OBJECTS);
67 //---------------------------------------------------------------------------
69 BrokenBrick::BrokenBrick(Sprite* nsprite,
70 const Vector& pos, const Vector& nmovement)
71 : sprite(new Sprite(*nsprite)), position(pos), movement(nmovement)
76 BrokenBrick::~BrokenBrick()
82 BrokenBrick::action(float elapsed_time)
84 position += movement * elapsed_time;
91 BrokenBrick::draw(DrawingContext& context)
93 sprite->draw_part(context,
94 Vector(rand() % 16, rand() % 16), Vector(16, 16),
95 position, LAYER_OBJECTS + 1);
98 //---------------------------------------------------------------------------
100 FloatingText::FloatingText(const Vector& pos, const std::string& text_)
101 : position(pos), text(text_)
104 position.x -= text.size() * 8;
107 FloatingText::FloatingText(const Vector& pos, int score)
112 // turn int into a string
114 snprintf(str, 10, "%d", score);
117 position.x -= text.size() * 8;
121 FloatingText::action(float elapsed_time)
123 position.y -= 1.4 * elapsed_time;
129 #define FADING_TIME .350
132 FloatingText::draw(DrawingContext& context)
134 // make an alpha animation when disapearing
136 if(timer.get_timeleft() < FADING_TIME)
137 alpha = int(timer.get_timeleft() * 255 / FADING_TIME);
141 context.push_transform();
142 context.set_alpha(alpha);
144 context.draw_text(gold_text, text, position, LEFT_ALLIGN, LAYER_OBJECTS+1);
146 context.pop_transform();
152 Sprite *img_trampoline;
154 Trampoline::Trampoline(LispReader& reader)
156 reader.read_float("x", base.x);
157 reader.read_float("y", base.y);
161 reader.read_float("power", power);
168 Trampoline::Trampoline(float x, float y)
182 Trampoline::write(LispWriter& writer)
184 writer.start_list("trampoline");
186 writer.write_float("x", base.x);
187 writer.write_float("y", base.y);
188 writer.write_float("power", power);
190 writer.end_list("trampoline");
194 Trampoline::draw(DrawingContext& context)
196 img_trampoline->set_frame(frame);
197 img_trampoline->draw(context, base, LAYER_OBJECTS);
202 Trampoline::action(float frame_ratio)
204 // TODO: Remove if we're too far off the screen
209 if (issolid(base.x + base.width/2, base.y + base.height))
211 base.y = int((base.y + base.height)/32) * 32 - base.height;
213 physic.enable_gravity(false);
214 physic.set_velocity_y(0.0f);
216 physic.set_velocity_x(0);
220 physic.enable_gravity(true);
223 else // Player is carrying us around
225 /* FIXME: The trampoline object shouldn't know about pplayer objects. */
226 /* If we're holding the iceblock */
227 Player& tux = *Sector::current()->player;
228 Direction dir = tux.dir;
232 base.x = tux.base.x + 16;
233 base.y = tux.base.y + tux.base.height/1.5 - base.height;
235 else /* facing left */
237 base.x = tux.base.x - 16;
238 base.y = tux.base.y + tux.base.height/1.5 - base.height;
241 if(collision_object_map(base))
244 base.y = tux.base.y + tux.base.height/1.5 - base.height;
248 physic.apply(frame_ratio, base.x, base.y, Sector::current()->gravity);
249 collision_swept_object_map(&old_base, &base);
253 Trampoline::collision(const MovingObject&, int)
259 Trampoline::collision(void *p_c_object, int c_object, CollisionType type)
261 Player* pplayer_c = NULL;
265 pplayer_c = (Player*) p_c_object;
267 if (type == COLLISION_NORMAL)
269 // Pick up if HELD (done in Player)
272 else if (type == COLLISION_SQUISH)
274 int squish_amount = (32 - (int)pplayer_c->base.y % 32);
276 if (squish_amount < 24)
278 else if (squish_amount < 28)
280 else if (squish_amount < 30)
285 if (squish_amount < 20) {
286 pplayer_c->physic.set_velocity_y(power);
287 pplayer_c->fall_mode = Player::TRAMPOLINE_JUMP;
289 else if (pplayer_c->physic.get_velocity_y() < 0)
290 pplayer_c->physic.set_velocity_y(-squish_amount/32);
302 /* Flying Platform */
305 Sprite *img_flying_platform;
307 FlyingPlatform::FlyingPlatform(LispReader& reader)
309 reader.read_int_vector("x", pos_x);
310 reader.read_int_vector("y", pos_y);
313 reader.read_float("velocity", velocity);
323 float x = pos_x[point+1] - pos_x[point];
324 float y = pos_y[point+1] - pos_y[point];
325 vel_x = x*velocity / sqrt(x*x + y*y);
326 vel_y = -(velocity - vel_x);
331 FlyingPlatform::FlyingPlatform(int x, int y)
340 FlyingPlatform::write(LispWriter& writer)
342 writer.start_list("flying-trampoline");
344 writer.write_int_vector("x", pos_x);
345 writer.write_int_vector("y", pos_y);
346 writer.write_float("velocity", velocity);
348 writer.end_list("flying-trampoline");
352 FlyingPlatform::draw(DrawingContext& context)
354 img_flying_platform->draw(context, base, LAYER_OBJECTS);
358 FlyingPlatform::action(float frame_ratio)
360 // TODO: Remove if we're too far off the screen
365 if((unsigned)point+1 != pos_x.size())
367 if(((pos_x[point+1] > pos_x[point] && base.x >= pos_x[point+1]) ||
368 (pos_x[point+1] < pos_x[point] && base.x <= pos_x[point+1]) ||
369 pos_x[point] == pos_x[point+1]) &&
370 ((pos_y[point+1] > pos_y[point] && base.y >= pos_y[point+1]) ||
371 (pos_y[point+1] < pos_y[point] && base.y <= pos_y[point+1]) ||
372 pos_y[point] == pos_y[point+1]))
376 float x = pos_x[point+1] - pos_x[point];
377 float y = pos_y[point+1] - pos_y[point];
378 vel_x = x*velocity / sqrt(x*x + y*y);
379 vel_y = -(velocity - vel_x);
389 if(pos_x[point+1] > base.x)
390 base.x += velocity * frame_ratio;
391 else if(pos_x[point+1] < base.x)
392 base.x -= velocity * frame_ratio;
394 if(pos_y[point+1] > base.y)
395 base.y += velocity * frame_ratio;
396 else if(pos_y[point+1] < base.y)
397 base.y -= velocity * frame_ratio;
400 base.x += vel_x * frame_ratio;
401 base.y += vel_y * frame_ratio;
405 FlyingPlatform::collision(const MovingObject&, int)
411 FlyingPlatform::collision(void *p_c_object, int c_object, CollisionType type)
416 // Player* pplayer_c = NULL;
420 // pplayer_c = (Player*) p_c_object;
432 Sprite *img_smoke_cloud = 0;
434 SmokeCloud::SmokeCloud(const Vector& pos)
441 SmokeCloud::action(float elapsed_time)
443 position.y -= 120 * elapsed_time;
450 SmokeCloud::draw(DrawingContext& context)
452 img_smoke_cloud->draw(context, position, LAYER_OBJECTS+1);
455 Particles::Particles(const Vector& epicenter, int min_angle, int max_angle, const Vector& initial_velocity, const Vector& acceleration, int number, Color color_, int size_, int life_time, int drawing_layer_)
456 : accel(acceleration), color(color_), size(size_), drawing_layer(drawing_layer_)
461 live_forever = false;
462 timer.start(life_time);
466 for(int p = 0; p < number; p++)
468 Particle* particle = new Particle;
469 particle->pos = epicenter;
471 float angle = ((rand() % (max_angle-min_angle))+min_angle)
472 * (M_PI / 180); // convert to radius
473 particle->vel.x = /*fabs*/(sin(angle)) * initial_velocity.x;
474 // if(angle >= M_PI && angle < M_PI*2)
475 // particle->vel.x *= -1; // work around to fix signal
476 particle->vel.y = /*fabs*/(cos(angle)) * initial_velocity.y;
477 // if(angle >= M_PI_2 && angle < 3*M_PI_2)
478 // particle->vel.y *= -1;
480 particles.push_back(particle);
484 Particles::~Particles()
487 for(std::vector<Particle*>::iterator i = particles.begin();
488 i < particles.end(); i++)
493 Particles::action(float elapsed_time)
495 Vector camera = Sector::current()->camera->get_translation();
498 for(std::vector<Particle*>::iterator i = particles.begin();
499 i != particles.end(); ) {
500 (*i)->pos.x += (*i)->vel.x * elapsed_time;
501 (*i)->pos.y += (*i)->vel.y * elapsed_time;
503 (*i)->vel.x += accel.x * elapsed_time;
504 (*i)->vel.y += accel.y * elapsed_time;
506 if((*i)->pos.x < camera.x || (*i)->pos.x > screen->w + camera.x ||
507 (*i)->pos.y < camera.y || (*i)->pos.y > screen->h + camera.y) {
509 i = particles.erase(i);
515 if((timer.check() && !live_forever) || particles.size() == 0)
520 Particles::draw(DrawingContext& context)
523 for(std::vector<Particle*>::iterator i = particles.begin();
524 i != particles.end(); i++) {
525 context.draw_filled_rect((*i)->pos, Vector(size,size), color,drawing_layer);
529 void load_object_gfx()
532 img_trampoline = sprite_manager->load("trampoline");
533 img_trampoline->start_animation(0);
534 img_flying_platform = sprite_manager->load("flying_platform");
536 img_smoke_cloud = sprite_manager->create("stomp");
539 void free_object_gfx()
541 delete img_smoke_cloud;