src/object/background.cpp

Go to the documentation of this file.
00001 //  SuperTux
00002 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
00003 //
00004 //  This program is free software: you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation, either version 3 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
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   // read position, defaults to (0,0)
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, /* default = */ 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   // FIXME: We are not handling 'pos'
00235   draw_image(context, Vector(level_size.width / 2.0f, level_size.height / 2.0f) + center_offset * (1.0f - speed));
00236 }
00237 
00238 /* EOF */

Generated on Mon Jun 9 03:38:19 2014 for SuperTux by  doxygen 1.5.1