Coins follow tilemaps or can be given paths
[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 "object/bouncy_coin.hpp"
21 #include "object/player.hpp"
22 #include "object/tilemap.hpp"
23 #include "supertux/level.hpp"
24 #include "supertux/object_factory.hpp"
25 #include "supertux/sector.hpp"
26
27 Coin::Coin(const Vector& pos)
28   : MovingSprite(pos, "images/objects/coin/coin.sprite", LAYER_TILES, COLGROUP_TOUCHABLE),
29     path(),
30     walker(),
31     offset(),
32     from_tilemap(false)
33 {
34   sound_manager->preload("sounds/coin.wav");
35 }
36
37 Coin::Coin(const Vector& pos, TileMap* tilemap)
38   : MovingSprite(pos, "images/objects/coin/coin.sprite", LAYER_TILES, COLGROUP_TOUCHABLE),
39     path(boost::shared_ptr<Path>(tilemap->get_path())),
40     walker(boost::shared_ptr<PathWalker>(tilemap->get_walker())),
41     offset(),
42     from_tilemap(true)
43 {
44   if(walker.get()) {
45     Vector v = path->get_base();
46     offset = pos - v;
47   }
48
49   sound_manager->preload("sounds/coin.wav");
50 }
51
52 Coin::Coin(const Reader& reader)
53   : MovingSprite(reader, "images/objects/coin/coin.sprite", LAYER_TILES, COLGROUP_TOUCHABLE),
54     path(),
55     walker(),
56     offset(),
57     from_tilemap(false)
58 {
59   const lisp::Lisp* pathLisp = reader.get_lisp("path");
60   if (pathLisp) {
61     path.reset(new Path());
62     path->read(*pathLisp);
63     walker.reset(new PathWalker(path.get()));
64     Vector v = path->get_base();
65     set_pos(v);
66   }
67
68   sound_manager->preload("sounds/coin.wav");
69 }
70
71 void
72 Coin::update(float elapsed_time)
73 {
74   // if we have a path to follow, follow it
75   if (walker.get()) {
76     Vector v = from_tilemap ? offset + walker->get_pos() : walker->advance(elapsed_time);
77     movement = v - get_pos();
78   }
79 }
80
81 void
82 Coin::collect()
83 {
84   // TODO: commented out musical code. Maybe fork this for a special "MusicalCoin" object?
85   /*
86     static Timer sound_timer;
87     static int pitch_one = 128;
88     static float last_pitch = 1;
89     float pitch = 1;
90
91     int tile = static_cast<int>(get_pos().y / 32);
92
93     if (!sound_timer.started()) {
94     pitch_one = tile;
95     pitch = 1;
96     last_pitch = 1;
97     }
98     else if (sound_timer.get_timegone() < 0.02) {
99     pitch = last_pitch;
100     }
101     else
102     {
103     switch ((pitch_one - tile) % 7) {
104     case -6:
105     pitch = 1.0/2;
106     break;
107     case -5:
108     pitch = 5.0/8;
109     break;
110     case -4:
111     pitch = 4.0/6;
112     break;
113     case -3:
114     pitch = 3.0/4;
115     break;
116     case -2:
117     pitch = 5.0/6;
118     break;
119     case -1:
120     pitch = 9.0/10;
121     break;
122     case 0:
123     pitch = 1.0;
124     break;
125     case 1:
126     pitch = 9.0/8;
127     break;
128     case 2:
129     pitch = 5.0/4;
130     break;
131     case 3:
132     pitch = 4.0/3;
133     break;
134     case 4:
135     pitch = 3.0/2;
136     break;
137     case 5:
138     pitch = 5.0/3;
139     break;
140     case 6:
141     pitch = 9.0/5;
142     break;
143     }
144     last_pitch = pitch;
145     }
146     sound_timer.start(1);
147
148     SoundSource* soundSource = sound_manager->create_sound_source("sounds/coin.wav");
149     soundSource->set_position(get_pos());
150     soundSource->set_pitch(pitch);
151     soundSource->play();
152     sound_manager->manage_source(soundSource);
153   */
154   Sector::current()->player->get_status()->add_coins(1);
155   Sector::current()->add_object(new BouncyCoin(get_pos()));
156   Sector::current()->get_level()->stats.coins++;
157   remove_me();
158 }
159
160 HitResponse
161 Coin::collision(GameObject& other, const CollisionHit& )
162 {
163   Player* player = dynamic_cast<Player*>(&other);
164   if(player == 0)
165     return ABORT_MOVE;
166
167   collect();
168   return ABORT_MOVE;
169 }
170
171 /* EOF */