- moved tilemanager into its own class
[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 "screen/drawing_context.h"
23 #include "setup.h"
24 #include "globals.h"
25 #include "lispreader.h"
26 #include "tile.h"
27 #include "tile_manager.h"
28
29 TileManager* TileManager::instance_  = 0;
30 std::set<TileGroup>* TileManager::tilegroups_  = 0;
31
32 TileManager::TileManager()
33 {
34   std::string filename = datadir + "/images/tilesets/supertux.stgt";
35   load_tileset(filename);
36 }
37
38 TileManager::~TileManager()
39 {
40   for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
41     delete *i;                                                                  
42   }
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(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
54     delete *i;
55   }
56   tiles.clear();
57  
58   lisp_object_t* root_obj = lisp_read_from_file(filename);
59
60   if (!root_obj)
61     st_abort("Couldn't load file", filename);
62
63   if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-tiles") == 0)
64     {
65       lisp_object_t* cur = lisp_cdr(root_obj);
66       int tileset_id = 0;
67
68       while(!lisp_nil_p(cur))
69         {
70           lisp_object_t* element = lisp_car(cur);
71
72           if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
73             {
74               LispReader reader(lisp_cdr(element));
75
76               Tile* tile = new Tile;
77               int tile_id = tile->read(reader);
78               if(tile_id < 0) {
79                 std::cerr 
80                   << "Warning: parse error when reading a tile, skipping.\n";
81                 continue;
82               }
83
84               tile_id += tileset_id;
85
86               if(tile_id >= int(tiles.size()))
87                 tiles.resize(tile_id+1);
88               tiles[tile_id] = tile;
89             }
90           else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
91             {
92               LispReader reader(lisp_cdr(element));
93               std::string filename;
94               reader.read_string("file", filename);
95               filename = datadir + "/images/tilesets/" + filename;
96               load_tileset(filename);
97             }
98           else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
99             {
100               TileGroup new_;
101               LispReader reader(lisp_cdr(element));
102               reader.read_string("name", new_.name);
103               reader.read_int_vector("tiles", new_.tiles);            
104               if(!tilegroups_)
105                 tilegroups_ = new std::set<TileGroup>;
106               tilegroups_->insert(new_).first;
107             }
108           else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
109             {
110               LispReader reader(lisp_cdr(element));
111               reader.read_int("id", tileset_id);
112               tileset_id *= 1000;
113             }
114           else
115             {
116               std::cerr << "Unknown symbol: " << 
117                 lisp_symbol(lisp_car(element)) << "\n";
118             }
119
120           cur = lisp_cdr(cur);
121         }
122     }
123   else
124     {
125       assert(0);
126     }
127
128   lisp_free(root_obj);
129   current_tileset = filename;
130 }
131
132 void
133 TileManager::draw_tile(DrawingContext& context, unsigned int c,
134     const Vector& pos, int layer)
135 {
136   if(c == 0)
137     return;
138
139   Tile& tile = get(c);
140
141   if(!tile.images.size())
142     return;
143
144   if(tile.images.size() > 1)
145   {
146     size_t frame 
147       = ((global_frame_counter*25) / tile.anim_speed) % tile.images.size();
148     context.draw_surface(tile.images[frame], pos, layer);
149   }
150   else if (tile.images.size() == 1)
151   {
152     context.draw_surface(tile.images[0], pos, layer);
153   }
154 }
155
156 /* EOF */