From: grumbel Date: Tue, 1 Dec 2009 04:06:20 +0000 (+0000) Subject: Implemented background alignment for resolution independent parallax scrolling X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=3e80597b38036106d6d252649a383a3bb16c7572;p=supertux.git Implemented background alignment for resolution independent parallax scrolling git-svn-id: http://supertux.lethargik.org/svn/supertux/trunk/supertux@6160 837edb03-e0f3-0310-88ca-d4d4e8b29345 --- diff --git a/src/object/background.cpp b/src/object/background.cpp index 8729ba527..728adc7d5 100644 --- a/src/object/background.cpp +++ b/src/object/background.cpp @@ -21,9 +21,11 @@ #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(), @@ -40,6 +42,7 @@ Background::Background() : } Background::Background(const Reader& reader) : + alignment(NO_ALIGNMENT), layer(LAYER_BACKGROUND0), imagefile_top(), imagefile(), @@ -63,6 +66,32 @@ Background::Background(const Reader& reader) : speed = 1.0; speed_y = 1.0; + 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 + { + 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); @@ -109,8 +138,9 @@ Background::set_image(const std::string& name, float speed) void Background::draw_image(DrawingContext& context, const Vector& pos) { - Sizef level(Sector::current()->get_width(), - Sector::current()->get_height()); + 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; // FIXME: Implement proper clipping here int start_x = -level.width / image->get_width() / 2; @@ -118,25 +148,66 @@ Background::draw_image(DrawingContext& context, const Vector& pos) int start_y = -level.height / image->get_height() / 2; int end_y = level.height / image->get_height() / 2; - 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); + 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.get(), p, layer); + } + break; - if (image_top.get() != NULL && (y < 0)) + case RIGHT_ALIGNMENT: + for(int y = start_y; y < end_y; ++y) { - context.draw_surface(image_top.get(), p, layer); + 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.get(), p, layer); } - else if (image_bottom.get() != NULL && (y > 0)) + break; + + case TOP_ALIGNMENT: + for(int x = start_x; x < end_x; ++x) { - context.draw_surface(image_bottom.get(), p, layer); + 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.get(), p, layer); } - else + 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.get(), 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.get(), p, layer); + } + else if (image_bottom.get() != NULL && (y > 0)) + { + context.draw_surface(image_bottom.get(), p, layer); + } + else + { + context.draw_surface(image.get(), p, layer); + } + } + break; + } } void diff --git a/src/object/background.hpp b/src/object/background.hpp index 2b4e2ebb0..75a1c9306 100644 --- a/src/object/background.hpp +++ b/src/object/background.hpp @@ -43,6 +43,19 @@ public: void draw_image(DrawingContext& context, const Vector& pos); private: + enum Alignment { + NO_ALIGNMENT, + LEFT_ALIGNMENT, + RIGHT_ALIGNMENT, + TOP_ALIGNMENT, + BOTTOM_ALIGNMENT + }; + + /** Backgrounds with NO_ALIGNMENT are repeated over the whole + screen, backgrounds with left, right, top, bottom alignment are + only repeated in one direction and attached to the level edge */ + Alignment alignment; + int layer; std::string imagefile_top; std::string imagefile;