Two leveleditor related bug fixes:
[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[tile_id] = tile;
84             }
85           else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
86             {
87               LispReader reader(lisp_cdr(element));
88               std::string filename;
89               reader.read_string("file", filename);
90               filename = datadir + "/images/tilesets/" + filename;
91               load_tileset(filename);
92             }
93           else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
94             {
95               TileGroup new_;
96               LispReader reader(lisp_cdr(element));
97               reader.read_string("name", new_.name);
98               reader.read_int_vector("tiles", new_.tiles);            
99               if(!tilegroups_)
100                 tilegroups_ = new std::set<TileGroup>;
101               tilegroups_->insert(new_).first;
102             }
103           else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
104             {
105               LispReader reader(lisp_cdr(element));
106               reader.read_int("id", tileset_id);
107               tileset_id *= 1000;
108             }
109           else
110             {
111               std::cerr << "Unknown symbol: " << 
112                 lisp_symbol(lisp_car(element)) << "\n";
113             }
114
115           cur = lisp_cdr(cur);
116         }
117     }
118   else
119     {
120       assert(0);
121     }
122
123   lisp_free(root_obj);
124   current_tileset = filename;
125 }
126
127 void
128 TileManager::draw_tile(DrawingContext& context, unsigned int c,
129     const Vector& pos, int layer)
130 {
131   if(c == 0)
132     return;
133
134   Tile* tile = get(c);
135
136   if(!tile->images.size())
137     return;
138
139   if(tile->images.size() > 1)
140   {
141     size_t frame 
142       = ((global_frame_counter*25) / tile->anim_speed) % tile->images.size();
143     context.draw_surface(tile->images[frame], pos, layer);
144   }
145   else if (tile->images.size() == 1)
146   {
147     context.draw_surface(tile->images[0], pos, layer);
148   }
149 }
150
151 Tile*
152 TileManager::get(unsigned int id)
153 {
154 Tiles::iterator i = tiles.find(id);
155 if(i == tiles.end())
156   return 0;
157 return i->second;
158 }
159
160 /* EOF */