1 /*
2  * Copyright (C) 2006-2019 Christopho, Solarus - http://www.solarus-games.org
3  *
4  * Solarus 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  * Solarus 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 along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 #include "solarus/core/Debug.h"
18 #include "solarus/entities/AnimatedTilePattern.h"
19 #include "solarus/entities/GroundInfo.h"
20 #include "solarus/entities/TilePattern.h"
21 #include "solarus/graphics/Surface.h"
22 #include <sstream>
23 
24 namespace Solarus {
25 
26 /**
27  * \brief Constructor.
28  *
29  * It is called by the subclasses.
30  *
31  * \param ground Kind of ground.
32  * \param size Size of the pattern in pixels (must be a multiple of 8).
33  */
TilePattern(Ground ground,const Size & size)34 TilePattern::TilePattern(Ground ground, const Size& size):
35   ground(ground),
36   size(size) {
37 
38   // Check the width and the height.
39   if (size.width <= 0 || size.height <= 0
40       || size.width % 8 != 0 || size.height % 8 != 0) {
41     std::ostringstream oss;
42     oss << "Invalid tile pattern: the size is ("
43         << size.width << "x" << size.height <<
44         ") but should be positive and multiple of 8 pixels";
45     Debug::die(oss.str());
46   }
47 }
48 
49 /**
50  * \brief Destructor.
51  */
~TilePattern()52 TilePattern::~TilePattern() {
53 }
54 
55 /**
56  * \brief Returns the width of the tile pattern.
57  * \return The width of the pattern.
58  */
get_width() const59 int TilePattern::get_width() const {
60   return size.width;
61 }
62 
63 /**
64  * \brief Returns the height of the tile pattern.
65  * \return The height of the pattern.
66  */
get_height() const67 int TilePattern::get_height() const {
68   return size.height;
69 }
70 
71 /**
72  * \brief Returns the size of the tile pattern.
73  * \return The size of the pattern.
74  */
get_size() const75 const Size& TilePattern::get_size() const {
76   return size;
77 }
78 
79 /**
80  * \brief Returns the king of ground of this tile pattern.
81  * \return The ground of this tile pattern
82  */
get_ground() const83 Ground TilePattern::get_ground() const {
84   return ground;
85 }
86 
87 /**
88  * \brief Updates this tile pattern.
89  *
90  * This function is called repeatedly by non-optimized tiles using the pattern.
91  *
92  * It does nothing by default.
93  */
update()94 void TilePattern::update() {
95 }
96 
97 /**
98  * \brief Returns whether this tile pattern is animated, i.e. not always drawn
99  * the same way.
100  *
101  * Non-animated tiles may be rendered faster by using intermediate surfaces
102  * that are drawn only once.
103  * This function should return false if the tile pattern is always drawn the same way.
104  * Returns true by default.
105  *
106  * \return true if this tile pattern is animated
107  */
is_animated() const108 bool TilePattern::is_animated() const {
109   return true;
110 }
111 
112 /**
113  * \brief Returns whether tiles having this tile pattern are drawn at their
114  * position.
115  *
116  * Usually, this function returns true, and when it is the case, draw() is
117  * called only for tiles that are located in the current viewport.
118  *
119  * However, some tile patterns may want to be drawn even when they are not
120  * in the viewport, typically to make an illusion of movement like parallax
121  * scrolling.
122  *
123  * \return true if tiles having this pattern are drawn where they are placed
124  */
is_drawn_at_its_position() const125 bool TilePattern::is_drawn_at_its_position() const {
126   return true;
127 }
128 
129 /**
130  * \brief Fills a rectangle by repeating this tile pattern.
131  * \param dst_surface The destination surface.
132  * \param dst_position Coordinates of the rectangle to fill in \c dst_surface.
133  * \param tileset The tileset to use.
134  * \param viewport Coordinates of the top-left corner of \c dst_surface
135  * relative to the map (may be used for scrolling tiles).
136  */
fill_surface(const SurfacePtr & dst_surface,const Rectangle & dst_position,const Tileset & tileset,const Point & viewport) const137 void TilePattern::fill_surface(
138     const SurfacePtr& dst_surface,
139     const Rectangle& dst_position,
140     const Tileset& tileset,
141     const Point& viewport
142 ) const {
143   Point dst;
144 
145   int limit_x = dst_position.get_x() + dst_position.get_width();
146   int limit_y = dst_position.get_y() + dst_position.get_height();
147 
148   for (int y = dst_position.get_y();
149       y < limit_y;
150       y += get_height()) {
151 
152     if ((y <= dst_surface->get_height() && y + get_height() > 0)
153         || !is_drawn_at_its_position()) {
154       dst.y = y;
155 
156       for (int x = dst_position.get_x();
157           x < limit_x;
158           x += get_width()) {
159 
160         if ((x <= dst_surface->get_width() && x + get_width() > 0)
161             || !is_drawn_at_its_position()) {
162           dst.x = x;
163           draw(dst_surface, dst, tileset, viewport);
164         }
165       }
166     }
167   }
168 }
169 
170 }
171 
172