2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
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.
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.
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/>.
17 #include "object/background.hpp"
23 #include "math/sizef.hpp"
24 #include "supertux/globals.hpp"
25 #include "supertux/object_factory.hpp"
26 #include "supertux/sector.hpp"
27 #include "util/log.hpp"
28 #include "util/reader.hpp"
30 Background::Background() :
31 alignment(NO_ALIGNMENT),
32 layer(LAYER_BACKGROUND0),
47 Background::Background(const Reader& reader) :
48 alignment(NO_ALIGNMENT),
49 layer(LAYER_BACKGROUND0),
62 // read position, defaults to (0,0)
67 this->pos = Vector(px,py);
72 std::string alignment_str;
73 if (reader.get("alignment", alignment_str))
75 if (alignment_str == "left")
77 alignment = LEFT_ALIGNMENT;
79 else if (alignment_str == "right")
81 alignment = RIGHT_ALIGNMENT;
83 else if (alignment_str == "top")
85 alignment = TOP_ALIGNMENT;
87 else if (alignment_str == "bottom")
89 alignment = BOTTOM_ALIGNMENT;
91 else if (alignment_str == "none")
93 alignment = NO_ALIGNMENT;
97 log_warning << "Background: invalid alignment: '" << alignment_str << "'" << std::endl;
98 alignment = NO_ALIGNMENT;
102 reader.get("scroll-offset-x", scroll_offset.x);
103 reader.get("scroll-offset-y", scroll_offset.y);
105 reader.get("scroll-speed-x", scroll_speed.x);
106 reader.get("scroll-speed-y", scroll_speed.y);
108 layer = reader_get_layer (reader, /* default = */ LAYER_BACKGROUND0);
110 if(!reader.get("image", imagefile) || !reader.get("speed", speed))
111 throw std::runtime_error("Must specify image and speed for background");
113 set_image(imagefile, speed);
114 if (!reader.get("speed-y", speed_y))
119 if (reader.get("image-top", imagefile_top)) {
120 image_top = Surface::create(imagefile_top);
122 if (reader.get("image-bottom", imagefile_bottom)) {
123 image_bottom = Surface::create(imagefile_bottom);
127 Background::~Background()
132 Background::update(float delta)
134 scroll_offset += scroll_speed * delta;
138 Background::set_image(const std::string& name, float speed)
140 this->imagefile = name;
143 image = Surface::create(name);
147 Background::draw_image(DrawingContext& context, const Vector& pos)
149 Sizef level(Sector::current()->get_width(), Sector::current()->get_height());
150 Sizef screen(SCREEN_WIDTH, SCREEN_HEIGHT);
151 Sizef parallax_image_size = (1.0f - speed) * screen + level * speed;
152 Rectf cliprect = context.get_cliprect();
154 int start_x = static_cast<int>(floorf((cliprect.get_left() - (pos.x - image->get_width() /2.0f)) / image->get_width()));
155 int end_x = static_cast<int>(ceilf((cliprect.get_right() - (pos.x + image->get_width() /2.0f)) / image->get_width()))+1;
156 int start_y = static_cast<int>(floorf((cliprect.get_top() - (pos.y - image->get_height()/2.0f)) / image->get_height()));
157 int end_y = static_cast<int>(ceilf((cliprect.get_bottom() - (pos.y + image->get_height()/2.0f)) / image->get_height()))+1;
162 for(int y = start_y; y < end_y; ++y)
164 Vector p(pos.x - parallax_image_size.width / 2.0f,
165 pos.y + y * image->get_height() - image->get_height() / 2.0f);
166 context.draw_surface(image, p, layer);
170 case RIGHT_ALIGNMENT:
171 for(int y = start_y; y < end_y; ++y)
173 Vector p(pos.x + parallax_image_size.width / 2.0f - image->get_width(),
174 pos.y + y * image->get_height() - image->get_height() / 2.0f);
175 context.draw_surface(image, p, layer);
180 for(int x = start_x; x < end_x; ++x)
182 Vector p(pos.x + x * image->get_width() - image->get_width() / 2.0f,
183 pos.y - parallax_image_size.height / 2.0f);
184 context.draw_surface(image, p, layer);
188 case BOTTOM_ALIGNMENT:
189 for(int x = start_x; x < end_x; ++x)
191 Vector p(pos.x + x * image->get_width() - image->get_width() / 2.0f,
192 pos.y - image->get_height() + parallax_image_size.height / 2.0f);
193 context.draw_surface(image, p, layer);
198 for(int y = start_y; y < end_y; ++y)
199 for(int x = start_x; x < end_x; ++x)
201 Vector p(pos.x + x * image->get_width() - image->get_width()/2,
202 pos.y + y * image->get_height() - image->get_height()/2);
204 if (image_top.get() != NULL && (y < 0))
206 context.draw_surface(image_top, p, layer);
208 else if (image_bottom.get() != NULL && (y > 0))
210 context.draw_surface(image_bottom, p, layer);
214 context.draw_surface(image, p, layer);
222 Background::draw(DrawingContext& context)
224 if(image.get() == NULL)
227 Sizef level_size(Sector::current()->get_width(),
228 Sector::current()->get_height());
229 Sizef screen(SCREEN_WIDTH, SCREEN_HEIGHT);
230 Sizef translation_range = level_size - screen;
231 Vector center_offset(context.get_translation().x - translation_range.width / 2.0f,
232 context.get_translation().y - translation_range.height / 2.0f);
234 // FIXME: We are not handling 'pos'
235 draw_image(context, Vector(level_size.width / 2.0f, level_size.height / 2.0f) + center_offset * (1.0f - speed));