287d0552524e87c11023aec2affa9fa8af45decd
[supertux.git] / src / worldmap.h
1 //  $Id$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2004 Ingo Ruhnke <grumbel@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 #ifndef SUPERTUX_WORLDMAP_H
21 #define SUPERTUX_WORLDMAP_H
22
23 #include <vector>
24 #include <string>
25
26 #include "math/vector.h"
27 #include "audio/musicref.h"
28 #include "video/screen.h"
29 #include "statistics.h"
30 #include "special/timer.h"
31
32 extern Menu* worldmap_menu;
33
34 namespace WorldMapNS {
35
36 enum WorldMapMenuIDs {
37   MNID_RETURNWORLDMAP,
38   MNID_QUITWORLDMAP
39   };
40
41 // For one way tiles
42 enum {
43   BOTH_WAYS,
44   NORTH_SOUTH_WAY,
45   SOUTH_NORTH_WAY,
46   EAST_WEST_WAY,
47   WEST_EAST_WAY
48   };
49
50 class Tile
51 {
52 public:
53   Tile();
54   ~Tile();
55
56   void draw(DrawingContext& context, Vector pos);
57
58   std::vector<Surface*> images;
59   int anim_speed;
60
61   // Directions in which Tux is allowed to walk from this tile
62   bool north;
63   bool east;
64   bool south;
65   bool west;
66
67   /** One way tile */
68   int one_way;
69
70   /** Stop on this tile or walk over it? */
71   bool stop;
72
73   /** When set automatically turn directions when walked over such a
74       tile (ie. walk smoothly a curve) */
75   bool auto_walk;
76 };
77
78 class TileManager
79 {
80 private:
81   typedef std::vector<Tile*> Tiles;
82   Tiles tiles;
83
84 public:
85   TileManager();
86   ~TileManager();
87
88   Tile* get(int i);
89 };
90
91 enum Direction { D_NONE, D_WEST, D_EAST, D_NORTH, D_SOUTH };
92
93 std::string direction_to_string(Direction d);
94 Direction   string_to_direction(const std::string& d);
95 Direction reverse_dir(Direction d);
96
97 class WorldMap;
98
99 class Tux
100 {
101 public:
102   Direction back_direction;
103 private:
104   WorldMap* worldmap;
105   Surface* largetux_sprite;
106   Surface* firetux_sprite;
107   Surface* smalltux_sprite;
108
109   Direction input_direction;
110   Direction direction;
111   Vector tile_pos;
112   /** Length by which tux is away from its current tile, length is in
113       input_direction direction */
114   float offset;
115   bool  moving;
116
117   void stop();
118 public: 
119   Tux(WorldMap* worldmap_);
120   ~Tux();
121   
122   void draw(DrawingContext& context, const Vector& offset);
123   void action(float elapsed_time);
124
125   void set_direction(Direction dir);
126
127   bool is_moving() const { return moving; }
128   Vector get_pos();
129   Vector get_tile_pos() const { return tile_pos; } 
130   void  set_tile_pos(Vector p) { tile_pos = p; } 
131 };
132
133 /** */
134 class WorldMap
135 {
136 private:
137   Tux* tux;
138
139   bool quit;
140
141   Surface* leveldot_green;
142   Surface* leveldot_red;
143   Surface* messagedot;
144   Surface* teleporterdot;
145
146   std::string name;
147   std::string music;
148
149   std::vector<int> tilemap;
150   int width;
151   int height;
152   
153   int start_x;
154   int start_y;
155
156   TileManager* tile_manager;
157
158 public:
159   struct SpecialTile
160   {
161     int x;
162     int y;
163     std::string level_name;
164     std::string title;
165     bool solved;
166
167     /** Statistics for level tiles */
168     Statistics statistics;
169
170     /** Optional flags: */
171
172     /** Check if this level should be vertically flipped */
173     bool vertical_flip;
174
175     /** Filename of the extro text to show once the level is
176         successfully completed */
177     std::string extro_filename;
178
179     /** Position to swap to player */
180     int teleport_dest_x, teleport_dest_y;
181
182     /** Message to show in the Map */
183     std::string map_message;
184     bool passive_message;
185
186     /** Hide special tile */
187     bool invisible;
188
189     /** Go to this world */
190     std::string next_worldmap;
191
192     /** Quit the worldmap */
193     bool quit_worldmap;
194
195     /** If false, disables the auto walking after finishing a level */
196     bool auto_path;
197
198     // Directions which are walkable from this level
199     bool north;
200     bool east;
201     bool south;
202     bool west;
203
204     /** Only applies actions (ie. passive messages) when going to that direction */
205     bool apply_action_north;
206     bool apply_action_east;
207     bool apply_action_south;
208     bool apply_action_west;
209   };
210
211   /** Variables to deal with the passive map messages */
212   Timer passive_message_timer;
213   std::string passive_message;
214
215 private:
216   std::string map_filename;
217
218   typedef std::vector<SpecialTile> SpecialTiles;
219   SpecialTiles special_tiles;
220
221   MusicRef song;
222
223   bool enter_level;
224
225   Vector offset;
226   std::string savegame_file;
227
228   void get_level_title(SpecialTile& special_tile);
229
230   void draw_status(DrawingContext& context);
231
232   // to avoid calculating total stats all the time. This way only
233   // when need, it is calculated.
234   Statistics total_stats;
235   void calculate_total_stats();
236
237   Timer frame_timer;
238
239 public:
240   WorldMap();
241   ~WorldMap();
242
243   /** Busy loop */
244   void display();
245
246   void load_map();
247   
248   void get_input();
249
250   /** Update Tux position */
251   void update(float delta);
252
253   /** Draw one frame */
254   void draw(DrawingContext& context, const Vector& offset);
255
256   Vector get_next_tile(Vector pos, Direction direction);
257   Tile* at(Vector pos);
258   WorldMap::SpecialTile* at_special_tile();
259
260   /** Check if it is possible to walk from \a pos into \a direction,
261       if possible, write the new position to \a new_pos */
262   bool path_ok(Direction direction, Vector pos, Vector* new_pos);
263
264   /* Save map to slot */
265   void savegame(const std::string& filename);
266   /* Load map from slot
267      You should call set_map_filename() before this */
268   void loadgame(const std::string& filename);
269   /* Load map directly from file */
270   void loadmap(const std::string& filename);
271
272   const std::string& get_world_title() const
273     { return name; }
274     
275   const int& get_start_x() const
276     { return start_x; }
277   
278   const int& get_start_y() const
279     { return start_y; }
280
281   void set_map_filename(std::string filename)
282     { map_filename = filename; }
283
284 private:
285   void on_escape_press();
286 };
287
288 } // namespace WorldMapNS
289
290 #endif
291
292 /* Local Variables: */
293 /* mode:c++ */
294 /* End: */