1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright (C) 2004-2010 by The Allacrost Project 3 // All Rights Reserved 4 // 5 // This code is licensed under the GNU GPL version 2. It is free software 6 // and you may modify it and/or redistribute it under the terms of this license. 7 // See http://www.gnu.org/copyleft/gpl.html for details. 8 /////////////////////////////////////////////////////////////////////////////// 9 10 /** **************************************************************************** 11 *** \file map_objects.h 12 *** \author Tyler Olsen, roots@allacrost.org 13 *** \brief Header file for map mode objects. 14 *** *****************************************************************************/ 15 16 #ifndef __MAP_OBJECTS_HEADER__ 17 #define __MAP_OBJECTS_HEADER__ 18 19 // Allacrost utilities 20 #include "utils.h" 21 #include "defs.h" 22 23 // Allacrost engines 24 #include "video.h" 25 26 // Local map mode headers 27 #include "map_utils.h" 28 29 namespace hoa_map { 30 31 namespace private_map { 32 33 /** **************************************************************************** 34 *** \brief Abstract class that represents objects on a map 35 *** 36 *** A map object can be anything from a sprite to a tree to a house. To state 37 *** it simply, a map object is a map image that is not tiled and need not be fixed 38 *** in place. Map objects are drawn in one of three layers: ground, pass, and sky 39 *** object layers. 40 41 *** All map objects have both a collision rectangle and an image rectangle. 42 *** The collision rectangle indicates what parts of the object may not overlap 43 *** with other collision rectangles and unwalkable sections of the map. The image 44 *** rectangle determines the size of the object as it is visible on the screen. 45 *** The collision rectangle and image rectangles do not need to be the same size. 46 *** Typically the collision rectangle is smaller than the image rectangle. It is 47 *** also possible to disable both rectangles via special properties that can be 48 *** enabled in this class. This would prevent the object from being a factor in 49 *** collision detection and/or it would never be drawn to the screen. 50 *** 51 *** State information about map objects may need to be retained upon leaving a 52 *** map. For example, a treasure (which is a type of map object) needs to know 53 *** whether or not the player has retrieved its contents already so that they 54 *** can not be gained a second time. This data is stored in the saved game file 55 *** so that even when the player exits the game, the state information can be 56 *** retrieved when the application starts again later. 57 *** 58 *** \note It is advised not to attempt to make map objects with dynamic sizes (i.e. 59 *** the various image frames that compose the object should all be the same size). 60 *** In theory, dynamically sized objects are feasible to implement in maps, but 61 *** they are much easier to be subject to bugs and other issues. 62 *** ***************************************************************************/ 63 class MapObject { 64 public: 65 MapObject(); 66 ~MapObject()67 virtual ~MapObject() 68 {} 69 70 /** \brief An identification number for the object as it is represented in the map file. 71 *** Player sprites are assigned object IDs from 5000 and above. Technically this means that 72 *** a map can have no more than 5000 objects that are not player sprites, but no map should 73 *** need to contain that many objects in the first place. Objects with an ID less than zero 74 *** are invalid. 75 **/ 76 int16 object_id; 77 78 /** \brief The map context that the object currently resides in. 79 *** Context helps to determine where an object "resides". For example, inside of a house or 80 *** outside of a house. The context member determines if the object should be drawn or not, 81 *** since objects are only drawn if they are in the same context as the map's camera. 82 *** Objects can only interact with one another if they both reside in the same context. 83 *** 84 *** \note The default value for this member is the base context (context 01). 85 **/ 86 MAP_CONTEXT context; 87 88 /** \brief Coordinates for the object's origin/position. 89 *** The origin of every map object is the bottom center point of the object. These 90 *** origin coordinates are used to determine where the object is on the map as well 91 *** as where the objects collision rectangle lies. 92 *** 93 *** The position coordinates are described by an integer (position) and a float (offset). 94 *** The position coordinates point to the map grid tile that the object currently occupies 95 *** and may range from 0 to the number of columns or rows of grid tiles on the map. The 96 *** offset member will always range from 0.0f and 1.0f to indicate the exact position of 97 *** the object within that grid tile. 98 **/ 99 //@{ 100 uint16 x_position, y_position; 101 float x_offset, y_offset; 102 //@} 103 104 /** \brief The half-width and height of the image, in map grid coordinates. 105 *** The half_width member is indeed just that: half the width of the object's image. We keep 106 *** the half width rather than the full width because the origin of the object is its bottom 107 *** center, and it is more convenient to store only half the sprite's width. 108 *** 109 *** \note These members assume that the object retains the same width and height regardless 110 *** of the current animation frame or image being drawn. If the object's image changes size 111 *** for any reason, the programmer must remember to change these values accordingly. 112 **/ 113 float img_half_width, img_height; 114 115 /** \brief Determines the collision rectangle for the object. 116 *** The collision area determines what portion of the map object may not be overlapped 117 *** by other objects or unwalkable regions of the map. The x and y coordinates are 118 *** relative to the origin, so an x value of 0.5f means that the collision rectangle 119 *** extends the length of 1/2 of a grid element from the origin on both sides, and a y value 120 *** of 1.0f means that the collision area exists from the origin to one grid element above. 121 *** 122 *** \note These members should always be positive and non-zero. Setting these members to 123 *** zero does <b>not</b> eliminate collision detection for the object. 124 **/ 125 float coll_half_width, coll_height; 126 127 //! \name Object Properties 128 //@{ 129 //! \brief When false, the Update() function will do nothing (default == true). 130 bool updatable; 131 132 //! \brief When false, the Draw() function will do nothing (default == true). 133 bool visible; 134 135 //! \brief When true, the object will not be examined for collision detection (default == false). 136 bool no_collision; 137 138 /** \brief When true, indicates that the object exists on the sky object layer (default == false). 139 *** This member is necessary for collision detection purposes. When a sprite needs to detect 140 *** if it has encountered a collision, that collision must be examined with other objects on 141 *** the appropriate layer (the ground/pass layers or the sky layer). 142 **/ 143 bool sky_object; 144 145 /** \brief When true, objects in the ground object layer will be drawn after the pass objects 146 *** This member is only checked for objects that exist in the ground layer. It has no meaning 147 *** for objects in the pass or sky layers. Its purpose is so that objects (such as a bridge) 148 *** in the pass layer can be both walked over and walked under by sprites in the ground layer. 149 **/ 150 bool draw_on_second_pass; 151 //@} 152 153 // ---------- Methods 154 155 /** \brief Updates the state of an object. 156 *** Many map objects may not actually have a use for this function. For example, animated objects 157 *** like a tree will automatically have their frames updated by the video engine in the draw 158 *** function. So it is the case that the implementation of this function in derived classes may 159 *** simply do nothing. 160 **/ 161 virtual void Update() = 0; 162 163 /** \brief Draws the object to the frame buffer. 164 *** Objects are drawn differently depending on what type of object they are and what their current 165 *** state is. Note that calling this function does not guarantee that the object will be drawn. 166 *** Many implementations of this function in the derived classes first call the ShouldDraw() method 167 *** to determine if the object should be drawn at all. 168 **/ 169 virtual void Draw() = 0; 170 171 /** \brief Determines if an object should be drawn to the screen. 172 *** \return True if the object should be drawn. 173 *** \note This function also moves the draw cursor to the proper position if the object should be drawn 174 *** 175 *** This method performs the common drawing operations of identifying whether or not the object 176 *** is visible on the screen and moving the drawing cursor to its location. The children classes 177 *** of this class may choose to make use of it (or not). 178 **/ 179 bool ShouldDraw(); 180 181 //! \brief Rolls over the position coordinates if the offsets exceed below 0.0f or above 1.0f 182 void CheckPositionOffsets(); 183 184 /** \brief Computes the full floating-point location coordinates of the object 185 *** \return The full x or y coordinate location of the object 186 *** 187 *** Since an object's position is stored as an integer component and an offset component, this 188 *** method simply returns a single floating point value representing the full x and y positions 189 *** of the object in a single variable. 190 **/ 191 //@{ ComputeXLocation()192 float ComputeXLocation() const 193 { return (static_cast<float>(x_position) + x_offset); } 194 ComputeYLocation()195 float ComputeYLocation() const 196 { return (static_cast<float>(y_position) + y_offset); } 197 //@} 198 199 //! \brief Retrieves the object type identifier GetObjectType()200 MAP_OBJECT_TYPE GetObjectType() const 201 { return _object_type; } 202 203 /** \brief Returns the collision rectangle for the current object 204 *** \param rect A reference to the MapRectangle object to store the collision rectangle data 205 **/ 206 void GetCollisionRectangle(MapRectangle& rect) const; 207 208 /** \brief Returns the image rectangle for the current object 209 *** \param rect A reference to the MapRectangle object to store the image rectangle data 210 **/ 211 void GetImageRectangle(MapRectangle& rect) const; 212 213 /** \brief Restores the saved state of the object 214 *** This state data is retained in the saved game file. When any map object is created and added 215 *** to the map, this function is called to load any stored state data that there may be. Notice 216 *** that the default implementation of this function does nothing. 217 **/ RestoreSaved()218 virtual void RestoreSaved() 219 {} 220 221 /** \name Lua Access Functions 222 *** These functions are specifically written to enable Lua to access the members of this class. 223 *** C++ code may also choose to use these functions, although all of the members here are public 224 *** so it is not mandatory to do so. 225 **/ 226 //@{ 227 void SetObjectID(int16 id = 0) 228 { object_id = id; } 229 SetContext(MAP_CONTEXT ctxt)230 void SetContext(MAP_CONTEXT ctxt) 231 { context = ctxt; } 232 SetXPosition(uint16 x,float offset)233 void SetXPosition(uint16 x, float offset) 234 { x_position = x; x_offset = offset; } 235 SetYPosition(uint16 y,float offset)236 void SetYPosition(uint16 y, float offset) 237 { y_position = y; y_offset = offset; } 238 SetImgHalfWidth(float width)239 void SetImgHalfWidth(float width) 240 { img_half_width = width; } 241 SetImgHeight(float height)242 void SetImgHeight(float height) 243 { img_height = height; } 244 SetCollHalfWidth(float collision)245 void SetCollHalfWidth(float collision) 246 { coll_half_width = collision; } 247 SetCollHeight(float collision)248 void SetCollHeight(float collision) 249 { coll_height = collision; } 250 SetUpdatable(bool update)251 void SetUpdatable(bool update) 252 { updatable = update; } 253 SetVisible(bool vis)254 void SetVisible(bool vis) 255 { visible = vis; } 256 SetNoCollision(bool coll)257 void SetNoCollision(bool coll) 258 { no_collision = coll; } 259 SetDrawOnSecondPass(bool pass)260 void SetDrawOnSecondPass(bool pass) 261 { draw_on_second_pass = pass; } 262 GetObjectID()263 int16 GetObjectID() const 264 { return object_id; } 265 GetContext()266 MAP_CONTEXT GetContext() const 267 { return context; } 268 GetXPosition(uint16 & x,float & offset)269 void GetXPosition(uint16 &x, float &offset) const 270 { x = x_position; offset = x_offset; } 271 GetYPosition(uint16 & y,float & offset)272 void GetYPosition(uint16 &y, float &offset) const 273 { y = y_position; offset = y_offset; } 274 GetImgHalfWidth()275 float GetImgHalfWidth() const 276 { return img_half_width; } 277 GetImgHeight()278 float GetImgHeight() const 279 { return img_height; } 280 GetCollHalfWidth()281 float GetCollHalfWidth() const 282 { return coll_half_width; } 283 GetCollHeight()284 float GetCollHeight() const 285 { return coll_height; } 286 IsUpdatable()287 bool IsUpdatable() const 288 { return updatable; } 289 IsVisible()290 bool IsVisible() const 291 { return visible; } 292 IsNoCollision()293 bool IsNoCollision() const 294 { return no_collision; } 295 IsDrawOnSecondPass()296 bool IsDrawOnSecondPass() const 297 { return draw_on_second_pass; } 298 GetType()299 MAP_OBJECT_TYPE GetType() const 300 { return _object_type; } 301 //@} 302 303 protected: 304 //! \brief This is used to identify the type of map object for inheriting classes. 305 MAP_OBJECT_TYPE _object_type; 306 }; // class MapObject 307 308 309 /** \brief This is a predicate used to sort MapObjects in correct draw order 310 *** \return True if the MapObject pointed by a should be drawn behind MapObject pointed by b 311 *** \note A simple '<' operator cannot be used with the sorting algorithm because it is sorting pointers. 312 **/ 313 struct MapObject_Ptr_Less { operatorMapObject_Ptr_Less314 const bool operator()(const MapObject* a, const MapObject* b) { 315 return (a->y_position + a->y_offset) < (b->y_position + b->y_offset); 316 } 317 }; 318 319 320 /** **************************************************************************** 321 *** \brief Represents visible objects on the map that have no motion. 322 *** 323 *** This class represents both still image and animated objects. These objects 324 *** are usually fixed in place and do not change their position. The object must 325 *** have at least one entry in its image vector, otherwise a segmentation fault 326 *** will occur if the Update or Draw functions are called. 327 *** 328 *** \note If the object does not have any animated images, set the 'updatable' 329 *** member of the base class to false. Forgetting to do this will do no harm, but 330 *** it will 331 *** ***************************************************************************/ 332 class PhysicalObject : public MapObject { 333 public: 334 PhysicalObject(); 335 336 ~PhysicalObject(); 337 338 /** \brief The index to the animations vector that contains the current image to display 339 *** When modifying this member, take care not to exceed the bounds of the animations vector 340 **/ 341 uint8 current_animation; 342 343 /** \brief A vector containing all the object's animations. 344 *** These need not be actual animations. If you just want a still image, add only a single 345 *** frame to the animation. Usually only need a single still image or animation will be 346 *** needed, but a vector is used here in case others are needed. 347 **/ 348 std::vector<hoa_video::AnimatedImage> animations; 349 350 //! \brief Updates the object's current animation. 351 virtual void Update(); 352 353 //! \brief Draws the object to the screen, if it is visible. 354 virtual void Draw(); 355 356 /** \name Lua Access Functions 357 *** These functions are specifically to enable Lua to access the members of this class. 358 **/ 359 //@{ AddAnimation(hoa_video::AnimatedImage new_img)360 void AddAnimation(hoa_video::AnimatedImage new_img) 361 { animations.push_back(new_img); } 362 SetCurrentAnimation(uint8 current)363 void SetCurrentAnimation(uint8 current) 364 { animations[current_animation].SetTimeProgress(0); current_animation = current; } 365 SetAnimationProgress(uint32 progress)366 void SetAnimationProgress(uint32 progress) 367 { animations[current_animation].SetTimeProgress(progress); } 368 GetCurrentAnimation()369 uint8 GetCurrentAnimation() const 370 { return current_animation; } 371 //@} 372 }; // class PhysicalObject : public MapObject 373 374 375 /** **************************************************************************** 376 *** \brief A helper class to MapMode responsible for management of all object and sprite data 377 *** 378 *** This class is responsible for loading, updating, and drawing all map objects 379 *** and map sprites, in addition to maintaining the map's collision grid and map 380 *** zones. This class contains the implementation of the collision detection 381 *** and path finding algorithms. 382 *** 383 *** \todo Each map object is assigned an ID and certain values of IDs are reserved 384 *** for different types of map objects. We need to find out what these are and 385 *** maintain a list of those ranges here. 386 *** ***************************************************************************/ 387 class ObjectSupervisor { 388 friend class hoa_map::MapMode; 389 // TEMP: for allowing context zones to access all objects 390 friend class hoa_map::private_map::ContextZone; 391 392 public: 393 ObjectSupervisor(); 394 395 ~ObjectSupervisor(); 396 397 //! \brief Returns a unique ID integer for an object to use GenerateObjectID()398 uint16 GenerateObjectID() 399 { return ++_last_id; } 400 401 /** \brief Retrieves a pointer to an object on this map 402 *** \param object_id The id number of the object to retreive 403 *** \return A pointer to the map object, or NULL if no object with that ID was found 404 **/ 405 MapObject* GetObject(uint32 object_id); 406 407 //! \brief Sorts objects on all three layers according to their draw order 408 void SortObjects(); 409 410 /** \brief Loads the collision grid data and saved state of all map objects 411 *** \param map_file A reference to the open map script file 412 *** 413 *** The file must be open prior to making this call and additionally must 414 *** be at the highest level scope (i.e., there are no actively open tables 415 *** in the script descriptor object). 416 **/ 417 void Load(hoa_script::ReadScriptDescriptor& map_file); 418 419 //! \brief Updates the state of all map zones and objects 420 void Update(); 421 422 /** \brief Draws the various object layers to the screen 423 *** \param frame A pointer to the information required to draw this frame 424 *** \note These functions do not reset the coordinate system and hence depend that the proper coordinate system 425 *** is already set prior to these function calls (0.0f, SCREEN_COLS, SCREEN_ROWS, 0.0f). These functions do make 426 *** modifications to the draw flags and the draw cursor position, which are not restored by the function 427 *** upon its return. Take measures to retain this information before calling these functions if necessary. 428 **/ 429 //@{ 430 void DrawGroundObjects(const MapFrame* const frame, const bool second_pass); 431 void DrawPassObjects(const MapFrame* const frame); 432 void DrawSkyObjects(const MapFrame* const frame); 433 //@} 434 435 /** \brief Finds the nearest map object within a certain distance of a sprite 436 *** \param sprite The sprite who is trying to find its nearest object 437 *** \param search_distance The maximum distance to search for an object from the sprite (default == 3.0f) 438 *** \return A pointer to the nearest map object, or NULL if no such object was found. 439 *** 440 *** An interactable object must be in the same context as the function argument is. For an object 441 *** to be valid, it's collision rectangle must be no greater than the search distance (in units of 442 *** collision grid elements) from the sprite's "calling" axis. For example, if the search distance was 3.0f 443 *** and the sprite was facing downwards, this function draws an imaginary rectangle below the sprite of height 444 *** 3.0f and a length equal to the length of the sprite. Any objects that have their collision rectangles intersect 445 *** with any portion of this search area are put on a list of valid objects, and once this list has been fully 446 *** constructed the nearest of these objects will be returned. 447 **/ 448 private_map::MapObject* FindNearestObject(const private_map::VirtualSprite* sprite, float search_distance = 3.0f); 449 450 /** \brief Determines if an object occupies an invalid position on the map 451 *** \param obj A pointer to the map object whose position should be checked 452 *** \return True if the object has collided with 453 *** 454 *** The collision condition is true if the object's collision rectangle occupies any space 455 *** outside of the map boundaries or if any of the collision grid tiles occupied by the 456 *** collision rectangle are unwalkable in the object's current context. 457 **/ 458 bool CheckMapCollision(const private_map::MapObject* const obj); 459 460 /** \brief Determines if a map object's collision rectangle intersects with a specified map area 461 *** \param rect A reference to the rectangular section of the map to do collision detection with 462 *** \param obj A pointer to a map object 463 *** \return True if the objects collide with one another 464 *** \note This test is "absolute", and does not factor in things such as map contexts or whether or 465 *** not the no_collision property is enabled on the MapObject. 466 **/ 467 bool CheckObjectCollision(const MapRectangle& rect, const private_map::MapObject* const obj); 468 469 /** \brief Determines if two map objects have overlapping collision rectangles 470 *** \param obj1 A pointer to a map object 471 *** \param obj2 A pointer to a different map object 472 *** \return True if the objects collide 473 **/ 474 bool DoObjectsCollide(const private_map::MapObject* const obj1, const private_map::MapObject* const obj2); 475 476 /** \brief Determines if a map object or sprite occupies a certain element of the collision grid 477 *** \param col The collision grid column 478 *** \param row The collision grid row 479 *** \return A pointer to the object occupying the grid position or NULL if the position is unoccupied 480 *** 481 *** \todo Take into account the object/sprite's collision property and also add a parameter for map context 482 **/ 483 private_map::MapObject* IsPositionOccupied(int16 col, int16 row); 484 485 /** \brief Determines if a specific map object occupies a specific element of the collision grid 486 *** \param col The collision grid column 487 *** \param row The collision grid row 488 *** \param object The object to check for occupation of the grid element 489 *** \return True if the grid element is occupied by the object 490 *** 491 *** \todo Take into account the object/sprite's collision property and also add a parameter for map context 492 **/ 493 bool IsPositionOccupiedByObject(int16 col, int16 row, MapObject* object); 494 495 /** \brief Determines if a map sprite's position is invalid because of a collision 496 *** \param sprite A pointer to the map sprite to check 497 *** \param collision_object A pointer to a pointer to the object that collides with the sprite. 498 *** This member may be set to NULL if this information is not required by the callee. Otherwise, the callee 499 *** should declare a pointer member of type MapObject and pass the address of that pointer to this parameter. 500 *** \return The type of collision detected, which may include NO_COLLISION if none was detected 501 *** 502 *** This method is invoked by a map sprite who wishes to check for its own collision. 503 *** The collision detection is performed against three types of obstacles: 504 *** 505 *** -# Boundary conditions: where the sprite has walked off the edges of the map 506 *** -# Grid collisions: where the sprite's collision rectangle overlaps with an unwalkable section of the map grid 507 *** -# Object collision: where the sprite's collision rectangle overlaps that of another object's, 508 *** where the object is in the same draw layer and context as the original sprite. 509 **/ 510 COLLISION_TYPE DetectCollision(private_map::VirtualSprite* sprite, private_map::MapObject** collision_object); 511 512 /** \brief Attempts to modify a sprite's position in response to an obstruction that it has collided with 513 *** \param coll_type The type of collision that has occurred 514 *** \param coll_obj A pointer to the MapObject that the sprite has collided with, if any 515 *** \return True if the sprite's position was successfully modified 516 *** 517 *** This function enables sprites to "slide" or "roll" around targets that are in their way. For example, 518 *** if a sprite moving west ran into a small tree, this function would examine the situation and if appropriate, 519 *** it would move the sprite in the north or south directions to get around the tree. This allows for a more 520 *** natural movement in the game and also enables sprites to better navigate through narrow passage ways. Put simply, 521 *** this function allows sprites to automatically roll/slide around the corners of obstructions. 522 *** 523 *** If the object that the sprite collided with is anothing moving sprite, then no attempt to modify the sprite's position 524 *** is performed. This allows for two moving sprites that collided with one another to not come into a deadlock situation 525 *** where they are both trying to move around the other since one sprite will stop its motion and the other will roll 526 *** around until the two are free from colliding with one another. 527 **/ 528 bool AdjustSpriteAroundCollision(VirtualSprite* sprite, COLLISION_TYPE coll_type, MapObject* coll_obj); 529 530 /** \brief Finds a path from a sprite's current position to a destination 531 *** \param sprite A pointer of the sprite to find the path for 532 *** \param path A reference to a vector of PathNode objects to store the path 533 *** \param dest The destination coordinates 534 *** \return True if a path to the destination was found successfully 535 *** 536 *** This algorithm uses the A* algorithm to find a path from a source to a destination. 537 *** This function ignores the position of all other objects and only concerns itself with 538 *** which map grid elements are walkable. 539 *** 540 *** \note If an error is detected or a path could not be found, the function will empty the path vector before returning 541 **/ 542 bool FindPath(private_map::VirtualSprite* sprite, std::vector<private_map::PathNode>& path, const private_map::PathNode& dest); 543 544 private: 545 /** \brief The number of rows and columns in the collision gride 546 *** The number of collision grid rows and columns is always equal to twice 547 *** that of the number of rows and columns of tiles (stored in the TileManager). 548 **/ 549 uint16 _num_grid_rows, _num_grid_cols; 550 551 //! \brief Holds the most recently generated object ID number 552 uint16 _last_id; 553 554 /** \brief A "virtual sprite" that can serve as a focus point for the camera. 555 *** This sprite is not visible to the player nor does it have any collision 556 *** detection properties. Usually, the camera focuses on the player's sprite 557 *** rather than this object, but it is useful for scripted sequences and other 558 *** things. 559 **/ 560 private_map::VirtualSprite *_virtual_focus; 561 562 /** \brief A 2D vector indicating which grid element on the map sprites may be occupied by objects. 563 *** Each bit of each element in this grid corresponds to a context. So all together this entire grid 564 *** stores the collision information for all 32 possible map contexts. 565 **/ 566 std::vector<std::vector<uint32> > _collision_grid; 567 568 /** \brief A map containing pointers to all of the sprites on a map. 569 *** This map does not include a pointer to the _virtual_focus object. The 570 *** sprite's unique identifier integer is used as the map key. 571 **/ 572 std::map<uint16, MapObject*> _all_objects; 573 574 /** \brief A container for all of the map objects located on the ground layer. 575 *** The ground object layer is where most objects and sprites exist in a typical map. 576 **/ 577 std::vector<MapObject*> _ground_objects; 578 579 /** \brief A container for all of the map objects located on the pass layer. 580 *** The pass object layer is named so because objects on this layer can both be 581 *** walked under or above by objects in the ground object layer. A good example 582 *** of an object that would typically go on this layer would be a bridge. This 583 *** layer usually has very few objects for the map. 584 **/ 585 std::vector<MapObject*> _pass_objects; 586 587 /** \brief A container for all of the map objects located on the sky layer. 588 *** The sky object layer contains the last series of elements that are drawn on 589 *** a map. These objects exist high in the sky above all other tiles and objects. 590 *** Translucent clouds can make good use of this object layer, for instance. 591 **/ 592 std::vector<MapObject*> _sky_objects; 593 594 //! \brief Container for all zones used in this map 595 std::vector<MapZone*> _zones; 596 597 // ---------- Methods 598 599 /** \brief Attempts to align a sprite's collision rectangle alongside whatever the sprite has collided against 600 *** \param sprite The sprite to examine for positional alignment 601 *** \param direction The direction in which the alignment should take place (only NORTH, SOUTH, EAST, and WEST are valid values) 602 *** \param coll_type The type of collision that occurred 603 *** \param sprite_coll_rect The collision rectangle of the sprite 604 *** \param object_coll_rect The collision rectangle of the collided object (unused if coll_type is not equal to OBJECT_COLLISION) 605 *** \return True if the sprite's position was modified 606 **/ 607 bool _AlignSpriteWithCollision(VirtualSprite* sprite, uint16 direction, COLLISION_TYPE coll_type, 608 const MapRectangle& sprite_coll_rect, const MapRectangle& object_coll_rect); 609 610 /** \brief A helper function to AdjustSpriteAroundCollision that moves a sprite around a corner 611 *** \param sprite The sprite to examine for movement adjustments 612 *** \param coll_type The type of collision that occurred (BOUNDARY_COLLISION is an invalid value for this function) 613 *** \param sprite_coll_rect The collision rectangle of the sprite 614 *** \param object_coll_rect The collision rectangle of the collided object (not valid if coll_type is not equal to OBJECT_COLLISION) 615 *** \return True if the sprite's position was modified 616 *** 617 *** This function is what allows a sprite to "roll" or "slide" around the corner of an obstruction when the sprite moves orthogonally. 618 *** The algorithm works by examining the immediate area around the sprite in the direction where the collision 619 *** occurred. It will examine a short line in the collision grid immediately next to the sprite in the collision 620 *** direction. The length of this line will be three times the length/height of the sprite's collision grid (rounded up to 621 *** whole integer values). For example, a sprite moving west with a collision rectangle size of 2 units wide by 3 units high will 622 *** equate to a line of 9 collision grid units to examine. If this 9 unit line contains any walkable section 623 *** that consists of 3 or more concurrent grid elements, the algorithm instructs the sprite to move in that direction. 624 *** 625 *** If the collision type was an OBJECT_COLLISION, then in addition to the collision grid the algorithm will examine if there is 626 *** a nearby corner of the object that was collided with. However, no other map objects will be considered in this case (because 627 *** we wish to limit the computational complexity of this algorithm). If there is another object in the way, then the function will 628 *** fail (return false) when it tries to modify the sprite's position around the corner. 629 *** 630 *** \todo One possible downside to this algorithm is that it doesn't take into account other nearby objects that could be 631 *** in the way. Theoretically if we had a line of sprites standing in an open plane and we tried to move one sprite through the middle 632 *** of them, the sprite would continue to oscillate around this living wall thinking it has found a gap to get through when 633 *** there is none. This is something to consider addressing in the future. 634 **/ 635 bool _MoveSpriteAroundCollisionCorner(VirtualSprite* sprite, COLLISION_TYPE coll_type, 636 const MapRectangle& sprite_coll_rect, const MapRectangle& object_coll_rect); 637 638 /** \brief A helper function to AdjustSpriteAroundCollision that handles diagonal adjustment to sprite movement 639 *** \param sprite The sprite to examine for movement adjustments 640 *** \param coll_type The type of collision that occurred 641 *** \param sprite_coll_rect The collision rectangle of the sprite 642 *** \param object_coll_rect The collision rectangle of the collided object (not valid if coll_type is not equal to OBJECT_COLLISION) 643 *** \return True if the sprite's position was modified 644 *** 645 *** This algorithm will first check for alignment of the sprite with its collision in either the horizontal or vertical directions 646 *** (and in rare cases, both). If the sprite is not aligned with the collision, its position will be adjusted so that it is. If 647 *** the sprite is already aligned, then the function will try moving the sprite in only the horizontal or vertical direction. 648 *** The sprite will never be positioned to move backwards. That is, if the sprite is trying to move north east, this function may 649 *** move the sprite north, east, or northeast, but it will never move it to the south or west. 650 **/ 651 bool _MoveSpriteAroundCollisionDiagonal(VirtualSprite* sprite, COLLISION_TYPE coll_type, 652 const MapRectangle& sprite_coll_rect, const MapRectangle& object_coll_rect); 653 654 /** \brief Modifies the position of a sprite and checks if the new position is valid 655 *** \param sprite The sprite whose position should be modify 656 *** \param direction The direction to modify the sprite's position in (NORTH, SOUTH, EAST, and WEST are the only valid values) 657 *** \param distance The distance to move the sprite in the specified direction 658 *** \return True if the sprite's position was successfully modified to a new valid location 659 **/ 660 bool _ModifySpritePosition(VirtualSprite* sprite, uint16 direction, float distance); 661 }; // class ObjectSupervisor 662 663 } // namespace private_map 664 665 } // namespace hoa_map 666 667 #endif // __MAP_OBJECTS_HEADER__ 668