00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "object/background.hpp"
00018
00019 #include <iostream>
00020 #include <math.h>
00021 #include <stdexcept>
00022
00023 #include "math/sizef.hpp"
00024 #include "supertux/globals.hpp"
00025 #include "supertux/object_factory.hpp"
00026 #include "supertux/sector.hpp"
00027 #include "util/log.hpp"
00028 #include "util/reader.hpp"
00029
00030 Background::Background() :
00031 alignment(NO_ALIGNMENT),
00032 layer(LAYER_BACKGROUND0),
00033 imagefile_top(),
00034 imagefile(),
00035 imagefile_bottom(),
00036 pos(),
00037 speed(),
00038 speed_y(),
00039 scroll_speed(),
00040 scroll_offset(),
00041 image_top(),
00042 image(),
00043 image_bottom()
00044 {
00045 }
00046
00047 Background::Background(const Reader& reader) :
00048 alignment(NO_ALIGNMENT),
00049 layer(LAYER_BACKGROUND0),
00050 imagefile_top(),
00051 imagefile(),
00052 imagefile_bottom(),
00053 pos(),
00054 speed(),
00055 speed_y(),
00056 scroll_speed(),
00057 scroll_offset(),
00058 image_top(),
00059 image(),
00060 image_bottom()
00061 {
00062
00063 float px = 0;
00064 float py = 0;
00065 reader.get("x", px);
00066 reader.get("y", py);
00067 this->pos = Vector(px,py);
00068
00069 speed = 1.0;
00070 speed_y = 1.0;
00071
00072 std::string alignment_str;
00073 if (reader.get("alignment", alignment_str))
00074 {
00075 if (alignment_str == "left")
00076 {
00077 alignment = LEFT_ALIGNMENT;
00078 }
00079 else if (alignment_str == "right")
00080 {
00081 alignment = RIGHT_ALIGNMENT;
00082 }
00083 else if (alignment_str == "top")
00084 {
00085 alignment = TOP_ALIGNMENT;
00086 }
00087 else if (alignment_str == "bottom")
00088 {
00089 alignment = BOTTOM_ALIGNMENT;
00090 }
00091 else if (alignment_str == "none")
00092 {
00093 alignment = NO_ALIGNMENT;
00094 }
00095 else
00096 {
00097 log_warning << "Background: invalid alignment: '" << alignment_str << "'" << std::endl;
00098 alignment = NO_ALIGNMENT;
00099 }
00100 }
00101
00102 reader.get("scroll-offset-x", scroll_offset.x);
00103 reader.get("scroll-offset-y", scroll_offset.y);
00104
00105 reader.get("scroll-speed-x", scroll_speed.x);
00106 reader.get("scroll-speed-y", scroll_speed.y);
00107
00108 layer = reader_get_layer (reader, LAYER_BACKGROUND0);
00109
00110 if(!reader.get("image", imagefile) || !reader.get("speed", speed))
00111 throw std::runtime_error("Must specify image and speed for background");
00112
00113 set_image(imagefile, speed);
00114 if (!reader.get("speed-y", speed_y))
00115 {
00116 speed_y = speed;
00117 }
00118
00119 if (reader.get("image-top", imagefile_top)) {
00120 image_top = Surface::create(imagefile_top);
00121 }
00122 if (reader.get("image-bottom", imagefile_bottom)) {
00123 image_bottom = Surface::create(imagefile_bottom);
00124 }
00125 }
00126
00127 Background::~Background()
00128 {
00129 }
00130
00131 void
00132 Background::update(float delta)
00133 {
00134 scroll_offset += scroll_speed * delta;
00135 }
00136
00137 void
00138 Background::set_image(const std::string& name, float speed)
00139 {
00140 this->imagefile = name;
00141 this->speed = speed;
00142
00143 image = Surface::create(name);
00144 }
00145
00146 void
00147 Background::draw_image(DrawingContext& context, const Vector& pos)
00148 {
00149 Sizef level(Sector::current()->get_width(), Sector::current()->get_height());
00150 Sizef screen(SCREEN_WIDTH, SCREEN_HEIGHT);
00151 Sizef parallax_image_size = (1.0f - speed) * screen + level * speed;
00152 Rectf cliprect = context.get_cliprect();
00153
00154 int start_x = static_cast<int>(floorf((cliprect.get_left() - (pos.x - image->get_width() /2.0f)) / image->get_width()));
00155 int end_x = static_cast<int>(ceilf((cliprect.get_right() - (pos.x + image->get_width() /2.0f)) / image->get_width()))+1;
00156 int start_y = static_cast<int>(floorf((cliprect.get_top() - (pos.y - image->get_height()/2.0f)) / image->get_height()));
00157 int end_y = static_cast<int>(ceilf((cliprect.get_bottom() - (pos.y + image->get_height()/2.0f)) / image->get_height()))+1;
00158
00159 switch(alignment)
00160 {
00161 case LEFT_ALIGNMENT:
00162 for(int y = start_y; y < end_y; ++y)
00163 {
00164 Vector p(pos.x - parallax_image_size.width / 2.0f,
00165 pos.y + y * image->get_height() - image->get_height() / 2.0f);
00166 context.draw_surface(image, p, layer);
00167 }
00168 break;
00169
00170 case RIGHT_ALIGNMENT:
00171 for(int y = start_y; y < end_y; ++y)
00172 {
00173 Vector p(pos.x + parallax_image_size.width / 2.0f - image->get_width(),
00174 pos.y + y * image->get_height() - image->get_height() / 2.0f);
00175 context.draw_surface(image, p, layer);
00176 }
00177 break;
00178
00179 case TOP_ALIGNMENT:
00180 for(int x = start_x; x < end_x; ++x)
00181 {
00182 Vector p(pos.x + x * image->get_width() - image->get_width() / 2.0f,
00183 pos.y - parallax_image_size.height / 2.0f);
00184 context.draw_surface(image, p, layer);
00185 }
00186 break;
00187
00188 case BOTTOM_ALIGNMENT:
00189 for(int x = start_x; x < end_x; ++x)
00190 {
00191 Vector p(pos.x + x * image->get_width() - image->get_width() / 2.0f,
00192 pos.y - image->get_height() + parallax_image_size.height / 2.0f);
00193 context.draw_surface(image, p, layer);
00194 }
00195 break;
00196
00197 case NO_ALIGNMENT:
00198 for(int y = start_y; y < end_y; ++y)
00199 for(int x = start_x; x < end_x; ++x)
00200 {
00201 Vector p(pos.x + x * image->get_width() - image->get_width()/2,
00202 pos.y + y * image->get_height() - image->get_height()/2);
00203
00204 if (image_top.get() != NULL && (y < 0))
00205 {
00206 context.draw_surface(image_top, p, layer);
00207 }
00208 else if (image_bottom.get() != NULL && (y > 0))
00209 {
00210 context.draw_surface(image_bottom, p, layer);
00211 }
00212 else
00213 {
00214 context.draw_surface(image, p, layer);
00215 }
00216 }
00217 break;
00218 }
00219 }
00220
00221 void
00222 Background::draw(DrawingContext& context)
00223 {
00224 if(image.get() == NULL)
00225 return;
00226
00227 Sizef level_size(Sector::current()->get_width(),
00228 Sector::current()->get_height());
00229 Sizef screen(SCREEN_WIDTH, SCREEN_HEIGHT);
00230 Sizef translation_range = level_size - screen;
00231 Vector center_offset(context.get_translation().x - translation_range.width / 2.0f,
00232 context.get_translation().y - translation_range.height / 2.0f);
00233
00234
00235 draw_image(context, Vector(level_size.width / 2.0f, level_size.height / 2.0f) + center_offset * (1.0f - speed));
00236 }
00237
00238