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