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