X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fobject%2Fbackground.cpp;h=7b0d75f00164b8a7bf85be1acec26f2c4acfe45a;hb=2372988b5c58303f17720945e14d48c7aebc95ee;hp=f60f18435537493adaa6104b82b597c9ff7dfedd;hpb=fea3446f05e1e7673607b835c269d3e8d1929ab3;p=supertux.git diff --git a/src/object/background.cpp b/src/object/background.cpp index f60f18435..7b0d75f00 100644 --- a/src/object/background.cpp +++ b/src/object/background.cpp @@ -1,12 +1,10 @@ -// $Id$ -// // SuperTux // Copyright (C) 2006 Matthias Braun // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,29 +12,52 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// along with this program. If not, see . -#include +#include "object/background.hpp" +#include +#include #include -#include "background.hpp" -#include "camera.hpp" -#include "video/drawing_context.hpp" -#include "lisp/lisp.hpp" -#include "lisp/writer.hpp" -#include "object_factory.hpp" -#include "resources.hpp" -#include "main.hpp" -#include "log.hpp" - -Background::Background() - : layer(LAYER_BACKGROUND0) + +#include "math/sizef.hpp" +#include "supertux/globals.hpp" +#include "supertux/object_factory.hpp" +#include "supertux/sector.hpp" +#include "util/log.hpp" +#include "util/reader.hpp" + +Background::Background() : + alignment(NO_ALIGNMENT), + layer(LAYER_BACKGROUND0), + imagefile_top(), + imagefile(), + imagefile_bottom(), + pos(), + speed(), + speed_y(), + scroll_speed(), + scroll_offset(), + image_top(), + image(), + image_bottom() { } -Background::Background(const lisp::Lisp& reader) - : layer(LAYER_BACKGROUND0) +Background::Background(const Reader& reader) : + alignment(NO_ALIGNMENT), + layer(LAYER_BACKGROUND0), + imagefile_top(), + imagefile(), + imagefile_bottom(), + pos(), + speed(), + speed_y(), + scroll_speed(), + scroll_offset(), + image_top(), + image(), + image_bottom() { // read position, defaults to (0,0) float px = 0; @@ -48,17 +69,58 @@ Background::Background(const lisp::Lisp& reader) speed = 1.0; speed_y = 1.0; - reader.get("layer", layer); + std::string alignment_str; + if (reader.get("alignment", alignment_str)) + { + if (alignment_str == "left") + { + alignment = LEFT_ALIGNMENT; + } + else if (alignment_str == "right") + { + alignment = RIGHT_ALIGNMENT; + } + else if (alignment_str == "top") + { + alignment = TOP_ALIGNMENT; + } + else if (alignment_str == "bottom") + { + alignment = BOTTOM_ALIGNMENT; + } + else if (alignment_str == "none") + { + alignment = NO_ALIGNMENT; + } + else + { + log_warning << "Background: invalid alignment: '" << alignment_str << "'" << std::endl; + alignment = NO_ALIGNMENT; + } + } + + reader.get("scroll-offset-x", scroll_offset.x); + reader.get("scroll-offset-y", scroll_offset.y); + + reader.get("scroll-speed-x", scroll_speed.x); + reader.get("scroll-speed-y", scroll_speed.y); + + layer = reader_get_layer (reader, /* default = */ LAYER_BACKGROUND0); + if(!reader.get("image", imagefile) || !reader.get("speed", speed)) throw std::runtime_error("Must specify image and speed for background"); set_image(imagefile, speed); - reader.get("speed-y", speed_y); + if (!reader.get("speed-y", speed_y)) + { + speed_y = speed; + } + if (reader.get("image-top", imagefile_top)) { - image_top.reset(new Surface(imagefile_top)); + image_top = Surface::create(imagefile_top); } if (reader.get("image-bottom", imagefile_bottom)) { - image_bottom.reset(new Surface(imagefile_bottom)); + image_bottom = Surface::create(imagefile_bottom); } } @@ -67,36 +129,93 @@ Background::~Background() } void -Background::write(lisp::Writer& writer) +Background::update(float delta) { - writer.start_list("background"); - - if (image_top.get() != NULL) - writer.write_string("image-top", imagefile_top); - - writer.write_string("image", imagefile); - if (image_bottom.get() != NULL) - writer.write_string("image-bottom", imagefile_bottom); - - writer.write_float("speed", speed); - writer.write_float("speed-y", speed_y); - writer.write_int("layer", layer); - - writer.end_list("background"); + scroll_offset += scroll_speed * delta; } void -Background::update(float) +Background::set_image(const std::string& name_, float speed_) { + this->imagefile = name_; + this->speed = speed_; + + image = Surface::create(name_); } void -Background::set_image(const std::string& name, float speed) +Background::draw_image(DrawingContext& context, const Vector& pos_) { - this->imagefile = name; - this->speed = speed; - - image.reset(new Surface(name)); + Sizef level(Sector::current()->get_width(), Sector::current()->get_height()); + Sizef screen(SCREEN_WIDTH, SCREEN_HEIGHT); + Sizef parallax_image_size = (1.0f - speed) * screen + level * speed; + Rectf cliprect = context.get_cliprect(); + + int start_x = static_cast(floorf((cliprect.get_left() - (pos_.x - image->get_width() /2.0f)) / image->get_width())); + int end_x = static_cast(ceilf((cliprect.get_right() - (pos_.x + image->get_width() /2.0f)) / image->get_width()))+1; + int start_y = static_cast(floorf((cliprect.get_top() - (pos_.y - image->get_height()/2.0f)) / image->get_height())); + int end_y = static_cast(ceilf((cliprect.get_bottom() - (pos_.y + image->get_height()/2.0f)) / image->get_height()))+1; + + switch(alignment) + { + case LEFT_ALIGNMENT: + for(int y = start_y; y < end_y; ++y) + { + Vector p(pos_.x - parallax_image_size.width / 2.0f, + pos_.y + y * image->get_height() - image->get_height() / 2.0f); + context.draw_surface(image, p, layer); + } + break; + + case RIGHT_ALIGNMENT: + for(int y = start_y; y < end_y; ++y) + { + Vector p(pos_.x + parallax_image_size.width / 2.0f - image->get_width(), + pos_.y + y * image->get_height() - image->get_height() / 2.0f); + context.draw_surface(image, p, layer); + } + break; + + case TOP_ALIGNMENT: + for(int x = start_x; x < end_x; ++x) + { + Vector p(pos_.x + x * image->get_width() - image->get_width() / 2.0f, + pos_.y - parallax_image_size.height / 2.0f); + context.draw_surface(image, p, layer); + } + break; + + case BOTTOM_ALIGNMENT: + for(int x = start_x; x < end_x; ++x) + { + Vector p(pos_.x + x * image->get_width() - image->get_width() / 2.0f, + pos_.y - image->get_height() + parallax_image_size.height / 2.0f); + context.draw_surface(image, p, layer); + } + break; + + case NO_ALIGNMENT: + for(int y = start_y; y < end_y; ++y) + for(int x = start_x; x < end_x; ++x) + { + Vector p(pos_.x + x * image->get_width() - image->get_width()/2, + pos_.y + y * image->get_height() - image->get_height()/2); + + if (image_top.get() != NULL && (y < 0)) + { + context.draw_surface(image_top, p, layer); + } + else if (image_bottom.get() != NULL && (y > 0)) + { + context.draw_surface(image_bottom, p, layer); + } + else + { + context.draw_surface(image, p, layer); + } + } + break; + } } void @@ -105,28 +224,15 @@ Background::draw(DrawingContext& context) if(image.get() == NULL) return; - int w = (int) image->get_width(); - int h = (int) image->get_height(); - int sx = int(pos.x-context.get_translation().x * speed) % w - w; - int sy = int(pos.y-context.get_translation().y * speed_y) % h - h; - int center_image_py = int(pos.y-context.get_translation().y * speed_y); - int bottom_image_py = int(pos.y-context.get_translation().y * speed_y) + h; - context.push_transform(); - context.set_translation(Vector(0, 0)); - for(int x = sx; x < SCREEN_WIDTH; x += w) { - for(int y = sy; y < SCREEN_HEIGHT; y += h) { - if (image_top.get() != NULL && (y < center_image_py)) { - context.draw_surface(image_top.get(), Vector(x, y), layer); - continue; - } - if (image_bottom.get() != NULL && (y >= bottom_image_py)) { - context.draw_surface(image_bottom.get(), Vector(x, y), layer); - continue; - } - context.draw_surface(image.get(), Vector(x, y), layer); - } - } - context.pop_transform(); + Sizef level_size(Sector::current()->get_width(), + Sector::current()->get_height()); + Sizef screen(SCREEN_WIDTH, SCREEN_HEIGHT); + Sizef translation_range = level_size - screen; + Vector center_offset(context.get_translation().x - translation_range.width / 2.0f, + context.get_translation().y - translation_range.height / 2.0f); + + // FIXME: We are not handling 'pos' + draw_image(context, Vector(level_size.width / 2.0f, level_size.height / 2.0f) + center_offset * (1.0f - speed)); } -IMPLEMENT_FACTORY(Background, "background"); +/* EOF */