Move patch to another directory
[supertux.git] / src / object / coin.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.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/coin.hpp"
18
19 #include "audio/sound_manager.hpp"
20 #include "util/reader.hpp"
21 #include "object/bouncy_coin.hpp"
22 #include "object/player.hpp"
23 #include "object/tilemap.hpp"
24 #include "supertux/level.hpp"
25 #include "supertux/object_factory.hpp"
26 #include "supertux/sector.hpp"
27
28 Coin::Coin(const Vector& pos)
29   : MovingSprite(pos, "images/objects/coin/coin.sprite", LAYER_OBJECTS - 1, COLGROUP_TOUCHABLE),
30     path(),
31     walker(),
32     offset(),
33     from_tilemap(false),
34     physic()
35 {
36   SoundManager::current()->preload("sounds/coin.wav");
37 }
38
39 Coin::Coin(const Vector& pos, TileMap* tilemap)
40   : MovingSprite(pos, "images/objects/coin/coin.sprite", LAYER_OBJECTS - 1, COLGROUP_TOUCHABLE),
41     path(std::shared_ptr<Path>(tilemap->get_path())),
42     walker(std::shared_ptr<PathWalker>(tilemap->get_walker())),
43     offset(),
44     from_tilemap(true),
45     physic()
46 {
47   if(walker.get()) {
48     Vector v = path->get_base();
49     offset = pos - v;
50   }
51
52   SoundManager::current()->preload("sounds/coin.wav");
53 }
54
55 Coin::Coin(const Reader& reader)
56   : MovingSprite(reader, "images/objects/coin/coin.sprite", LAYER_OBJECTS - 1, COLGROUP_TOUCHABLE),
57     path(),
58     walker(),
59     offset(),
60     from_tilemap(false),
61     physic()
62 {
63   const lisp::Lisp* pathLisp = reader.get_lisp("path");
64   if (pathLisp) {
65     path.reset(new Path());
66     path->read(*pathLisp);
67     walker.reset(new PathWalker(path.get()));
68     Vector v = path->get_base();
69     set_pos(v);
70   }
71
72   SoundManager::current()->preload("sounds/coin.wav");
73 }
74
75 void
76 Coin::update(float elapsed_time)
77 {
78   // if we have a path to follow, follow it
79   if (walker.get()) {
80     Vector v = from_tilemap ? offset + walker->get_pos() : walker->advance(elapsed_time);
81     movement = v - get_pos();
82   }
83 }
84
85 void
86 Coin::collect()
87 {
88   // TODO: commented out musical code. Maybe fork this for a special "MusicalCoin" object?
89   /*
90     static Timer sound_timer;
91     static int pitch_one = 128;
92     static float last_pitch = 1;
93     float pitch = 1;
94
95     int tile = static_cast<int>(get_pos().y / 32);
96
97     if (!sound_timer.started()) {
98     pitch_one = tile;
99     pitch = 1;
100     last_pitch = 1;
101     }
102     else if (sound_timer.get_timegone() < 0.02) {
103     pitch = last_pitch;
104     }
105     else
106     {
107     switch ((pitch_one - tile) % 7) {
108     case -6:
109     pitch = 1.0/2;
110     break;
111     case -5:
112     pitch = 5.0/8;
113     break;
114     case -4:
115     pitch = 4.0/6;
116     break;
117     case -3:
118     pitch = 3.0/4;
119     break;
120     case -2:
121     pitch = 5.0/6;
122     break;
123     case -1:
124     pitch = 9.0/10;
125     break;
126     case 0:
127     pitch = 1.0;
128     break;
129     case 1:
130     pitch = 9.0/8;
131     break;
132     case 2:
133     pitch = 5.0/4;
134     break;
135     case 3:
136     pitch = 4.0/3;
137     break;
138     case 4:
139     pitch = 3.0/2;
140     break;
141     case 5:
142     pitch = 5.0/3;
143     break;
144     case 6:
145     pitch = 9.0/5;
146     break;
147     }
148     last_pitch = pitch;
149     }
150     sound_timer.start(1);
151
152     SoundSource* soundSource = SoundManager::current()->create_sound_source("sounds/coin.wav");
153     soundSource->set_position(get_pos());
154     soundSource->set_pitch(pitch);
155     soundSource->play();
156     SoundManager::current()->manage_source(soundSource);
157   */
158   Sector::current()->player->get_status()->add_coins(1);
159   Sector::current()->add_object(std::make_shared<BouncyCoin>(get_pos()));
160   Sector::current()->get_level()->stats.coins++;
161   remove_me();
162 }
163
164 HitResponse
165 Coin::collision(GameObject& other, const CollisionHit& )
166 {
167   Player* player = dynamic_cast<Player*>(&other);
168   if(player == 0)
169     return ABORT_MOVE;
170
171   collect();
172   return ABORT_MOVE;
173 }
174
175 /* The following defines a coin subject to gravity */
176 HeavyCoin::HeavyCoin(const Vector& pos, const Vector& init_velocity)
177   : Coin(pos),
178   physic()
179 {
180   physic.enable_gravity(true);
181   SoundManager::current()->preload("sounds/coin2.ogg");
182   set_group(COLGROUP_MOVING);
183   physic.set_velocity(init_velocity);
184 }
185
186 HeavyCoin::HeavyCoin(const Reader& reader)
187   : Coin(reader),
188   physic()
189 {
190   physic.enable_gravity(true);
191   SoundManager::current()->preload("sounds/coin2.ogg");
192   set_group(COLGROUP_MOVING);
193 }
194
195 void
196 HeavyCoin::update(float elapsed_time)
197 {
198   // enable physics
199   movement = physic.get_movement(elapsed_time);
200 }
201
202 void
203 HeavyCoin::collision_solid(const CollisionHit& hit)
204 {
205   int clink_threshold = 100; // sets the minimum speed needed to result in collision noise
206   //TODO: colliding HeavyCoins should have their own unique sound
207
208   if(hit.bottom) {
209     if(physic.get_velocity_y() > clink_threshold)
210       SoundManager::current()->play("sounds/coin2.ogg");
211     if(physic.get_velocity_y() > 200) {// lets some coins bounce
212       physic.set_velocity_y(-99);
213     }else{
214       physic.set_velocity_y(0);
215       physic.set_velocity_x(0);
216     }
217   }
218   if(hit.right || hit.left) {
219     if(physic.get_velocity_x() > clink_threshold || physic.get_velocity_x() < clink_threshold)
220       SoundManager::current()->play("sounds/coin2.ogg");
221     physic.set_velocity_x(-physic.get_velocity_x());
222   }
223   if(hit.top) {
224     if(physic.get_velocity_y() < clink_threshold)
225       SoundManager::current()->play("sounds/coin2.ogg");
226     physic.set_velocity_y(-physic.get_velocity_y());
227   }
228 }
229
230 /* EOF */