tilemap.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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. #ifndef HEADER_SUPERTUX_OBJECT_TILEMAP_HPP
  17. #define HEADER_SUPERTUX_OBJECT_TILEMAP_HPP
  18. #include <algorithm>
  19. #include <unordered_set>
  20. #include "math/rect.hpp"
  21. #include "math/rectf.hpp"
  22. #include "math/size.hpp"
  23. #include "object/path_object.hpp"
  24. #include "object/path_walker.hpp"
  25. #include "supertux/autotile.hpp"
  26. #include "supertux/game_object.hpp"
  27. #include "video/color.hpp"
  28. #include "video/flip.hpp"
  29. #include "video/drawing_target.hpp"
  30. class CollisionObject;
  31. class CollisionGroundMovementManager;
  32. class DrawingContext;
  33. class Tile;
  34. class TileSet;
  35. /**
  36. * This class is responsible for managing an array of tiles.
  37. * @scripting
  38. * @summary A ""TileMap"" that was given a name can be controlled by scripts.
  39. The tilemap can be moved by specifying a path for it.
  40. * @instances A ""TileMap"" is instantiated by placing a definition inside a level.
  41. It can then be accessed by its name from a script or via ""sector.name"" from the console.
  42. */
  43. class TileMap final : public GameObject,
  44. public PathObject
  45. {
  46. public:
  47. static void register_class(ssq::VM& vm);
  48. public:
  49. TileMap(const TileSet *tileset);
  50. TileMap(const TileSet *tileset, const ReaderMapping& reader);
  51. ~TileMap() override;
  52. virtual void finish_construction() override;
  53. static std::string class_name() { return "tilemap"; }
  54. virtual std::string get_class_name() const override { return class_name(); }
  55. virtual std::string get_exposed_class_name() const override { return "TileMap"; }
  56. virtual const std::string get_icon_path() const override { return "images/engine/editor/tilemap.png"; }
  57. static std::string display_name() { return _("Tilemap"); }
  58. virtual std::string get_display_name() const override { return display_name(); }
  59. virtual GameObjectClasses get_class_types() const override { return GameObject::get_class_types().add(typeid(PathObject)).add(typeid(TileMap)); }
  60. virtual ObjectSettings get_settings() override;
  61. virtual void after_editor_set() override;
  62. void save_state() override;
  63. void check_state() override;
  64. virtual void update(float dt_sec) override;
  65. virtual void draw(DrawingContext& context) override;
  66. virtual void editor_update() override;
  67. virtual void on_flip(float height) override;
  68. void set(int width, int height, const std::vector<unsigned int>& vec,
  69. int z_pos, bool solid);
  70. /** resizes the tilemap to a new width and height (tries to not
  71. destroy the existing map) */
  72. void resize(int newwidth, int newheight, int fill_id = 0,
  73. int xoffset = 0, int yoffset = 0);
  74. void resize(const Size& newsize, const Size& resize_offset);
  75. int get_width() const { return m_width; }
  76. int get_height() const { return m_height; }
  77. Size get_size() const { return Size(m_width, m_height); }
  78. void set_offset(const Vector &offset_) { m_offset = offset_; }
  79. Vector get_offset() const { return m_offset; }
  80. void set_ground_movement_manager(const std::shared_ptr<CollisionGroundMovementManager>& movement_manager)
  81. {
  82. m_ground_movement_manager = movement_manager;
  83. }
  84. void move_by(const Vector& pos);
  85. /** Get the movement of this tilemap. The collision detection code
  86. may need a non-negative y-movement. Passing `false' as the
  87. `actual' argument will provide that. Used exclusively in
  88. src/supertux/sector.cpp. */
  89. Vector get_movement(bool actual) const
  90. {
  91. if (actual) {
  92. return m_movement;
  93. }
  94. return Vector(m_movement.x, std::max(0.0f, m_movement.y));
  95. }
  96. /** Returns the position of the upper-left corner of tile (x, y) in
  97. the sector. */
  98. Vector get_tile_position(int x, int y) const
  99. { return m_offset + Vector(static_cast<float>(x), static_cast<float>(y)) * 32.0f; }
  100. Rectf get_bbox() const {
  101. return Rectf(get_tile_position(0, 0),
  102. get_tile_position(m_width, m_height));
  103. }
  104. Rectf get_tile_bbox(int x, int y) const {
  105. return Rectf(get_tile_position(x, y),
  106. get_tile_position(x + 1, y + 1));
  107. }
  108. /** Returns the half-open rectangle of (x, y) tile indices that
  109. overlap the given rectangle in the sector. */
  110. Rect get_tiles_overlapping(const Rectf &rect) const;
  111. /** Called by the collision mechanism to indicate that this tilemap has been hit on
  112. the top, i.e. has hit a moving object on the bottom of its collision rectangle. */
  113. void hits_object_bottom(CollisionObject& object);
  114. void notify_object_removal(CollisionObject* other);
  115. int get_layer() const { return m_z_pos; }
  116. void set_layer(int layer) { m_z_pos = layer; }
  117. bool is_solid() const { return m_real_solid && m_effective_solid; }
  118. /**
  119. * @scripting
  120. * @description Switches the tilemap's real solidity to ""solid"".${SRG_TABLENEWPARAGRAPH}
  121. Note: The effective solidity is also influenced by the alpha of the tilemap.
  122. * @param bool $solid
  123. */
  124. void set_solid(bool solid = true);
  125. /**
  126. * @scripting
  127. * @description Returns the effective solidity of the tilemap.
  128. */
  129. bool get_solid() const;
  130. bool is_outside_bounds(const Vector& pos) const;
  131. const Tile& get_tile(int x, int y) const;
  132. const Tile& get_tile_at(const Vector& pos) const;
  133. /**
  134. * @scripting
  135. * @description Returns the ID of the tile at the given coordinates or 0 if out of bounds.
  136. The origin is at the top left.
  137. * @param int $x
  138. * @param int $y
  139. */
  140. uint32_t get_tile_id(int x, int y) const;
  141. /**
  142. * @scripting
  143. * @description Returns the ID of the tile at the given position (in world coordinates).
  144. * @param float $x
  145. * @param float $y
  146. */
  147. uint32_t get_tile_id_at(float x, float y) const;
  148. uint32_t get_tile_id_at(const Vector& pos) const;
  149. /**
  150. * @scripting
  151. * @description Changes the tile at the given coordinates to ""newtile"".
  152. The origin is at the top left.
  153. * @param int $x
  154. * @param int $y
  155. * @param int $newtile
  156. */
  157. void change(int x, int y, uint32_t newtile);
  158. /**
  159. * @scripting
  160. * @description Changes the tile at the given position (in-world coordinates) to ""newtile"".
  161. * @param float $x
  162. * @param float $y
  163. * @param int $newtile
  164. */
  165. void change_at(float x, float y, uint32_t newtile);
  166. void change_at(const Vector& pos, uint32_t newtile);
  167. /**
  168. * @scripting
  169. * @description Changes all tiles with the given ID.
  170. * @param int $oldtile
  171. * @param int $newtile
  172. */
  173. void change_all(uint32_t oldtile, uint32_t newtile);
  174. /** Puts the correct autotile block at the given position */
  175. void autotile(int x, int y, uint32_t tile);
  176. enum class AutotileCornerOperation {
  177. ADD_TOP_LEFT,
  178. ADD_TOP_RIGHT,
  179. ADD_BOTTOM_LEFT,
  180. ADD_BOTTOM_RIGHT,
  181. REMOVE_TOP_LEFT,
  182. REMOVE_TOP_RIGHT,
  183. REMOVE_BOTTOM_LEFT,
  184. REMOVE_BOTTOM_RIGHT,
  185. };
  186. /** Puts the correct autotile blocks at the tiles around the given corner */
  187. void autotile_corner(int x, int y, uint32_t tile, AutotileCornerOperation op);
  188. /** Erases in autotile mode */
  189. void autotile_erase(const Vector& pos, const Vector& corner_pos);
  190. /** Returns the Autotileset associated with the given tile */
  191. AutotileSet* get_autotileset(uint32_t tile) const;
  192. void set_flip(Flip flip) { m_flip = flip; }
  193. Flip get_flip() const { return m_flip; }
  194. /**
  195. * @scripting
  196. * @description Starts fading the tilemap to the opacity given by ""alpha"".
  197. Destination opacity will be reached after ""time"" seconds. Also influences solidity.
  198. * @param float $alpha
  199. * @param float $time
  200. */
  201. void fade(float alpha, float time);
  202. /** Start fading the tilemap to tint given by RGBA.
  203. Destination opacity will be reached after @c seconds seconds. Doesn't influence solidity. */
  204. void tint_fade(const Color& new_tint, float time = 0.f);
  205. /**
  206. * @scripting
  207. * @description Starts fading the tilemap to tint given by RGBA.
  208. Destination opacity will be reached after ""time"" seconds. Doesn't influence solidity.
  209. * @param float $time
  210. * @param float $red
  211. * @param float $green
  212. * @param float $blue
  213. * @param float $alpha
  214. */
  215. void tint_fade(float time, float red, float green, float blue, float alpha);
  216. Color get_current_tint() const { return m_current_tint; }
  217. /**
  218. * @scripting
  219. * @description Instantly switches the tilemap's opacity to ""alpha"". Also influences solidity.
  220. * @param float $alpha
  221. */
  222. void set_alpha(float alpha);
  223. /**
  224. * @scripting
  225. * @description Returns the tilemap's opacity.${SRG_TABLENEWPARAGRAPH}
  226. Note: While the tilemap is fading in or out, this will return the current alpha value, not the target alpha.
  227. */
  228. float get_alpha() const;
  229. float get_target_alpha() const { return m_alpha; }
  230. void set_tileset(const TileSet* new_tileset);
  231. const std::vector<uint32_t>& get_tiles() const { return m_tiles; }
  232. private:
  233. void update_effective_solid(bool update_manager = true);
  234. void float_channel(float target, float &current, float remaining_time, float dt_sec);
  235. bool is_corner(uint32_t tile) const;
  236. void apply_offset_x(int fill_id, int xoffset);
  237. void apply_offset_y(int fill_id, int yoffset);
  238. public:
  239. bool m_editor_active;
  240. private:
  241. const TileSet* m_tileset;
  242. typedef std::vector<uint32_t> Tiles;
  243. Tiles m_tiles;
  244. #ifdef DOXYGEN_SCRIPTING
  245. /**
  246. * @scripting
  247. * @description Equivalent to ""get_solid()"" and ""set_solid()"".
  248. */
  249. bool m_solid;
  250. #endif
  251. /* read solid: In *general*, is this a solid layer? effective solid:
  252. is the layer *currently* solid? A generally solid layer may be
  253. not solid when its alpha is low. See `is_solid' above. */
  254. bool m_real_solid;
  255. bool m_effective_solid;
  256. float m_speed_x;
  257. float m_speed_y;
  258. int m_width;
  259. int m_height;
  260. int m_z_pos;
  261. Vector m_offset;
  262. Vector m_movement; /**< The movement that happened last frame */
  263. /** Objects that were touching the top of a solid tile at the last frame */
  264. std::unordered_set<CollisionObject*> m_objects_hit_bottom;
  265. std::shared_ptr<CollisionGroundMovementManager> m_ground_movement_manager;
  266. Flip m_flip;
  267. /**
  268. * @scripting
  269. * @description Determines the tilemap's current opacity.
  270. */
  271. float m_alpha; /**< requested tilemap opacity */
  272. float m_current_alpha; /**< current tilemap opacity */
  273. float m_remaining_fade_time; /**< seconds until requested tilemap opacity is reached */
  274. /** The tint can have its own alpha channel, but this alpha channel doesn't affect
  275. the solidity of the tilemap. This alpha channel makes the tilemap only less or
  276. more translucent.*/
  277. Color m_tint; /**< requested tilemap tint */
  278. Color m_current_tint; /**< current tilemap tint */
  279. float m_remaining_tint_fade_time; /**< seconds until requested tilemap tint is reached */
  280. /** Set to LIGHTMAP to draw to lightmap */
  281. DrawingTarget m_draw_target;
  282. int m_new_size_x;
  283. int m_new_size_y;
  284. int m_new_offset_x;
  285. int m_new_offset_y;
  286. bool m_add_path;
  287. int m_starting_node;
  288. private:
  289. TileMap(const TileMap&) = delete;
  290. TileMap& operator=(const TileMap&) = delete;
  291. };
  292. #endif
  293. /* EOF */