add RTL info
[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],
156                             Rectf(source, Sizef(size)),
157                             Rectf(pos - Vector(action->x_offset, action->y_offset),
158                                   Sizef(size)),
159                             layer + action->z_order);
160 }
161
162 int
163 Sprite::get_width() const
164 {
165   assert(frameidx < get_frames());
166   return (int) action->surfaces[get_frame()]->get_width();
167 }
168
169 int
170 Sprite::get_height() const
171 {
172   assert(frameidx < get_frames());
173   return (int) action->surfaces[get_frame()]->get_height();
174 }
175
176 float
177 Sprite::get_current_hitbox_x_offset() const
178 {
179   return action->x_offset;
180 }
181
182 float
183 Sprite::get_current_hitbox_y_offset() const
184 {
185   return action->y_offset;
186 }
187
188 float
189 Sprite::get_current_hitbox_width() const
190 {
191   return action->hitbox_w;
192 }
193
194 float
195 Sprite::get_current_hitbox_height() const
196 {
197   return action->hitbox_h;
198 }
199
200 Rectf
201 Sprite::get_current_hitbox() const
202 {
203   return Rectf(action->x_offset, action->y_offset, action->x_offset + action->hitbox_w, action->y_offset + action->hitbox_h);
204 }
205
206 void
207 Sprite::set_angle(float a)
208 {
209   angle = a;
210 }
211
212 float
213 Sprite::get_angle() const
214 {
215   return angle;
216 }
217
218 void
219 Sprite::set_color(const Color& c)
220 {
221   color = c;
222 }
223
224 Color
225 Sprite::get_color() const
226 {
227   return color;
228 }
229
230 void
231 Sprite::set_blend(const Blend& b)
232 {
233   blend = b;
234 }
235
236 Blend
237 Sprite::get_blend() const
238 {
239   return blend;
240 }
241
242 /* EOF */