bec57344c5eee5e5e13096aa8c417600b95328d0
[supertux.git] / src / sprite / sprite.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "sprite/sprite.hpp"
18
19 #include <assert.h>
20 #include <math.h>
21
22 #include "supertux/timer.hpp"
23
24 Sprite::Sprite(SpriteData& newdata) :
25   data(newdata),
26   frame(0),
27   frameidx(0),
28   animation_loops(-1),
29   last_ticks(),
30   angle(0.0f),
31   color(1.0f, 1.0f, 1.0f, 1.0f),
32   blend(),
33   action(data.get_action("normal"))
34 {
35   if(!action)
36     action = data.actions.begin()->second;
37   last_ticks = game_time;
38 }
39
40 Sprite::Sprite(const Sprite& other) :
41   data(other.data), 
42   frame(other.frame),
43   frameidx(other.frameidx),
44   animation_loops(other.animation_loops),
45   last_ticks(game_time),
46   angle(0.0f), // FIXME: this can't be right
47   color(1.0f, 1.0f, 1.0f, 1.0f),
48   blend(),
49   action(other.action)
50 {
51 }
52
53 Sprite::~Sprite()
54 {
55 }
56
57 SpritePtr
58 Sprite::clone() const
59 {
60   return SpritePtr(new Sprite(*this));
61 }
62
63 void
64 Sprite::set_action(const std::string& name, int loops)
65 {
66   if(action && action->name == name)
67     return;
68
69   const SpriteData::Action* newaction = data.get_action(name);
70   if(!newaction) {
71     log_debug << "Action '" << name << "' not found." << std::endl;
72     return;
73   }
74
75   action = newaction;
76   animation_loops = loops;
77   frame = 0;
78   frameidx = 0;
79 }
80
81 void
82 Sprite::set_action_continued(const std::string& name)
83 {
84   if(action && action->name == name)
85     return;
86
87   const SpriteData::Action* newaction = data.get_action(name);
88   if(!newaction) {
89     log_debug << "Action '" << name << "' not found." << std::endl;
90     return;
91   }
92
93   action = newaction;
94   update();
95 }
96
97 bool
98 Sprite::animation_done()
99 {
100   return animation_loops == 0;
101 }
102
103 void
104 Sprite::update()
105 {
106   float frame_inc = action->fps * (game_time - last_ticks);
107   last_ticks = game_time;
108
109   frame += frame_inc;
110
111   while(frame >= 1.0f) {
112     frame -= 1.0f;
113     frameidx++;
114   }
115
116   while(frameidx >= get_frames()) {
117     frameidx -= get_frames();
118     animation_loops--;
119     if(animation_done()) {
120       break;
121     }
122   }
123
124   if(animation_done()) {
125     frame = 0;
126     frameidx = get_frames()-1;
127   }
128
129   assert(frameidx < get_frames());
130 }
131
132 void
133 Sprite::draw(DrawingContext& context, const Vector& pos, int layer,
134              DrawingEffect effect)
135 {
136   assert(action != 0);
137   update();
138
139   context.set_drawing_effect(effect);
140   context.draw_surface(action->surfaces[frameidx],
141                        pos - Vector(action->x_offset, action->y_offset),
142                        angle,
143                        color,
144                        blend,
145                        layer + action->z_order);
146 }
147
148 void
149 Sprite::draw_part(DrawingContext& context, const Vector& source,
150                   const Vector& size, const Vector& pos, int layer)
151 {
152   assert(action != 0);
153   update();
154
155   context.draw_surface_part(action->surfaces[frameidx], source, size,
156                             pos - Vector(action->x_offset, action->y_offset),
157                             layer + action->z_order);
158 }
159
160 int
161 Sprite::get_width() const
162 {
163   assert(frameidx < get_frames());
164   return (int) action->surfaces[get_frame()]->get_width();
165 }
166
167 int
168 Sprite::get_height() const
169 {
170   assert(frameidx < get_frames());
171   return (int) action->surfaces[get_frame()]->get_height();
172 }
173
174 float
175 Sprite::get_current_hitbox_x_offset() const
176 {
177   return action->x_offset;
178 }
179
180 float
181 Sprite::get_current_hitbox_y_offset() const
182 {
183   return action->y_offset;
184 }
185
186 float
187 Sprite::get_current_hitbox_width() const
188 {
189   return action->hitbox_w;
190 }
191
192 float
193 Sprite::get_current_hitbox_height() const
194 {
195   return action->hitbox_h;
196 }
197
198 Rectf
199 Sprite::get_current_hitbox() const
200 {
201   return Rectf(action->x_offset, action->y_offset, action->x_offset + action->hitbox_w, action->y_offset + action->hitbox_h);
202 }
203
204 void
205 Sprite::set_angle(float a)
206 {
207   angle = a;
208 }
209
210 float
211 Sprite::get_angle() const
212 {
213   return angle;
214 }
215
216 void
217 Sprite::set_color(const Color& c)
218 {
219   color = c;
220 }
221
222 Color
223 Sprite::get_color() const
224 {
225   return color;
226 }
227
228 void
229 Sprite::set_blend(const Blend& b)
230 {
231   blend = b;
232 }
233
234 Blend
235 Sprite::get_blend() const
236 {
237   return blend;
238 }
239
240 /* EOF */