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 #ifndef SOLARUS_MAP_H
18 #define SOLARUS_MAP_H
19
20 #include "solarus/core/Common.h"
21 #include "solarus/core/Debug.h"
22 #include "solarus/core/MapData.h"
23 #include "solarus/core/Rectangle.h"
24 #include "solarus/entities/CameraPtr.h"
25 #include "solarus/entities/Entities.h"
26 #include "solarus/entities/Ground.h"
27 #include "solarus/entities/TilePattern.h"
28 #include "solarus/entities/Tileset.h"
29 #include "solarus/graphics/SurfacePtr.h"
30 #include "solarus/graphics/Transition.h"
31 #include "solarus/lua/ExportableToLua.h"
32
33 namespace Solarus {
34
35 class Destination;
36 class InputEvent;
37 class LuaContext;
38 class Tileset;
39 class Sprite;
40
41 /**
42 * \brief Represents a map where the game can take place.
43 *
44 * A map is a game scene. It contains various information, including:
45 * - its dimensions,
46 * - the tileset,
47 * - the tiles and the other entities placed on the map,
48 * - the ground of each 8x8 square,
49 * - the background music.
50 */
51 class SOLARUS_API Map: public ExportableToLua {
52
53 public:
54
55 // creation and destruction
56 explicit Map(const std::string& id);
57
58 // map properties
59 const std::string& get_id() const;
60 const Tileset& get_tileset() const;
61 const std::string& get_tileset_id() const;
62 void set_tileset(const std::string& tileset_id);
63 const std::string& get_music_id() const;
64 bool has_world() const;
65 const std::string& get_world() const;
66 void set_world(const std::string& world);
67 bool has_floor() const;
68 int get_floor() const;
69 void set_floor(int floor);
70 const Rectangle& get_location() const;
71
72 Size get_size() const;
73 int get_width() const;
74 int get_height() const;
75 int get_width8() const;
76 int get_height8() const;
77
78 int get_min_layer() const;
79 int get_max_layer() const;
80 bool is_valid_layer(int layer) const;
81
82 // camera
83 const CameraPtr& get_camera() const;
84 SurfacePtr get_camera_surface(); // TODO remove
85
86 // loading
87 bool is_loaded() const;
88 void load(Game& game);
89 void unload();
90 Game& get_game();
91 const std::shared_ptr<Savegame>& get_savegame();
92 bool is_game_running() const;
93 LuaContext& get_lua_context();
94 virtual const std::string& get_lua_type_name() const override;
95
96 void notify_opening_transition_finished();
97
98 // entities
99 Entities& get_entities();
100 const Entities& get_entities() const;
101
102 // presence of the hero
103 bool is_started() const;
104 void start();
105 void leave();
106
107 // current destination point
108 void set_destination(const std::string& destination_name);
109 const std::string& get_destination_name() const;
110 std::shared_ptr<Destination> get_destination();
111 int get_destination_side() const;
112
113 // collisions with obstacles (checked before a move)
114 bool test_collision_with_border(int x, int y) const;
115 bool test_collision_with_border(const Point& point) const;
116 bool test_collision_with_border(const Rectangle& collision_box) const;
117 bool test_collision_with_ground(
118 int layer,
119 int x,
120 int y,
121 const Entity& entity_to_check,
122 bool& found_diagonal_wall
123 ) const;
124 bool test_collision_with_entities(
125 int layer,
126 const Rectangle& collision_box,
127 Entity& entity_to_check
128 );
129 bool test_collision_with_obstacles(
130 int layer,
131 const Rectangle& collision_box,
132 Entity& entity_to_check
133 );
134 bool test_collision_with_obstacles(
135 int layer,
136 int x,
137 int y,
138 Entity& entity_to_check
139 );
140 bool test_collision_with_obstacles(
141 int layer,
142 const Point& point,
143 Entity& entity_to_check
144 );
145 bool has_empty_ground(
146 int layer,
147 const Rectangle& collision_box
148 ) const;
149
150 Ground get_ground(
151 int layer,
152 int x,
153 int y,
154 const Entity* entity_to_check
155 ) const;
156 Ground get_ground(
157 int layer,
158 const Point& xy,
159 const Entity* entity_to_check
160 ) const;
161 Ground get_ground_from_entity(const Entity& entity, int x, int y) const;
162 Ground get_ground_from_entity(const Entity& entity, const Point& xy) const;
163
164 // collisions with detectors (checked after a move)
165 void check_collision_with_detectors(Entity& entity);
166 void check_collision_with_detectors(Entity& entity, Sprite& sprite);
167 void check_collision_from_detector(Entity& detector);
168 void check_collision_from_detector(Entity& detector, Sprite& detector_sprite);
169
170 // main loop
171 bool notify_input(const InputEvent& event);
172 void update();
173 bool is_suspended() const;
174 void check_suspended();
175 void draw();
176 void draw_visual(Drawable& drawable, const Point& xy,
177 const Rectangle& clipping_area);
178 void draw_visual(Drawable& drawable, const Point& xy);
179 void draw_visual(Drawable& drawable, int x, int y);
180 void draw_visual(Drawable& drawable, int x, int y,
181 const Rectangle& clipping_area);
182
183 private:
184
185 void set_suspended(bool suspended);
186 void build_background_surface();
187 void build_foreground_surface();
188 void draw_background(const SurfacePtr& dst_surface);
189 void draw_foreground(const SurfacePtr& dst_surface);
190
191 // map properties
192
193 std::shared_ptr<Savegame>
194 savegame; /**< The savegame associated to the game.
195 * Persists even after the game is destroyed. */
196 std::string id; /**< Id of this map. */
197
198 int width8; /**< Map width in 8x8 squares (width8 = get_width() / 8). */
199 int height8; /**< Map height in 8x8 squares (height8 = get_height() / 8). */
200 int min_layer; /**< Lowest layer of the map (0 or less). */
201 int max_layer; /**< Highest layer of the map (0 or more). */
202
203 std::string tileset_id; /**< Id of the current tileset. */
204 Tileset* tileset; /**< Tileset of the map: every tile of this map
205 * is extracted from this tileset. */
206
207 std::string music_id; /**< Id of the current music of the map:
208 * can be a valid music, Music::none or Music::unchanged. */
209
210 std::string world; /**< Name of the context where this map is. When changing context,
211 * the savegame starting position is set and crystal switches are reset. */
212
213 int floor; /**< The floor where this map is (possibly MapData::NO_FLOOR). */
214
215 Rectangle location; /**< Location of the map in its context: the width and height fields
216 * indicate the map size in pixel, and the x and y field indicate the position.
217 * This is used to correctly scroll between adjacent maps. */
218
219 // Quest screen
220 SurfacePtr
221 background_surface; /**< A surface filled with the background color of the tileset. */
222 SurfacePtr
223 foreground_surface; /**< A surface with black bars when the map is smaller than the screen. */
224
225 // map state
226 bool loaded; /**< Whether the loading phase is done. */
227 bool started; /**< Whether this map is the current map. */
228 std::string destination_name; /**< Current destination point on the map,
229 * or "_same" to keep the hero's coordinates,
230 * or "_side0", "_side1", "_side2" or "_side3"
231 * to place the hero on a side of the map,
232 * or an empty string to use the one saved. */
233
234 std::unique_ptr<Entities>
235 entities; /**< The entities on the map. */
236 bool suspended; /**< Whether the game is suspended. */
237 };
238
239 /**
240 * \brief Tests whether a point is outside the map area.
241 * \param x x of the point to check.
242 * \param y y of the point to check.
243 * \return true if this point is outside the map area.
244 */
test_collision_with_border(int x,int y)245 inline bool Map::test_collision_with_border(int x, int y) const {
246
247 return (x < 0 || y < 0 || x >= location.get_width() || y >= location.get_height());
248 }
249
250 /**
251 * \brief Tests whether a point is outside the map area.
252 * \param point point to check.
253 * \return true if this point is outside the map area.
254 */
test_collision_with_border(const Point & point)255 inline bool Map::test_collision_with_border(const Point& point) const {
256
257 return test_collision_with_border(point.x, point.y);
258 }
259
260 /**
261 * \brief Returns the tileset associated to this map.
262 * \return The tileset.
263 */
get_tileset()264 inline const Tileset& Map::get_tileset() const {
265
266 SOLARUS_ASSERT(tileset != nullptr,
267 std::string("Missing tileset in map '") + get_id() + "'"
268 );
269 return *tileset;
270 }
271
272 /**
273 * \brief Returns the entities of the map.
274 *
275 * This function should not be called before the map is loaded into a game.
276 *
277 * \return The entities of the map.
278 */
get_entities()279 inline const Entities& Map::get_entities() const {
280 return *entities;
281 }
282
283 /**
284 * \overload Non-const version.
285 */
get_entities()286 inline Entities& Map::get_entities() {
287 return *entities;
288 }
289
290 /**
291 * \brief Returns the camera of the map.
292 * \return The camera, or nullptr if there is no camera.
293 */
get_camera()294 inline const CameraPtr& Map::get_camera() const {
295
296 return get_entities().get_camera();
297 }
298
299 }
300
301 #endif
302
303