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/core/System.h"
19 #include "solarus/entities/AnimatedTilePattern.h"
20 #include "solarus/entities/ParallaxScrollingTilePattern.h"
21 #include "solarus/entities/Tileset.h"
22 #include "solarus/graphics/Surface.h"
23
24 namespace Solarus {
25
26 /**
27 * \brief Creates a multi-frame tile pattern.
28 * \param ground Kind of ground of the tile pattern.
29 * \param frames Rectangles in the tileset image.
30 * \param frame_delay Delay in milliseconds between each frame.
31 * \param mirror_loop Whether to play the animation backwards when it loops.
32 * \param parallax \c true to also set parallax scrolling to the tile pattern.
33 */
AnimatedTilePattern(Ground ground,const std::vector<Rectangle> & frames,uint32_t frame_delay,bool mirror_loop,bool parallax)34 AnimatedTilePattern::AnimatedTilePattern(
35 Ground ground,
36 const std::vector<Rectangle>& frames,
37 uint32_t frame_delay,
38 bool mirror_loop,
39 bool parallax
40 ):
41 TilePattern(ground, frames[0].get_size()),
42 frames(frames),
43 frame_delay(frame_delay),
44 mirror_loop(mirror_loop),
45 parallax(parallax),
46 frame_index(0),
47 next_frame_date(System::now() + frame_delay) {
48
49 Debug::check_assertion(!this->frames.empty(), "Missing frames for animated pattern");
50 }
51
52 /**
53 * \copydoc TilePattern::update
54 */
update()55 void AnimatedTilePattern::update() {
56
57 uint32_t now = System::now();
58 while (now >= next_frame_date) {
59 if (!mirror_loop) {
60 frame_index = (frame_index + 1) % frames.size();
61 }
62 else {
63 frame_index = (frame_index + 1) % (2 * frames.size() - 2);
64 }
65 next_frame_date += frame_delay;
66 }
67 }
68
69 /**
70 * \copydoc TilePattern::draw
71 */
draw(const SurfacePtr & dst_surface,const Point & dst_position,const Tileset & tileset,const Point & viewport) const72 void AnimatedTilePattern::draw(
73 const SurfacePtr& dst_surface,
74 const Point& dst_position,
75 const Tileset& tileset,
76 const Point& viewport
77 ) const {
78 const SurfacePtr& tileset_image = tileset.get_tiles_image();
79
80 int final_frame_index = frame_index;
81 int num_frames = frames.size();
82 if (mirror_loop && frame_index >= num_frames) {
83 final_frame_index = (2 * frames.size() - 2) - frame_index;
84 }
85 Debug::check_assertion(final_frame_index >= 0 && final_frame_index < num_frames, "Wrong frame index");
86 const Rectangle& src = frames[final_frame_index];
87 Point dst = dst_position;
88
89 if (parallax) {
90 dst += viewport / ParallaxScrollingTilePattern::ratio;
91 }
92
93 tileset_image->draw_region(src, dst_surface, dst);
94 }
95
96 /**
97 * \brief Returns whether tiles having this tile pattern are drawn at their
98 * position.
99 *
100 * Usually, this function returns true, and when it is the case, draw() is
101 * called only for tiles that are located in the current viewport.
102 *
103 * However, some tile patterns may want to be drawn even when they are not
104 * in the viewport, typically to make an illusion of movement like parallax
105 * scrolling.
106 *
107 * \return true to if this tile pattern is always drawn at its coordinates
108 */
is_drawn_at_its_position() const109 bool AnimatedTilePattern::is_drawn_at_its_position() const {
110 return !parallax;
111 }
112
113 }
114
115