1// SuperTux - MovingSprite Base Class
2// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.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 "object/moving_sprite.hpp"
18
19#include <math.h>
20#include <physfs.h>
21
22#include "editor/editor.hpp"
23#include "math/random.hpp"
24#include "math/util.hpp"
25#include "object/sprite_particle.hpp"
26#include "sprite/sprite_manager.hpp"
27#include "supertux/sector.hpp"
28#include "util/reader_mapping.hpp"
29#include "util/writer.hpp"
30
31MovingSprite::MovingSprite(const Vector& pos, const std::string& sprite_name_,
32 int layer_, CollisionGroup collision_group) :
33 m_sprite_name(sprite_name_),
34 m_default_sprite_name(sprite_name_),
35 m_sprite(SpriteManager::current()->create(m_sprite_name)),
36 m_layer(layer_)
37{
38 m_col.m_bbox.set_pos(pos);
39 m_col.m_bbox.set_size(m_sprite->get_current_hitbox_width(), m_sprite->get_current_hitbox_height());
40 set_group(collision_group);
41}
42
43MovingSprite::MovingSprite(const ReaderMapping& reader, const Vector& pos, int layer_, CollisionGroup collision_group) :
44 MovingObject(reader),
45 m_sprite_name(),
46 m_default_sprite_name(),
47 m_sprite(),
48 m_layer(layer_)
49{
50 m_col.m_bbox.set_pos(pos);
51 if (!reader.get("sprite", m_sprite_name))
52 throw std::runtime_error("no sprite name set");
53
54 //m_default_sprite_name = m_sprite_name;
55 m_sprite = SpriteManager::current()->create(m_sprite_name);
56 m_col.m_bbox.set_size(m_sprite->get_current_hitbox_width(), m_sprite->get_current_hitbox_height());
57 set_group(collision_group);
58}
59
60MovingSprite::MovingSprite(const ReaderMapping& reader, const std::string& sprite_name_, int layer_, CollisionGroup collision_group) :
61 MovingObject(reader),
62 m_sprite_name(sprite_name_),
63 m_default_sprite_name(sprite_name_),
64 m_sprite(),
65 m_layer(layer_)
66{
67 reader.get("x", m_col.m_bbox.get_left());
68 reader.get("y", m_col.m_bbox.get_top());
69 reader.get("sprite", m_sprite_name);
70
71 //Make the sprite go default when the sprite file is invalid
72 if (m_sprite_name.empty() || !PHYSFS_exists(m_sprite_name.c_str())) {
73 m_sprite = SpriteManager::current()->create(m_default_sprite_name);
74 } else {
75 m_sprite = SpriteManager::current()->create(m_sprite_name);
76 }
77
78 m_col.m_bbox.set_size(m_sprite->get_current_hitbox_width(), m_sprite->get_current_hitbox_height());
79 set_group(collision_group);
80}
81
82MovingSprite::MovingSprite(const ReaderMapping& reader, int layer_, CollisionGroup collision_group) :
83 MovingObject(reader),
84 m_sprite_name(),
85 m_default_sprite_name(),
86 m_sprite(),
87 m_layer(layer_)
88{
89 reader.get("x", m_col.m_bbox.get_left());
90 reader.get("y", m_col.m_bbox.get_top());
91 if (!reader.get("sprite", m_sprite_name))
92 throw std::runtime_error("no sprite name set");
93
94 //m_default_sprite_name = m_sprite_name;
95 m_sprite = SpriteManager::current()->create(m_sprite_name);
96 m_col.m_bbox.set_size(m_sprite->get_current_hitbox_width(), m_sprite->get_current_hitbox_height());
97 set_group(collision_group);
98}
99
100void
101MovingSprite::draw(DrawingContext& context)
102{
103 m_sprite->draw(context.color(), get_pos(), m_layer);
104}
105
106void
107MovingSprite::update(float )
108{
109}
110
111std::string
112MovingSprite::get_sprite_name() const
113{
114 return m_sprite_name;
115}
116
117void
118MovingSprite::set_action(const std::string& action, int loops)
119{
120 m_sprite->set_action(action, loops);
121 m_col.set_size(m_sprite->get_current_hitbox_width(), m_sprite->get_current_hitbox_height());
122}
123
124void
125MovingSprite::set_action_centered(const std::string& action, int loops)
126{
127 Vector old_size = m_col.m_bbox.get_size().as_vector();
128 m_sprite->set_action(action, loops);
129 m_col.set_size(m_sprite->get_current_hitbox_width(), m_sprite->get_current_hitbox_height());
130 set_pos(get_pos() - (m_col.m_bbox.get_size().as_vector() - old_size) / 2);
131}
132
133void
134MovingSprite::set_action(const std::string& action, int loops, AnchorPoint anchorPoint)
135{
136 Rectf old_bbox = m_col.m_bbox;
137 m_sprite->set_action(action, loops);
138 float w = m_sprite->get_current_hitbox_width();
139 float h = m_sprite->get_current_hitbox_height();
140 m_col.set_size(w, h);
141 set_pos(get_anchor_pos(old_bbox, w, h, anchorPoint));
142}
143
144void
145MovingSprite::change_sprite(const std::string& new_sprite_name)
146{
147 m_sprite_name = new_sprite_name;
148 m_sprite = SpriteManager::current()->create(m_sprite_name);
149}
150
151ObjectSettings
152MovingSprite::get_settings()
153{
154 ObjectSettings result = MovingObject::get_settings();
155
156 result.add_sprite(_("Sprite"), &m_sprite_name, "sprite", m_default_sprite_name);
157
158 result.reorder({"sprite", "x", "y"});
159
160 return result;
161}
162
163void
164MovingSprite::after_editor_set()
165{
166 std::string current_action = m_sprite->get_action();
167 m_sprite = SpriteManager::current()->create(m_sprite_name);
168 m_sprite->set_action(current_action);
169}
170
171void
172MovingSprite::spawn_explosion_sprites(int count, const std::string& sprite_path)
173{
174 for (int i = 0; i < count; i++) {
175 Vector ppos = m_col.m_bbox.get_middle();
176 float angle = graphicsRandom.randf(-math::PI_2, math::PI_2);
177 float velocity = graphicsRandom.randf(350, 400);
178 float vx = sinf(angle)*velocity;
179 float vy = -cosf(angle)*velocity;
180 Vector pspeed = Vector(vx, vy);
181 Vector paccel = Vector(0, Sector::get().get_gravity()*10);
182 Sector::get().add<SpriteParticle>(sprite_path,
183 "default",
184 ppos, ANCHOR_MIDDLE,
185 pspeed, paccel,
186 LAYER_OBJECTS-1);
187 }
188}
189
190/* EOF */
191