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 17 #ifndef HEADER_SUPERTUX_SUPERTUX_GAME_OBJECT_HPP 18 #define HEADER_SUPERTUX_SUPERTUX_GAME_OBJECT_HPP 19 20 #include <algorithm> 21 #include <string> 22 23 #include "editor/object_settings.hpp" 24 #include "supertux/game_object_component.hpp" 25 #include "util/fade_helper.hpp" 26 #include "util/gettext.hpp" 27 #include "util/uid.hpp" 28 29 class DrawingContext; 30 class GameObjectComponent; 31 class ObjectRemoveListener; 32 class ReaderMapping; 33 class Writer; 34 35 /** 36 Base class for all the things that make up Levels' Sectors. 37 38 Each sector of a level will hold a list of active GameObject while the 39 game is played. 40 41 This class is responsible for: 42 - Updating and Drawing the object. This should happen in the update() and 43 draw() functions. Both are called once per frame. 44 - Providing a safe way to remove the object by calling the remove_me 45 functions. 46 */ 47 class GameObject 48 { 49 friend class GameObjectManager; 50 51 public: 52 GameObject(); 53 GameObject(const std::string& name); 54 GameObject(const ReaderMapping& reader); 55 virtual ~GameObject(); 56 57 /** Called after all objects have been added to the Sector and the 58 Sector is fully constructed. If objects refer to other objects 59 by name, those connection can be resolved here. */ finish_construction()60 virtual void finish_construction() {} 61 get_uid() const62 UID get_uid() const { return m_uid; } 63 64 /** This function is called once per frame and allows the object to 65 update it's state. The dt_sec is the time that has passed since 66 the last frame in seconds and should be the base for all timed 67 calculations (don't use SDL_GetTicks directly as this will fail 68 in pause mode). This function is not called in the Editor. */ 69 virtual void update(float dt_sec) = 0; 70 71 /** The GameObject should draw itself onto the provided 72 DrawingContext if this function is called. */ 73 virtual void draw(DrawingContext& context) = 0; 74 75 /** This function saves the object. Editor will use that. */ 76 virtual void save(Writer& writer); get_class() const77 virtual std::string get_class() const { return "game-object"; } get_display_name() const78 virtual std::string get_display_name() const { return _("Unknown object"); } 79 80 /** If true only a single object of this type is allowed in a 81 given GameObjectManager */ is_singleton() const82 virtual bool is_singleton() const { return false; } 83 84 /** Does this object have variable size 85 (secret area trigger, wind, etc.) */ has_variable_size() const86 virtual bool has_variable_size() const { return false; } 87 88 /** Indicates if the object will be saved. If false, the object will 89 be skipped on saving and can't be cloned in the editor. */ is_saveable() const90 virtual bool is_saveable() const { return true; } 91 92 /** Indicates if get_settings() is implemented. If true the editor 93 will display Tip and ObjectMenu. */ has_settings() const94 virtual bool has_settings() const { return is_saveable(); } 95 virtual ObjectSettings get_settings(); 96 after_editor_set()97 virtual void after_editor_set() {} 98 99 /** When level is flipped vertically */ on_flip(float height)100 virtual void on_flip(float height) {} 101 102 /** schedules this object to be removed at the end of the frame */ remove_me()103 virtual void remove_me() { m_scheduled_for_removal = true; } 104 105 /** returns true if the object is not scheduled to be removed yet */ is_valid() const106 bool is_valid() const { return !m_scheduled_for_removal; } 107 108 /** registers a remove listener which will be called if the object 109 gets removed/destroyed */ 110 void add_remove_listener(ObjectRemoveListener* listener); 111 112 /** unregisters a remove listener, so it will no longer be called if 113 the object gets removed/destroyed */ 114 void del_remove_listener(ObjectRemoveListener* listener); 115 set_name(const std::string & name)116 void set_name(const std::string& name) { m_name = name; } get_name() const117 const std::string& get_name() const { return m_name; } 118 get_icon_path() const119 virtual const std::string get_icon_path() const { 120 return "images/tiles/auxiliary/notile.png"; 121 } 122 123 /** stops all looping sounds */ stop_looping_sounds()124 virtual void stop_looping_sounds() {} 125 126 /** continues all looping sounds */ play_looping_sounds()127 virtual void play_looping_sounds() {} 128 129 template<typename T> get_component()130 T* get_component() { 131 for(auto& component : m_components) { 132 if (T* result = dynamic_cast<T*>(component.get())) { 133 return result; 134 } 135 } 136 return nullptr; 137 } 138 add_component(std::unique_ptr<GameObjectComponent> component)139 void add_component(std::unique_ptr<GameObjectComponent> component) { 140 m_components.emplace_back(std::move(component)); 141 } 142 remove_component(GameObjectComponent * component)143 void remove_component(GameObjectComponent* component) { 144 auto it = std::find_if(m_components.begin(), m_components.end(), 145 [component](const std::unique_ptr<GameObjectComponent>& lhs){ 146 return lhs.get() == component; 147 }); 148 if (it != m_components.end()) { 149 m_components.erase(it); 150 } 151 } 152 153 /** The editor requested the deletion of the object */ editor_delete()154 virtual void editor_delete() { remove_me(); } 155 156 /** The user clicked on the object in the editor and selected it*/ editor_select()157 virtual void editor_select() {} 158 159 /** The object got deselected */ editor_deselect()160 virtual void editor_deselect() {} 161 162 /** Called each frame in the editor, used to keep linked objects 163 together (e.g. platform on a path) */ editor_update()164 virtual void editor_update() {} 165 166 private: set_uid(const UID & uid)167 void set_uid(const UID& uid) { m_uid = uid; } 168 169 protected: 170 /** a name for the gameobject, this is mostly a hint for scripts and 171 for debugging, don't rely on names being set or being unique */ 172 std::string m_name; 173 174 /** Fade Helpers are for easing/fading script functions */ 175 std::vector<std::unique_ptr<FadeHelper>> m_fade_helpers; 176 177 private: 178 /** A unique id for the object to safely refer to it. This will be 179 set by the GameObjectManager. */ 180 UID m_uid; 181 182 /** this flag indicates if the object should be removed at the end of the frame */ 183 bool m_scheduled_for_removal; 184 185 std::vector<std::unique_ptr<GameObjectComponent> > m_components; 186 187 std::vector<ObjectRemoveListener*> m_remove_listeners; 188 189 private: 190 GameObject(const GameObject&) = delete; 191 GameObject& operator=(const GameObject&) = delete; 192 }; 193 194 #endif 195 196 /* EOF */ 197