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