Background drawing now starts at the center of the level, instead of the top/left...
[supertux.git] / src / object / background.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
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.
8 //
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.
13 //
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/>.
16
17 #include "object/background.hpp"
18
19 #include <iostream>
20 #include "math/sizef.hpp"
21 #include "supertux/globals.hpp"
22 #include "supertux/object_factory.hpp"
23 #include "supertux/sector.hpp"
24 #include "util/reader.hpp"
25
26 Background::Background() :
27   layer(LAYER_BACKGROUND0),
28   imagefile_top(),
29   imagefile(),
30   imagefile_bottom(),
31   pos(),
32   speed(),
33   speed_y(),
34   scroll_speed(),
35   scroll_offset(),
36   image_top(),
37   image(),
38   image_bottom()
39 {
40 }
41
42 Background::Background(const Reader& reader) :
43   layer(LAYER_BACKGROUND0),
44   imagefile_top(),
45   imagefile(),
46   imagefile_bottom(),
47   pos(),
48   speed(),
49   speed_y(),
50   scroll_speed(),
51   scroll_offset(),
52   image_top(),
53   image(),
54   image_bottom()
55 {
56   // read position, defaults to (0,0)
57   float px = 0;
58   float py = 0;
59   reader.get("x", px);
60   reader.get("y", py);
61   this->pos = Vector(px,py);
62
63   speed = 1.0;
64   speed_y = 1.0;
65
66   reader.get("scroll-offset-x", scroll_offset.x);
67   reader.get("scroll-offset-y", scroll_offset.y);
68
69   reader.get("scroll-speed-x", scroll_speed.x);
70   reader.get("scroll-speed-y", scroll_speed.y);
71
72   reader.get("layer", layer);
73   if(!reader.get("image", imagefile) || !reader.get("speed", speed))
74     throw std::runtime_error("Must specify image and speed for background");
75
76   set_image(imagefile, speed);
77   if (!reader.get("speed-y", speed_y))
78   {
79     speed_y = speed;
80   }
81
82   if (reader.get("image-top", imagefile_top)) {
83     image_top = Surface::create(imagefile_top);
84   }
85   if (reader.get("image-bottom", imagefile_bottom)) {
86     image_bottom = Surface::create(imagefile_bottom);
87   }
88 }
89
90 Background::~Background()
91 {
92 }
93
94 void
95 Background::update(float delta)
96 {
97   scroll_offset += scroll_speed * delta;
98 }
99
100 void
101 Background::set_image(const std::string& name, float speed)
102 {
103   this->imagefile = name;
104   this->speed = speed;
105
106   image = Surface::create(name);
107 }
108
109 void
110 Background::draw_image(DrawingContext& context, const Vector& pos)
111 {
112   Sizef level(Sector::current()->get_width(),
113               Sector::current()->get_height());
114
115   // FIXME: Implement proper clipping here
116   int start_x = -level.width  / image->get_width()  / 2;
117   int end_x   =  level.width  / image->get_width()  / 2;
118   int start_y = -level.height / image->get_height() / 2;
119   int end_y   =  level.height / image->get_height() / 2;
120
121   for(int y = start_y; y <= end_y; ++y)
122     for(int x = start_x; x <= end_x; ++x)
123     {
124       Vector p(pos.x + x * image->get_width()  - image->get_width()/2, 
125                pos.y + y * image->get_height() - image->get_height()/2);
126
127       if (image_top.get() != NULL && (y < 0))
128       {
129         context.draw_surface(image_top.get(), p, layer);
130       }
131       else if (image_bottom.get() != NULL && (y > 0))
132       {
133         context.draw_surface(image_bottom.get(), p, layer);
134       }
135       else
136       {
137         context.draw_surface(image.get(), p, layer);
138       }
139     }
140 }
141
142 void
143 Background::draw(DrawingContext& context)
144 {
145   if(image.get() == NULL)
146     return;
147
148   Sizef level_size(Sector::current()->get_width(),
149                    Sector::current()->get_height());
150   Sizef screen(SCREEN_WIDTH, SCREEN_HEIGHT);
151   Sizef translation_range = level_size - screen;
152   Vector center_offset(context.get_translation().x - translation_range.width  / 2.0f, 
153                        context.get_translation().y - translation_range.height / 2.0f);
154
155   // FIXME: We are not handling 'pos'
156   draw_image(context, Vector(level_size.width / 2.0f, level_size.height / 2.0f) + center_offset * (1.0f - speed));
157 }
158
159 /* EOF */