Replaced the use of a vector for the tiles placement by a map one.
[supertux.git] / src / tile_manager.cpp
1 //  $Id$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2004 Tobias Glaesser <tobi.web@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
19 //  02111-1307, USA.
20
21 #include <assert.h>
22 #include "video/drawing_context.h"
23 #include "app/setup.h"
24 #include "app/globals.h"
25 #include "utils/lispreader.h"
26 #include "tile.h"
27 #include "tile_manager.h"
28 #include "scene.h"
29
30 TileManager* TileManager::instance_  = 0;
31 std::set<TileGroup>* TileManager::tilegroups_  = 0;
32
33 TileManager::TileManager()
34 {
35   std::string filename = datadir + "/images/tilesets/supertux.stgt";
36   load_tileset(filename);
37 }
38
39 TileManager::~TileManager()
40 {
41   for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i)
42     delete i->second;
43
44   delete tilegroups_;
45 }
46
47 void TileManager::load_tileset(std::string filename)
48 {
49   if(filename == current_tileset)
50     return;
51   
52   // free old tiles
53   for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i)
54     delete i->second;
55   tiles.clear();
56  
57   lisp_object_t* root_obj = lisp_read_from_file(filename);
58
59   if (!root_obj)
60     Termination::abort("Couldn't load file", filename);
61
62   if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-tiles") == 0)
63     {
64       lisp_object_t* cur = lisp_cdr(root_obj);
65       int tileset_id = 0;
66
67       while(!lisp_nil_p(cur))
68         {
69           lisp_object_t* element = lisp_car(cur);
70
71           if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
72             {
73               LispReader reader(lisp_cdr(element));
74
75               Tile* tile = new Tile;
76               int tile_id = tile->read(reader);
77               if(tile_id < 0) {
78                 std::cerr 
79                   << "Warning: parse error when reading a tile (id < 0), skipping.\n";
80                 continue;
81               }
82
83               tiles.insert(std::make_pair(tile_id, tile));
84
85 /*              tile_id += tileset_id;
86
87               if(tile_id >= int(tiles.size()))
88                 tiles.resize(tile_id+1);
89               tiles[tile_id] = tile;*/
90             }
91           else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
92             {
93               LispReader reader(lisp_cdr(element));
94               std::string filename;
95               reader.read_string("file", filename);
96               filename = datadir + "/images/tilesets/" + filename;
97               load_tileset(filename);
98             }
99           else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
100             {
101               TileGroup new_;
102               LispReader reader(lisp_cdr(element));
103               reader.read_string("name", new_.name);
104               reader.read_int_vector("tiles", new_.tiles);            
105               if(!tilegroups_)
106                 tilegroups_ = new std::set<TileGroup>;
107               tilegroups_->insert(new_).first;
108             }
109           else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
110             {
111               LispReader reader(lisp_cdr(element));
112               reader.read_int("id", tileset_id);
113               tileset_id *= 1000;
114             }
115           else
116             {
117               std::cerr << "Unknown symbol: " << 
118                 lisp_symbol(lisp_car(element)) << "\n";
119             }
120
121           cur = lisp_cdr(cur);
122         }
123     }
124   else
125     {
126       assert(0);
127     }
128
129   lisp_free(root_obj);
130   current_tileset = filename;
131 }
132
133 void
134 TileManager::draw_tile(DrawingContext& context, unsigned int c,
135     const Vector& pos, int layer)
136 {
137   if(c == 0)
138     return;
139
140   Tile* tile = get(c);
141
142   if(!tile->images.size())
143     return;
144
145   if(tile->images.size() > 1)
146   {
147     size_t frame 
148       = ((global_frame_counter*25) / tile->anim_speed) % tile->images.size();
149     context.draw_surface(tile->images[frame], pos, layer);
150   }
151   else if (tile->images.size() == 1)
152   {
153     context.draw_surface(tile->images[0], pos, layer);
154   }
155 }
156
157 Tile*
158 TileManager::get(unsigned int id)
159 {
160 Tiles::iterator i = tiles.find(id);
161
162 if(i == tiles.end())
163   {
164   std::cerr << "Warning: Asked for a non-existing tile id. Ignoring.\n";
165   // Never return 0, but return the first tile instead so that
166   // user code doesn't have to check for NULL pointers all over
167   // the place
168   i = tiles.begin();
169   return i->second;
170   }
171 return i->second;
172
173 /*
174     if(id < tiles.size())
175       {
176         return *tiles[id]; 
177       }
178     else
179       {
180         // Never return 0, but return the 0th tile instead so that
181         // user code doesn't have to check for NULL pointers all over
182         // the place
183         return *tiles[0]; 
184       }*/
185 }
186
187 /* EOF */