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 |
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 | |
34 | class DrawingContext; |
35 | class Tile; |
36 | class TileSet; |
37 | |
38 | /** This class is responsible for drawing the level tiles */ |
39 | class TileMap final : |
40 | public GameObject, |
41 | public ExposedObject<TileMap, scripting::TileMap>, |
42 | public PathObject |
43 | { |
44 | public: |
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 | |
167 | private: |
168 | void update_effective_solid(); |
169 | void float_channel(float target, float ¤t, float remaining_time, float dt_sec); |
170 | |
171 | public: |
172 | bool m_editor_active; |
173 | |
174 | private: |
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 | |
218 | private: |
219 | TileMap(const TileMap&) = delete; |
220 | TileMap& operator=(const TileMap&) = delete; |
221 | }; |
222 | |
223 | #endif |
224 | |
225 | /* EOF */ |
226 | |