1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright (C) 2004-2011 by The Allacrost Project 3 // Copyright (C) 2012-2016 by Bertram (Valyria Tear) 4 // All Rights Reserved 5 // 6 // This code is licensed under the GNU GPL version 2. It is free software 7 // and you may modify it and/or redistribute it under the terms of this license. 8 // See https://www.gnu.org/copyleft/gpl.html for details. 9 /////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef __MAP_OBJECT_HEADER__ 12 #define __MAP_OBJECT_HEADER__ 13 14 #include "modes/map/map_utils.h" 15 16 #include "engine/video/image.h" 17 /* 18 #include "modes/map/map_treasure_supervisor.h" 19 20 namespace vt_script { 21 class ReadScriptDescriptor; 22 } 23 24 namespace vt_mode_manager { 25 class ParticleEffect; 26 } 27 28 namespace vt_defs { 29 void BindModeCode(); 30 } 31 */ 32 namespace vt_map 33 { 34 35 class MapMode; 36 37 //! \brief Used to know on which draw layer the object should be registered. 38 enum MapObjectDrawLayer { 39 // Before ground layer object. Used to display flat object on ground. 40 FLATGROUND_OBJECT = 0, 41 // Ground objects, such as characters and props. 42 GROUND_OBJECT, 43 // TODO: Objects used as bridges, removing the map collision when they are visible. They are displayed as flat ground objects. 44 PASS_OBJECT, 45 // Object displayed above all map layers. 46 SKY_OBJECT, 47 // An object not registered to be drawn on one specific map layer, 48 // since it's has other means and shouldn't be taken in account for collisions. 49 // E.g.: Ambient sound objects. 50 NO_LAYER_OBJECT 51 }; 52 53 namespace private_map 54 { 55 56 // Update the alpha of the interaction icon according to its distance from the player sprite. 57 const float INTERACTION_ICON_VISIBLE_RANGE = 10.0f; 58 59 class ContextZone; 60 class MapSprite; 61 class MapZone; 62 class VirtualSprite; 63 64 /** **************************************************************************** 65 *** \brief Abstract class that represents objects on a map 66 *** 67 *** A map object can be anything from a sprite to a tree to a house. To state 68 *** it simply, a map object is a map image that is not tiled and need not be fixed 69 *** in place. Map objects are drawn in one of three layers: ground, pass, and sky 70 *** object layers. 71 72 *** All map objects have both a collision rectangle and an image rectangle. 73 *** The collision rectangle indicates what parts of the object may not overlap 74 *** with other collision rectangles and unwalkable sections of the map. The image 75 *** rectangle determines the size of the object as it is visible on the screen. 76 *** The collision rectangle and image rectangles do not need to be the same size. 77 *** Typically the collision rectangle is smaller than the image rectangle. It is 78 *** also possible to disable both rectangles via special properties that can be 79 *** enabled in this class. This would prevent the object from being a factor in 80 *** collision detection and/or it would never be drawn to the screen. 81 *** 82 *** State information about map objects may need to be retained upon leaving a 83 *** map. For example, a treasure (which is a type of map object) needs to know 84 *** whether or not the player has retrieved its contents already so that they 85 *** can not be gained a second time. This data is stored in the saved game file 86 *** so that even when the player exits the game, the state information can be 87 *** retrieved when the application starts again later. 88 *** 89 *** \note It is advised not to attempt to make map objects with dynamic sizes (i.e. 90 *** the various image frames that compose the object should all be the same size). 91 *** In theory, dynamically sized objects are feasible to implement in maps, but 92 *** they are much easier to be subject to bugs and other issues. 93 *** ***************************************************************************/ 94 class MapObject 95 { 96 public: 97 explicit MapObject(MapObjectDrawLayer layer); 98 virtual ~MapObject(); 99 100 /** \brief Updates the state of an object. 101 *** Many map objects may not actually have a use for this function. For example, animated objects 102 *** like a tree will automatically have their frames updated by the video engine in the draw 103 *** function. So it is the case that the implementation of this function in derived classes may 104 *** simply do nothing. 105 **/ 106 virtual void Update(); 107 108 /** \brief Draws the object to the frame buffer. 109 *** Objects are drawn differently depending on what type of object they are and what their current 110 *** state is. Note that calling this function does not guarantee that the object will be drawn. 111 *** Many implementations of this function in the derived classes first call the ShouldDraw() method 112 *** to determine if the object should be drawn at all. 113 **/ 114 virtual void Draw() = 0; 115 116 /** \brief Determines if an object should be drawn to the screen. 117 *** \return True if the object should be drawn. 118 *** \note This function also moves the draw cursor to the proper position if the object should be drawn 119 *** 120 *** This method performs the common drawing operations of identifying whether or not the object 121 *** is visible on the screen and moving the drawing cursor to its location. The children classes 122 *** of this class may choose to make use of it (or not). 123 **/ 124 bool ShouldDraw(); 125 //@} 126 127 //! \brief Retrieves the object type identifier GetObjectType()128 MAP_OBJECT_TYPE GetObjectType() const { 129 return _object_type; 130 } 131 132 /** \brief Tells whether the object is currently colliding with another object or a wall 133 *** \param pos_x The tile x position to test against a collision 134 *** \param pos_y The tile y position to test against a collision 135 **/ 136 bool IsColliding(float pos_x, float pos_y); 137 138 /** \brief Tells whether the object is currently colliding with another object or a wall 139 *** \param object The other object to test against a collision 140 **/ 141 bool IsCollidingWith(MapObject* other_object); 142 143 //! \brief Returns the collision rectangle for the current object on the map collision grid 144 vt_common::Rectangle2D GetGridCollisionRectangle() const; 145 146 /** \brief Returns the collision rectangle for the current object for the given position 147 *** \return rect A MapRectangle object storing the collision rectangle data 148 *** using the given position. 149 **/ 150 vt_common::Rectangle2D GetGridCollisionRectangle(float tile_x, float tile_y) const; 151 152 //! \brief Returns the collision rectangle for the current object. 153 vt_common::Rectangle2D GetScreenCollisionRectangle() const; 154 155 /** \brief Returns the collision rectangle for the current object for the given position 156 *** \return rect A MapRectangle object storing the collision rectangle data 157 *** using the given pixel position. 158 **/ 159 vt_common::Rectangle2D GetScreenCollisionRectangle(float screen_x, float screen_y) const; 160 161 /** \brief Returns the image rectangle for the current object 162 *** \param rect A MapRectangle object storing the image rectangle data 163 **/ 164 virtual vt_common::Rectangle2D GetScreenImageRectangle() const; 165 166 /** \brief Returns the image rectangle for the current object 167 *** \param rect A MapRectangle object storing the image rectangle data 168 **/ 169 virtual vt_common::Rectangle2D GetGridImageRectangle() const; 170 171 /** \brief Restores the saved state of the object 172 *** This state data is retained in the saved game file. When any map object is created and added 173 *** to the map, this function is called to load any stored state data that there may be. Notice 174 *** that the default implementation of this function does nothing. 175 **/ RestoreSaved()176 virtual void RestoreSaved() 177 {} 178 179 /** \name Lua Access Functions 180 *** These functions are specifically written to enable Lua to access the members of this class. 181 *** C++ code may also choose to use these functions, although all of the members here are public 182 *** so it is not mandatory to do so. 183 **/ 184 //@{ SetPosition(float x,float y)185 void SetPosition(float x, float y) { 186 _tile_position.x = x; 187 _tile_position.y = y; 188 } 189 SetXPosition(float x)190 void SetXPosition(float x) { 191 _tile_position.x = x; 192 } 193 SetYPosition(float y)194 void SetYPosition(float y) { 195 _tile_position.y = y; 196 } 197 198 //! \brief Set the object image half width (in pixels). 199 //! \note The value in map tiles is also stored. SetImgPixelHalfWidth(float width)200 void SetImgPixelHalfWidth(float width) { 201 _img_pixel_half_width = width; 202 _img_screen_half_width = width * MAP_ZOOM_RATIO; 203 _img_grid_half_width = width / GRID_LENGTH * MAP_ZOOM_RATIO; 204 } 205 206 //! \brief Set the object image half width (in pixels). 207 //! \note The value in map tiles is also stored. SetImgPixelHeight(float height)208 void SetImgPixelHeight(float height) { 209 _img_pixel_height = height; 210 _img_screen_height = height * MAP_ZOOM_RATIO; 211 _img_grid_height = height / GRID_LENGTH * MAP_ZOOM_RATIO; 212 } 213 SetCollPixelHalfWidth(float collision)214 void SetCollPixelHalfWidth(float collision) { 215 _coll_pixel_half_width = collision; 216 _coll_screen_half_width = collision * MAP_ZOOM_RATIO; 217 _coll_grid_half_width = collision / GRID_LENGTH * MAP_ZOOM_RATIO; 218 } 219 SetCollPixelHeight(float collision)220 void SetCollPixelHeight(float collision) { 221 _coll_pixel_height = collision; 222 _coll_screen_height = collision * MAP_ZOOM_RATIO; 223 _coll_grid_height = collision / GRID_LENGTH * MAP_ZOOM_RATIO; 224 } 225 SetUpdatable(bool update)226 void SetUpdatable(bool update) { 227 _updatable = update; 228 } 229 SetVisible(bool vis)230 void SetVisible(bool vis) { 231 _visible = vis; 232 } 233 234 // Use a set of COLLISION_TYPE bitmask values SetCollisionMask(uint32_t collision_types)235 void SetCollisionMask(uint32_t collision_types) { 236 _collision_mask = collision_types; 237 } 238 SetDrawOnSecondPass(bool pass)239 void SetDrawOnSecondPass(bool pass) { 240 _draw_on_second_pass = pass; 241 } 242 243 //! \brief Tells the draw layer for faster deletion from the object supervisor. GetObjectDrawLayer()244 MapObjectDrawLayer GetObjectDrawLayer() const { 245 return _draw_layer; 246 } 247 GetObjectID()248 int16_t GetObjectID() const { 249 return _object_id; 250 } 251 252 //! \brief Get the object position in tiles. GetPosition()253 vt_common::Position2D GetPosition() const { 254 return _tile_position; 255 } 256 GetXPosition()257 float GetXPosition() const { 258 return _tile_position.x; 259 } 260 GetYPosition()261 float GetYPosition() const { 262 return _tile_position.y; 263 } 264 GetImgScreenHalfWidth()265 float GetImgScreenHalfWidth() const { 266 return _img_screen_half_width; 267 } 268 GetImgScreenHeight()269 float GetImgScreenHeight() const { 270 return _img_screen_height; 271 } 272 GetCollGridHalfWidth()273 float GetCollGridHalfWidth() const { 274 return _coll_grid_half_width; 275 } 276 GetCollGridHeight()277 float GetCollGridHeight() const { 278 return _coll_grid_height; 279 } 280 IsUpdatable()281 bool IsUpdatable() const { 282 return _updatable; 283 } 284 IsVisible()285 bool IsVisible() const { 286 return _visible; 287 } 288 GetCollisionMask()289 uint32_t GetCollisionMask() const { 290 return _collision_mask; 291 } 292 IsDrawOnSecondPass()293 bool IsDrawOnSecondPass() const { 294 return _draw_on_second_pass; 295 } 296 GetType()297 MAP_OBJECT_TYPE GetType() const { 298 return _object_type; 299 } 300 301 virtual void SetGrayscale(bool grayscale = true) { 302 _grayscale = grayscale; 303 } 304 IsGrayscale()305 bool IsGrayscale() const { 306 return _grayscale; 307 } 308 309 /** \brief Play the corresponding emote animation set in the emotes.lua file 310 *** \see LoadEmotes() in the GameGlobal class. 311 **/ 312 void Emote(const std::string& emote_name, vt_map::private_map::ANIM_DIRECTIONS dir = vt_map::private_map::ANIM_SOUTH); 313 314 //! \brief Indicates whether the given map object is using an emote animation. HasEmote()315 bool HasEmote() const { 316 return (_emote_animation); 317 } 318 319 //! \brief Loads the current animation file as the new interaction icon of the object. 320 void SetInteractionIcon(const std::string& animation_filename); 321 322 //! \brief Draws the interaction icon at the top of the sprite, if any. 323 void DrawInteractionIcon(); 324 //@} 325 326 protected: 327 /** \brief An identification number for the object as it is represented in the map file. 328 *** Objects with an ID less than zero are invalid. 329 **/ 330 int16_t _object_id; 331 332 /** \brief Coordinates for the object's origin/position. 333 *** The origin of every map object is the bottom center point of the object. These 334 *** origin coordinates are used to determine where the object is on the map as well 335 *** as where the objects collision rectangle lies. 336 *** 337 *** The position coordinates point to the map grid tile that the object currently occupies 338 *** and may range from 0 to the number of columns or rows of grid tiles on the map. 339 **/ 340 vt_common::Position2D _tile_position; 341 342 //! \brief The originally desired half-width and height of the image, in pixels 343 //! Used as a base value to later get the screen and tile corresponding values. 344 float _img_pixel_half_width; 345 float _img_pixel_height; 346 347 //! \brief The image half-width and height as seen on screen. (pixel value * zoom ratio). 348 float _img_screen_half_width; 349 float _img_screen_height; 350 351 //! \brief The half-width and height of the image, in map tile coordinates. 352 //! (A grid unit is half a tile). 353 float _img_grid_half_width; 354 float _img_grid_height; 355 356 /** \brief Determines the collision rectangle for the object in pixels. 357 *** The collision area determines what portion of the map object may not be overlapped 358 *** by other objects or unwalkable regions of the map. 359 *** 360 *** \note These members should always be positive and non-zero. Setting these members to 361 *** zero does <b>not</b> eliminate collision detection for the object. 362 *** 363 *** Used as a base value to later get the screen and tile corresponding values. 364 **/ 365 float _coll_pixel_half_width; 366 float _coll_pixel_height; 367 368 //! \brief The collision half-width and height as seen on screen in the debug view. 369 //! (pixel value * zoom ratio). 370 float _coll_screen_half_width; 371 float _coll_screen_height; 372 373 //! \brief Determines the collision rectangle for the object in map grid coordinates. 374 //! (A grid unit is half a tile). 375 float _coll_grid_half_width; 376 float _coll_grid_height; 377 378 //! \brief When false, the Update() function will do nothing (default == true). 379 bool _updatable; 380 381 //! \brief When false, the Draw() function will do nothing (default == true). 382 bool _visible; 383 384 //! \brief The collision mask indicating what the object will collide with. (i.e.: walls + objects, nothing, ...) 385 //! \NOTE: COLLISION TYPE used as bitmask 386 uint32_t _collision_mask; 387 388 /** \brief When true, objects in the ground object layer will be drawn after the pass objects 389 *** This member is only checked for objects that exist in the ground layer. It has no meaning 390 *** for objects in the pass or sky layers. Its purpose is so that objects (such as a bridge) 391 *** in the pass layer can be both walked over and walked under by sprites in the ground layer. 392 **/ 393 bool _draw_on_second_pass; 394 395 //! \brief This is used to identify the type of map object for inheriting classes. 396 MAP_OBJECT_TYPE _object_type; 397 398 //! \brief the emote animation to play. 399 //! \note This is a reference pointer only, and shouldn't be deleted. 400 vt_video::AnimatedImage* _emote_animation; 401 402 //! \brief the interaction icon animation to play, if any. 403 //! \note This one should be deleted in the destructor. 404 vt_video::AnimatedImage* _interaction_icon; 405 406 //! \brief The emote animation drawing offset in screen coordinates (pixel value * zoom ratio) 407 //! (depending on the map object direction) 408 vt_common::Position2D _emote_screen_offset; 409 410 //! \brief the time the emote animation will last in milliseconds, 411 int32_t _emote_time; 412 413 //! \brief The object draw layer. Used to know where to register the MapObject, 414 //! and when to delete it in the ObjectSupervisor. 415 MapObjectDrawLayer _draw_layer; 416 417 //! \brief Tells whether the map object sprite and animation should be displayed grayscaled or not. 418 bool _grayscale; 419 420 //! \brief Takes care of updating the emote animation and state. 421 void _UpdateEmote(); 422 423 //! \brief Takes care of drawing the emote animation. 424 void _DrawEmote(); 425 }; // class MapObject 426 427 428 /** \brief This is a predicate used to sort MapObjects in correct draw order 429 *** \return True if the MapObject pointed by a should be drawn behind MapObject pointed by b 430 *** \note A simple '<' operator cannot be used with the sorting algorithm because it is sorting pointers. 431 **/ 432 struct MapObject_Ptr_Less { operatorMapObject_Ptr_Less433 bool operator()(const MapObject* a, const MapObject* b) { 434 return (a->GetYPosition()) < (b->GetYPosition()); 435 } 436 }; 437 438 } // namespace private_map 439 440 } // namespace vt_map 441 442 #endif // __MAP_OBJECT_HEADER__ 443