5668fa6d6a2e04baa8ba28588f2303d1ba2477ee
[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 #include <config.h>
21
22 #include <cmath>
23 #include <cassert>
24 #include <iostream>
25 #include <stdexcept>
26
27 #include "app/globals.h"
28 #include "tile.h"
29 #include "scene.h"
30 #include "resources.h"
31 #include "utils/lispreader.h"
32 #include "math/vector.h"
33 #include "video/drawing_context.h"
34
35 Tile::Tile()
36   : id(0), editor_image(0), attributes(0), data(0), anim_fps(1)
37 {
38 }
39
40 Tile::~Tile()
41 {
42   for(std::vector<Surface*>::iterator i = images.begin(); i != images.end();
43       ++i) {
44     delete *i;
45   }
46   delete editor_image;
47 }
48
49 void
50 Tile::parse(LispReader& reader)
51 {
52   if(!reader.read_uint("id", id)) {
53     throw std::runtime_error("Missing tile-id.");
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 |= UNISOLID | SOLID;
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_float("anim-fps", anim_fps);
80
81   if(reader.read_int("slope-type", data)) {
82     attributes |= SOLID | SLOPE;
83   }
84
85   parse_images(reader.read_lisp("images"));
86   reader.read_string("editor-images", editor_imagefile);
87 }
88
89 void
90 Tile::parse_images(lisp_object_t* list)
91 {
92   while(!lisp_nil_p(list)) {
93     lisp_object_t* cur = lisp_car(list);
94     if(lisp_string_p(cur)) {
95       imagespecs.push_back(ImageSpec(lisp_string(cur), Rectangle(0, 0, 0, 0)));
96     } else if(lisp_cons_p(cur) && lisp_symbol_p(lisp_car(cur))) {
97       lisp_object_t* sym  = lisp_car(cur);
98       lisp_object_t* data = lisp_cdr(cur);
99       
100       if (strcmp(lisp_symbol(sym), "region") == 0) {
101         float x = lisp_integer(lisp_list_nth(data, 1));
102         float y = lisp_integer(lisp_list_nth(data, 2));
103         float width = lisp_integer(lisp_list_nth(data, 3));
104         float height = lisp_integer(lisp_list_nth(data, 4));
105         imagespecs.push_back(ImageSpec(lisp_string(lisp_car(data)),
106               Rectangle(x, y, x+width, y+height)));
107       } else {
108         std::cerr << "Tile: Type mismatch, should be '(region \"somestring\" x y w h)'" << std::endl;
109         continue;
110       }
111     } else {
112       std::cerr << "Expected string or list in images tag.\n";
113       continue;
114     }
115     
116     list = lisp_cdr(list);
117   }
118 }
119
120 void
121 Tile::load_images()
122 {
123   assert(images.size() == 0);
124   for(std::vector<ImageSpec>::iterator i = imagespecs.begin(); i !=
125       imagespecs.end(); ++i) {
126     const ImageSpec& spec = *i;
127     Surface* surface;
128     std::string file 
129       = get_resource_filename(std::string("images/tilesets/") + spec.file);
130     if(spec.rect.get_width() <= 0) {
131       surface = new Surface(file, true);
132     } else {
133       surface = new Surface(file,
134           (int) spec.rect.p1.x,
135           (int) spec.rect.p1.y,
136           (int) spec.rect.get_width(),
137           (int) spec.rect.get_height(), true);
138     }
139     images.push_back(surface);
140   }
141   if(editor_imagefile != "") {
142     editor_image = new Surface(
143         get_resource_filename(
144           std::string("images/tilesets/") + editor_imagefile), true);
145   }
146 }
147
148 Surface*
149 Tile::get_editor_image() const
150 {
151   if(editor_image)
152     return editor_image;
153   if(images.size() > 0)
154     return images[0];
155
156   return 0;
157 }
158
159 void
160 Tile::draw(DrawingContext& context, const Vector& pos, int layer) const
161 {
162   if(images.size() > 1) {
163     size_t frame = size_t(global_time * anim_fps) % images.size();
164     context.draw_surface(images[frame], pos, layer);
165   } else if (images.size() == 1) {
166     context.draw_surface(images[0], pos, layer);
167   }
168 }
169