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#ifndef HEADER_SUPERTUX_OBJECT_TILEMAP_HPP
18#define HEADER_SUPERTUX_OBJECT_TILEMAP_HPP
19
20#include <algorithm>
21
22#include "math/rect.hpp"
23#include "math/rectf.hpp"
24#include "math/size.hpp"
25#include "object/path_object.hpp"
26#include "object/path_walker.hpp"
27#include "squirrel/exposed_object.hpp"
28#include "scripting/tilemap.hpp"
29#include "supertux/game_object.hpp"
30#include "video/color.hpp"
31#include "video/flip.hpp"
32#include "video/drawing_target.hpp"
33
34class DrawingContext;
35class Tile;
36class TileSet;
37
38/** This class is responsible for drawing the level tiles */
39class TileMap final :
40 public GameObject,
41 public ExposedObject<TileMap, scripting::TileMap>,
42 public PathObject
43{
44public:
45 TileMap(const TileSet *tileset);
46 TileMap(const TileSet *tileset, const ReaderMapping& reader);
47 virtual ~TileMap();
48
49 virtual void finish_construction() override;
50
51 virtual std::string get_class() const override { return "tilemap"; }
52 virtual const std::string get_icon_path() const override { return "images/engine/editor/tilemap.png"; }
53 virtual std::string get_display_name() const override { return _("Tilemap"); }
54
55 virtual ObjectSettings get_settings() override;
56 virtual void after_editor_set() override;
57
58 virtual void update(float dt_sec) override;
59 virtual void draw(DrawingContext& context) override;
60
61 virtual void editor_update() override;
62
63 /** Move tilemap until at given node, then stop */
64 void goto_node(int node_no);
65
66 /** Start moving tilemap */
67 void start_moving();
68
69 /** Stop tilemap at next node */
70 void stop_moving();
71
72 void set(int width, int height, const std::vector<unsigned int>& vec,
73 int z_pos, bool solid);
74
75 /** resizes the tilemap to a new width and height (tries to not
76 destroy the existing map) */
77 void resize(int newwidth, int newheight, int fill_id = 0,
78 int xoffset = 0, int yoffset = 0);
79 void resize(const Size& newsize, const Size& resize_offset);
80
81 int get_width() const { return m_width; }
82 int get_height() const { return m_height; }
83 Size get_size() const { return Size(m_width, m_height); }
84
85 void set_offset(const Vector &offset_) { m_offset = offset_; }
86 Vector get_offset() const { return m_offset; }
87
88 void move_by(const Vector& pos);
89
90 /** Get the movement of this tilemap. The collision detection code
91 may need a non-negative y-movement. Passing `false' as the
92 `actual' argument will provide that. Used exclusively in
93 src/supertux/sector.cpp. */
94 Vector get_movement(bool actual) const
95 {
96 if (actual) {
97 return m_movement;
98 } else {
99 return Vector(m_movement.x, std::max(0.0f, m_movement.y));
100 }
101 }
102
103 /** Returns the position of the upper-left corner of tile (x, y) in
104 the sector. */
105 Vector get_tile_position(int x, int y) const
106 { return m_offset + Vector(static_cast<float>(x), static_cast<float>(y)) * 32.0f; }
107
108 Rectf get_bbox() const {
109 return Rectf(get_tile_position(0, 0),
110 get_tile_position(m_width, m_height));
111 }
112
113 Rectf get_tile_bbox(int x, int y) const {
114 return Rectf(get_tile_position(x, y),
115 get_tile_position(x + 1, y + 1));
116 }
117
118 /** Returns the half-open rectangle of (x, y) tile indices that
119 overlap the given rectangle in the sector. */
120 Rect get_tiles_overlapping(const Rectf &rect) const;
121
122 int get_layer() const { return m_z_pos; }
123 void set_layer(int layer_) { m_z_pos = layer_; }
124
125 bool is_solid() const { return m_real_solid && m_effective_solid; }
126
127 /** Changes Tilemap's solidity, i.e. whether to consider it when
128 doing collision detection. */
129 void set_solid(bool solid = true);
130
131 const Tile& get_tile(int x, int y) const;
132 const Tile& get_tile_at(const Vector& pos) const;
133 uint32_t get_tile_id(int x, int y) const;
134 uint32_t get_tile_id_at(const Vector& pos) const;
135
136 void change(int x, int y, uint32_t newtile);
137
138 void change_at(const Vector& pos, uint32_t newtile);
139
140 /** changes all tiles with the given ID */
141 void change_all(uint32_t oldtile, uint32_t newtile);
142
143 void set_flip(Flip flip) { m_flip = flip; }
144 Flip get_flip() const { return m_flip; }
145
146 /** Start fading the tilemap to opacity given by @c alpha.
147 Destination opacity will be reached after @c seconds seconds.
148 Also influences solidity. */
149 void fade(float alpha, float seconds = 0);
150
151 /** Start fading the tilemap to tint given by RGBA.
152 Destination opacity will be reached after @c seconds seconds. Doesn't influence solidity. */
153 void tint_fade(const Color& new_tint, float seconds = 0);
154
155 /** Instantly switch tilemap's opacity to @c alpha. Also influences solidity. */
156 void set_alpha(float alpha);
157
158 /** Return tilemap's opacity. Note that while the tilemap is fading
159 in or out, this will return the current alpha value, not the
160 target alpha. */
161 float get_alpha() const;
162
163 void set_tileset(const TileSet* new_tileset);
164
165 const std::vector<uint32_t>& get_tiles() const { return m_tiles; }
166
167private:
168 void update_effective_solid();
169 void float_channel(float target, float &current, float remaining_time, float dt_sec);
170
171public:
172 bool m_editor_active;
173
174private:
175 const TileSet* m_tileset;
176
177 typedef std::vector<uint32_t> Tiles;
178 Tiles m_tiles;
179
180 /* read solid: In *general*, is this a solid layer? effective solid:
181 is the layer *currently* solid? A generally solid layer may be
182 not solid when its alpha is low. See `is_solid' above. */
183 bool m_real_solid;
184 bool m_effective_solid;
185
186 float m_speed_x;
187 float m_speed_y;
188 int m_width;
189 int m_height;
190 int m_z_pos;
191 Vector m_offset;
192 Vector m_movement; /**< The movement that happened last frame */
193
194 Flip m_flip;
195 float m_alpha; /**< requested tilemap opacity */
196 float m_current_alpha; /**< current tilemap opacity */
197 float m_remaining_fade_time; /**< seconds until requested tilemap opacity is reached */
198
199 /** The tint can have its own alpha channel, but this alpha channel doesn't affect
200 the solidity of the tilemap. This alpha channel makes the tilemap only less or
201 more translucent.*/
202 Color m_tint; /**< requested tilemap tint */
203 Color m_current_tint; /**< current tilemap tint */
204 float m_remaining_tint_fade_time; /**< seconds until requested tilemap tint is reached */
205
206 /** Is the tilemap currently moving (following the path) */
207 bool m_running;
208
209 /** Set to LIGHTMAP to draw to lightmap */
210 DrawingTarget m_draw_target;
211
212 int m_new_size_x;
213 int m_new_size_y;
214 int m_new_offset_x;
215 int m_new_offset_y;
216 bool m_add_path;
217
218private:
219 TileMap(const TileMap&) = delete;
220 TileMap& operator=(const TileMap&) = delete;
221};
222
223#endif
224
225/* EOF */
226