- added unisolid patch from Upsilon
[supertux.git] / src / tile.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 "tile.h"
22 #include "scene.h"
23 #include "assert.h"
24
25 TileManager* TileManager::instance_  = 0;
26 std::set<TileGroup>* TileManager::tilegroups_  = 0;
27
28 Tile::Tile()
29 {
30 }
31
32 Tile::~Tile()
33 {
34   for(std::vector<Surface*>::iterator i = images.begin(); i != images.end();
35       ++i) {
36     delete *i;
37   }
38   for(std::vector<Surface*>::iterator i = editor_images.begin();
39       i != editor_images.end(); ++i) {
40     delete *i;                                                                
41   }
42 }
43
44 //---------------------------------------------------------------------------
45
46 TileManager::TileManager()
47 {
48   std::string filename = datadir + "/images/tilesets/supertux.stgt";
49   load_tileset(filename);
50 }
51
52 TileManager::~TileManager()
53 {
54   for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
55     delete *i;                                                                  
56   }
57 }
58
59 void TileManager::load_tileset(std::string filename)
60 {
61   if(filename == current_tileset)
62     return;
63   
64   // free old tiles
65   for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
66     delete *i;
67   }
68   tiles.clear();
69  
70   lisp_object_t* root_obj = lisp_read_from_file(filename);
71
72   if (!root_obj)
73     st_abort("Couldn't load file", filename);
74
75   if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-tiles") == 0)
76     {
77       lisp_object_t* cur = lisp_cdr(root_obj);
78       int tileset_id = 0;
79
80       while(!lisp_nil_p(cur))
81         {
82           lisp_object_t* element = lisp_car(cur);
83
84           if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
85             {
86               
87              
88               Tile* tile = new Tile;
89               tile->id      = -1;
90               tile->solid   = false;
91               tile->unisolid = false;
92               tile->brick   = false;
93               tile->ice     = false;
94               tile->water   = false;
95               tile->spike   = false;
96               tile->fullbox = false;
97               tile->distro  = false;
98               tile->goal    = false;
99               tile->data    = 0;
100               tile->next_tile  = 0;
101               tile->anim_speed = 25;
102
103               LispReader reader(lisp_cdr(element));
104               assert(reader.read_int("id",  &tile->id));
105               reader.read_bool("solid",     &tile->solid);
106               reader.read_bool("unisolid",  &tile->unisolid);
107               reader.read_bool("brick",     &tile->brick);
108               reader.read_bool("ice",       &tile->ice);
109               reader.read_bool("water",     &tile->water);
110               reader.read_bool("spike",     &tile->spike);
111               reader.read_bool("fullbox",   &tile->fullbox);
112               reader.read_bool("distro",    &tile->distro);
113               reader.read_bool("goal",      &tile->goal);
114               reader.read_int("data",       &tile->data);
115               reader.read_int("anim-speed", &tile->anim_speed);
116               reader.read_int("next-tile",  &tile->next_tile);
117               reader.read_string_vector("images",  &tile->filenames);
118               reader.read_string_vector("editor-images", &tile->editor_filenames);
119
120               for(std::vector<std::string>::iterator it = tile->
121                   filenames.begin();
122                   it != tile->filenames.end();
123                   ++it)
124                 {
125                   Surface* cur_image;
126                   tile->images.push_back(cur_image);
127                   tile->images[tile->images.size()-1] = new Surface(
128                                datadir +  "/images/tilesets/" + (*it),
129                                USE_ALPHA);
130                 }
131               for(std::vector<std::string>::iterator it = tile->editor_filenames.begin();
132                   it != tile->editor_filenames.end();
133                   ++it)
134                 {
135                   Surface* cur_image;
136                   tile->editor_images.push_back(cur_image);
137                   tile->editor_images[tile->editor_images.size()-1] = new Surface(
138                                datadir + "/images/tilesets/" + (*it),
139                                USE_ALPHA);
140                 }
141                 
142               if (tile->id + tileset_id >= int(tiles.size())
143                  )
144                 tiles.resize(tile->id + tileset_id+1);
145
146               tiles[tile->id + tileset_id] = tile;
147             }
148           else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
149             {
150               LispReader reader(lisp_cdr(element));
151               std::string filename;
152               reader.read_string("file",  &filename);
153               filename = datadir + "/images/tilesets/" + filename;
154               load_tileset(filename);
155             }
156           else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
157             {
158               TileGroup new_;
159               LispReader reader(lisp_cdr(element));
160               reader.read_string("name",  &new_.name);
161               reader.read_int_vector("tiles", &new_.tiles);           
162               if(!tilegroups_)
163                 tilegroups_ = new std::set<TileGroup>;
164               tilegroups_->insert(new_).first;
165             }
166           else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
167             {
168               LispReader reader(lisp_cdr(element));
169               reader.read_int("id",  &tileset_id);
170               tileset_id *= 1000;
171             }
172           else
173             {
174               puts("Unhandled symbol");
175             }
176
177           cur = lisp_cdr(cur);
178         }
179     }
180   else
181     {
182       assert(0);
183     }
184
185   lisp_free(root_obj);
186   current_tileset = filename;
187 }
188
189 void
190 Tile::draw(float x, float y, unsigned int c, Uint8 alpha)
191 {
192   if (c != 0)
193     {
194       Tile* ptile = TileManager::instance()->get(c);
195       if(ptile)
196         {
197           if(ptile->images.size() > 1)
198             {
199               ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))]->draw(x,y, alpha);
200             }
201           else if (ptile->images.size() == 1)
202             {
203               ptile->images[0]->draw(x,y, alpha);
204             }
205           else
206             {
207               //printf("Tile not dravable %u\n", c);
208             }
209         }
210     }
211 }
212
213 void
214 Tile::draw_stretched(float x, float y, int w, int h, unsigned int c, Uint8 alpha)
215 {
216   if (c != 0)
217     {
218       Tile* ptile = TileManager::instance()->get(c);
219       if(ptile)
220         {
221           if(ptile->images.size() > 1)
222             {
223               ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))]->draw_stretched(x,y,w,h, alpha);
224             }
225           else if (ptile->images.size() == 1)
226             {
227               ptile->images[0]->draw_stretched(x,y, w, h, alpha);
228             }
229           else
230             {
231               //printf("Tile not dravable %u\n", c);
232             }
233         }
234     }
235 }
236
237 // EOF //
238