tilemap.hpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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 "squirrel/exposed_object.hpp"
  26. #include "scripting/tilemap.hpp"
  27. #include "supertux/autotile.hpp"
  28. #include "supertux/game_object.hpp"
  29. #include "video/color.hpp"
  30. #include "video/flip.hpp"
  31. #include "video/drawing_target.hpp"
  32. class DrawingContext;
  33. class CollisionObject;
  34. class CollisionGroundMovementManager;
  35. class Tile;
  36. class TileSet;
  37. /** This class is responsible for drawing the level tiles */
  38. class TileMap final :
  39. public GameObject,
  40. public ExposedObject<TileMap, scripting::TileMap>,
  41. public PathObject
  42. {
  43. public:
  44. TileMap(const TileSet *tileset);
  45. TileMap(const TileSet *tileset, const ReaderMapping& reader);
  46. ~TileMap() override;
  47. virtual void finish_construction() override;
  48. static std::string class_name() { return "tilemap"; }
  49. virtual std::string get_class_name() const override { return class_name(); }
  50. virtual const std::string get_icon_path() const override { return "images/engine/editor/tilemap.png"; }
  51. static std::string display_name() { return _("Tilemap"); }
  52. virtual std::string get_display_name() const override { return display_name(); }
  53. virtual ObjectSettings get_settings() override;
  54. virtual void after_editor_set() override;
  55. void save_state() override;
  56. void check_state() override;
  57. virtual void update(float dt_sec) override;
  58. virtual void draw(DrawingContext& context) override;
  59. virtual void editor_update() override;
  60. virtual void on_flip(float height) override;
  61. /** Move tilemap until at given node, then stop */
  62. void goto_node(int node_idx);
  63. /** Instantly jump to the given node */
  64. void jump_to_node(int node_idx, bool instantaneous = false);
  65. /** Start moving tilemap */
  66. void start_moving();
  67. /** Stop tilemap at next node */
  68. void stop_moving();
  69. void set(int width, int height, const std::vector<unsigned int>& vec,
  70. int z_pos, bool solid);
  71. /** resizes the tilemap to a new width and height (tries to not
  72. destroy the existing map) */
  73. void resize(int newwidth, int newheight, int fill_id = 0,
  74. int xoffset = 0, int yoffset = 0);
  75. void resize(const Size& newsize, const Size& resize_offset);
  76. int get_width() const { return m_width; }
  77. int get_height() const { return m_height; }
  78. Size get_size() const { return Size(m_width, m_height); }
  79. void set_offset(const Vector &offset_) { m_offset = offset_; }
  80. Vector get_offset() const { return m_offset; }
  81. void set_ground_movement_manager(const std::shared_ptr<CollisionGroundMovementManager>& movement_manager)
  82. {
  83. m_ground_movement_manager = movement_manager;
  84. }
  85. void move_by(const Vector& pos);
  86. /** Get the movement of this tilemap. The collision detection code
  87. may need a non-negative y-movement. Passing `false' as the
  88. `actual' argument will provide that. Used exclusively in
  89. src/supertux/sector.cpp. */
  90. Vector get_movement(bool actual) const
  91. {
  92. if (actual) {
  93. return m_movement;
  94. }
  95. return Vector(m_movement.x, std::max(0.0f, m_movement.y));
  96. }
  97. /** Returns the position of the upper-left corner of tile (x, y) in
  98. the sector. */
  99. Vector get_tile_position(int x, int y) const
  100. { return m_offset + Vector(static_cast<float>(x), static_cast<float>(y)) * 32.0f; }
  101. Rectf get_bbox() const {
  102. return Rectf(get_tile_position(0, 0),
  103. get_tile_position(m_width, m_height));
  104. }
  105. Rectf get_tile_bbox(int x, int y) const {
  106. return Rectf(get_tile_position(x, y),
  107. get_tile_position(x + 1, y + 1));
  108. }
  109. /** Returns the half-open rectangle of (x, y) tile indices that
  110. overlap the given rectangle in the sector. */
  111. Rect get_tiles_overlapping(const Rectf &rect) const;
  112. /** Called by the collision mechanism to indicate that this tilemap has been hit on
  113. the top, i.e. has hit a moving object on the bottom of its collision rectangle. */
  114. void hits_object_bottom(CollisionObject& object);
  115. void notify_object_removal(CollisionObject* other);
  116. int get_layer() const { return m_z_pos; }
  117. void set_layer(int layer) { m_z_pos = layer; }
  118. bool is_solid() const { return m_real_solid && m_effective_solid; }
  119. /** Changes Tilemap's solidity, i.e. whether to consider it when
  120. doing collision detection. */
  121. void set_solid(bool solid = true);
  122. bool is_outside_bounds(const Vector& pos) const;
  123. const Tile& get_tile(int x, int y) const;
  124. const Tile& get_tile_at(const Vector& pos) const;
  125. uint32_t get_tile_id(int x, int y) const;
  126. uint32_t get_tile_id_at(const Vector& pos) const;
  127. void change(int x, int y, uint32_t newtile);
  128. void change_at(const Vector& pos, uint32_t newtile);
  129. /** changes all tiles with the given ID */
  130. void change_all(uint32_t oldtile, uint32_t newtile);
  131. /** Puts the correct autotile block at the given position */
  132. void autotile(int x, int y, uint32_t tile);
  133. enum class AutotileCornerOperation {
  134. ADD_TOP_LEFT,
  135. ADD_TOP_RIGHT,
  136. ADD_BOTTOM_LEFT,
  137. ADD_BOTTOM_RIGHT,
  138. REMOVE_TOP_LEFT,
  139. REMOVE_TOP_RIGHT,
  140. REMOVE_BOTTOM_LEFT,
  141. REMOVE_BOTTOM_RIGHT,
  142. };
  143. /** Puts the correct autotile blocks at the tiles around the given corner */
  144. void autotile_corner(int x, int y, uint32_t tile, AutotileCornerOperation op);
  145. /** Erases in autotile mode */
  146. void autotile_erase(const Vector& pos, const Vector& corner_pos);
  147. /** Returns the Autotileset associated with the given tile */
  148. AutotileSet* get_autotileset(uint32_t tile) const;
  149. void set_flip(Flip flip) { m_flip = flip; }
  150. Flip get_flip() const { return m_flip; }
  151. /** Start fading the tilemap to opacity given by @c alpha.
  152. Destination opacity will be reached after @c seconds seconds.
  153. Also influences solidity. */
  154. void fade(float alpha, float seconds = 0);
  155. /** Start fading the tilemap to tint given by RGBA.
  156. Destination opacity will be reached after @c seconds seconds. Doesn't influence solidity. */
  157. void tint_fade(const Color& new_tint, float seconds = 0);
  158. Color get_current_tint() const { return m_current_tint; }
  159. /** Instantly switch tilemap's opacity to @c alpha. Also influences solidity. */
  160. void set_alpha(float alpha);
  161. /** Return tilemap's opacity. Note that while the tilemap is fading
  162. in or out, this will return the current alpha value, not the
  163. target alpha. */
  164. float get_alpha() const;
  165. float get_target_alpha() const { return m_alpha; }
  166. void set_tileset(const TileSet* new_tileset);
  167. const std::vector<uint32_t>& get_tiles() const { return m_tiles; }
  168. private:
  169. void update_effective_solid(bool update_manager = true);
  170. void float_channel(float target, float &current, float remaining_time, float dt_sec);
  171. bool is_corner(uint32_t tile) const;
  172. void apply_offset_x(int fill_id, int xoffset);
  173. void apply_offset_y(int fill_id, int yoffset);
  174. public:
  175. bool m_editor_active;
  176. private:
  177. const TileSet* m_tileset;
  178. typedef std::vector<uint32_t> Tiles;
  179. Tiles m_tiles;
  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. float m_speed_x;
  186. float m_speed_y;
  187. int m_width;
  188. int m_height;
  189. int m_z_pos;
  190. Vector m_offset;
  191. Vector m_movement; /**< The movement that happened last frame */
  192. /** Objects that were touching the top of a solid tile at the last frame */
  193. std::unordered_set<CollisionObject*> m_objects_hit_bottom;
  194. std::shared_ptr<CollisionGroundMovementManager> m_ground_movement_manager;
  195. Flip m_flip;
  196. float m_alpha; /**< requested tilemap opacity */
  197. float m_current_alpha; /**< current tilemap opacity */
  198. float m_remaining_fade_time; /**< seconds until requested tilemap opacity is reached */
  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. /** Set to LIGHTMAP to draw to lightmap */
  206. DrawingTarget m_draw_target;
  207. int m_new_size_x;
  208. int m_new_size_y;
  209. int m_new_offset_x;
  210. int m_new_offset_y;
  211. bool m_add_path;
  212. int m_starting_node;
  213. private:
  214. TileMap(const TileMap&) = delete;
  215. TileMap& operator=(const TileMap&) = delete;
  216. };
  217. #endif
  218. /* EOF */