Fake solid for trampoline.
[supertux.git] / src / object / trampoline.cpp
1 //  $Id$
2 //
3 //  SuperTux - Trampoline
4 //  Copyright (C) 2006 Wolfgang Becker <uafr@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 <config.h>
21
22 #include "trampoline.hpp"
23 #include "object_factory.hpp"
24 #include "player.hpp"
25 #include "audio/sound_manager.hpp"
26 #include "sprite/sprite_manager.hpp"
27
28 /* Trampoline will accelerate player to to VY_INITIAL, if 
29  * he jumps on it to VY_MIN. */
30 namespace {
31   const std::string TRAMPOLINE_SOUND = "sounds/trampoline.wav";
32   const float VY_MIN = -900; //negative, upwards
33   const float VY_INITIAL = -500;
34 }
35
36 Trampoline::Trampoline(const lisp::Lisp& lisp)
37         : MovingSprite(lisp, "images/objects/trampoline/trampoline.sprite" )
38 {
39   sound_manager->preload( TRAMPOLINE_SOUND );
40   flags |= FLAG_PORTABLE;
41   flags |= FLAG_SOLID;
42   physic.set_velocity(0, 0);
43   physic.enable_gravity(true);
44   on_ground = false;
45
46   bool portable = true;
47   //Check if this trampoline is not portable
48   if( lisp.get( "portable", portable ) ){
49     if( !portable ){
50         flags ^= FLAG_PORTABLE;
51         //we need another sprite
52         sprite_name = "images/objects/trampoline/trampoline_fix.sprite";
53         sprite = sprite_manager->create( sprite_name );
54         sprite->set_action("normal");
55     }
56   }
57 }
58
59 void
60 Trampoline::update( float elapsed_time ){
61     if( !on_ground ){
62         movement = physic.get_movement(elapsed_time);
63     }
64     if(sprite->animation_done()) {
65       sprite->set_action("normal");
66     }
67 }
68
69 HitResponse
70 Trampoline::collision(GameObject& other, const CollisionHit& hit )
71 {
72   //Tramponine has to be on ground to work.
73   if( !on_ground ){
74       return FORCE_MOVE;
75   }
76   Player* player = dynamic_cast<Player*> (&other);
77   if ( player ) {
78     float vy = player->physic.get_velocity_y();
79     //player is falling down on trampoline
80     if(hit.top && vy > 0) {
81       if(player->get_controller()->hold(Controller::JUMP)) { 
82         vy = VY_MIN;
83       } else {
84         vy = VY_INITIAL;
85       }
86       player->physic.set_velocity_y( vy );
87       sound_manager->play( TRAMPOLINE_SOUND );
88       sprite->set_action("swinging", 1);
89       return FORCE_MOVE;
90     }
91   }
92   //Fake being solid for moving_object. 
93   MovingObject* moving_object = dynamic_cast<MovingObject*> (&other);
94   if( moving_object ){
95       CollisionHit hit_other = hit;
96       std::swap(hit_other.left, hit_other.right);
97       std::swap(hit_other.top, hit_other.bottom);
98       moving_object->collision_solid( hit_other );
99   }
100   return FORCE_MOVE;
101 }
102
103 void 
104 Trampoline::collision_solid( const CollisionHit& hit ){
105   if( hit.bottom ){
106      on_ground = true;
107   }
108
109
110 void
111 Trampoline::grab( MovingObject&, const Vector& pos, Direction ){
112   movement = pos - get_pos();
113   set_group( COLGROUP_DISABLED );
114   on_ground = true;
115   sprite->set_animation_loops( 0 );
116 }
117
118 void
119 Trampoline::ungrab(MovingObject& , Direction ){
120   set_group( COLGROUP_MOVING );
121   on_ground = false;
122   physic.set_velocity(0, 0);
123 }
124
125
126 IMPLEMENT_FACTORY(Trampoline, "trampoline");