1 //  SuperTux - Rusty Trampoline
2 //  Copyright (C) 2006 Wolfgang Becker <uafr@gmx.de>
3 //  Copyright (C) 2011 Jonas Kuemmerlin <rgcjonas@googlemail.com>
4 //
5 //  This program is free software: you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation, either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 #include "object/rusty_trampoline.hpp"
19 
20 #include "audio/sound_manager.hpp"
21 #include "badguy/walking_badguy.hpp"
22 #include "control/controller.hpp"
23 #include "object/player.hpp"
24 #include "sprite/sprite.hpp"
25 #include "util/reader_mapping.hpp"
26 
27 /* Trampoline will accelerate Tux to to VY_BOUNCE, if
28  * he jumps on it to VY_TRIGGER. */
29 namespace {
30 const std::string BOUNCE_SOUND = "sounds/trampoline.wav";
31 const float VY_TRIGGER = -900; //negative, upwards
32 const float VY_BOUNCE = -500;
33 }
34 
RustyTrampoline(const ReaderMapping & mapping)35 RustyTrampoline::RustyTrampoline(const ReaderMapping& mapping) :
36   Rock(mapping, "images/objects/rusty-trampoline/rusty-trampoline.sprite"),
37   portable(true), counter(3)
38 {
39   SoundManager::current()->preload(BOUNCE_SOUND);
40 
41   mapping.get("counter", counter);
42   mapping.get("portable", portable); //do we really need this?
43 }
44 
45 void
update(float dt_sec)46 RustyTrampoline::update(float dt_sec)
47 {
48   if (m_sprite->animation_done()) {
49     if (counter < 1) {
50       remove_me();
51     } else {
52       m_sprite->set_action("normal");
53     }
54 
55   }
56 
57   Rock::update(dt_sec);
58 }
59 
60 ObjectSettings
get_settings()61 RustyTrampoline::get_settings()
62 {
63   ObjectSettings result = Rock::get_settings();
64 
65   result.add_int(_("Counter"), &counter, "counter", 3);
66   result.add_bool(_("Portable"), &portable, "portable", true);
67 
68   result.reorder({"counter", "x", "y"});
69 
70   return result;
71 }
72 
73 HitResponse
collision(GameObject & other,const CollisionHit & hit)74 RustyTrampoline::collision(GameObject& other, const CollisionHit& hit)
75 {
76   //Trampoline has to be on ground to work.
77   if (on_ground) {
78     auto player = dynamic_cast<Player*> (&other);
79     //Trampoline works for player
80     if (player) {
81       float vy = player->get_physic().get_velocity_y();
82       //player is falling down on trampoline
83       if (hit.top && vy >= 0) {
84         if (player->get_controller().hold(Control::JUMP)) {
85           vy = VY_TRIGGER;
86         } else {
87           vy = VY_BOUNCE;
88         }
89         player->get_physic().set_velocity_y(vy);
90         SoundManager::current()->play(BOUNCE_SOUND);
91         counter--;
92         if (counter > 0) {
93           m_sprite->set_action("swinging", 1);
94         } else {
95           m_sprite->set_action("breaking", 1);
96         }
97 
98         return FORCE_MOVE;
99       }
100     }
101     auto walking_badguy = dynamic_cast<WalkingBadguy*> (&other);
102     //Trampoline also works for WalkingBadguy
103     if (walking_badguy) {
104       float vy = walking_badguy->get_velocity_y();
105       //walking_badguy is falling down on trampoline
106       if (hit.top && vy >= 0) {
107         vy = VY_BOUNCE;
108         walking_badguy->set_velocity_y(vy);
109         SoundManager::current()->play(BOUNCE_SOUND);
110         counter--;
111         if (counter > 0) {
112           m_sprite->set_action("swinging", 1);
113         } else {
114           m_sprite->set_action("breaking", 1);
115         }
116         return FORCE_MOVE;
117       }
118     }
119   }
120 
121   return Rock::collision(other, hit);
122 }
123 
124 void
collision_solid(const CollisionHit & hit)125 RustyTrampoline::collision_solid(const CollisionHit& hit) {
126   Rock::collision_solid(hit);
127 }
128 
129 void
grab(MovingObject & object,const Vector & pos,Direction dir)130 RustyTrampoline::grab(MovingObject& object, const Vector& pos, Direction dir) {
131   Rock::grab(object, pos, dir);
132 }
133 
134 void
ungrab(MovingObject & object,Direction dir)135 RustyTrampoline::ungrab(MovingObject& object, Direction dir) {
136   Rock::ungrab(object, dir);
137   m_sprite->set_action("breaking", 1);
138   counter = 0; //remove in update()
139 }
140 
141 bool
is_portable() const142 RustyTrampoline::is_portable() const
143 {
144   return Rock::is_portable() && portable;
145 }
146 
147 /* EOF */
148