| 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_OBJECT_PLAYER_HPP |
| 18 | #define |
| 19 | |
| 20 | #include "scripting/player.hpp" |
| 21 | #include "sprite/sprite_ptr.hpp" |
| 22 | #include "squirrel/exposed_object.hpp" |
| 23 | #include "supertux/direction.hpp" |
| 24 | #include "supertux/moving_object.hpp" |
| 25 | #include "supertux/physic.hpp" |
| 26 | #include "supertux/player_status.hpp" |
| 27 | #include "supertux/sequence.hpp" |
| 28 | #include "supertux/timer.hpp" |
| 29 | #include "video/surface_ptr.hpp" |
| 30 | |
| 31 | class BadGuy; |
| 32 | class Portable; |
| 33 | class Climbable; |
| 34 | class Controller; |
| 35 | class CodeController; |
| 36 | |
| 37 | extern const float TUX_INVINCIBLE_TIME_WARNING; |
| 38 | |
| 39 | class Player final : public MovingObject, |
| 40 | public ExposedObject<Player, scripting::Player> |
| 41 | { |
| 42 | public: |
| 43 | enum FallMode { ON_GROUND, JUMPING, TRAMPOLINE_JUMP, FALLING }; |
| 44 | |
| 45 | public: |
| 46 | Player(PlayerStatus& player_status, const std::string& name); |
| 47 | virtual ~Player(); |
| 48 | |
| 49 | virtual void update(float dt_sec) override; |
| 50 | virtual void draw(DrawingContext& context) override; |
| 51 | virtual void collision_solid(const CollisionHit& hit) override; |
| 52 | virtual HitResponse collision(GameObject& other, const CollisionHit& hit) override; |
| 53 | virtual void collision_tile(uint32_t tile_attributes) override; |
| 54 | virtual bool is_saveable() const override { return false; } |
| 55 | virtual bool is_singleton() const override { return true; } |
| 56 | |
| 57 | void set_controller(const Controller* controller); |
| 58 | /** Level solved. Don't kill Tux any more. */ |
| 59 | void set_winning(); |
| 60 | bool is_winning() const { return m_winning; } |
| 61 | |
| 62 | // Tux can only go this fast. If set to 0 no special limit is used, only the default limits. |
| 63 | void set_speedlimit(float newlimit); |
| 64 | float get_speedlimit() const; |
| 65 | |
| 66 | const Controller& get_controller() const { return *m_controller; } |
| 67 | |
| 68 | void use_scripting_controller(bool use_or_release); |
| 69 | void do_scripting_controller(const std::string& control, bool pressed); |
| 70 | |
| 71 | void make_invincible(); |
| 72 | |
| 73 | bool is_invincible() const { return m_invincible_timer.started(); } |
| 74 | bool is_dying() const { return m_dying; } |
| 75 | |
| 76 | Direction peeking_direction_x() const { return m_peekingX; } |
| 77 | Direction peeking_direction_y() const { return m_peekingY; } |
| 78 | |
| 79 | void kill(bool completely); |
| 80 | void move(const Vector& vector); |
| 81 | |
| 82 | bool add_bonus(const std::string& bonus); |
| 83 | bool set_bonus(const std::string& bonus); |
| 84 | void add_coins(int count); |
| 85 | int get_coins() const; |
| 86 | |
| 87 | /** picks up a bonus, taking care not to pick up lesser bonus items than we already have |
| 88 | |
| 89 | @returns true if the bonus has been set (or was already good enough) |
| 90 | false if the bonus could not be set (for example no space for big tux) */ |
| 91 | bool add_bonus(BonusType type, bool animate = false); |
| 92 | |
| 93 | /** like add_bonus, but can also downgrade the bonus items carried */ |
| 94 | bool set_bonus(BonusType type, bool animate = false); |
| 95 | |
| 96 | PlayerStatus& get_status() const { return m_player_status; } |
| 97 | |
| 98 | /** set kick animation */ |
| 99 | void kick(); |
| 100 | |
| 101 | /** play cheer animation. |
| 102 | This might need some space and behave in an unpredictable way. |
| 103 | Best to use this at level end. */ |
| 104 | void do_cheer(); |
| 105 | |
| 106 | /** duck down if possible. |
| 107 | this won't last long as long as input is enabled. */ |
| 108 | void do_duck(); |
| 109 | |
| 110 | /** stand back up if possible. */ |
| 111 | void do_standup(); |
| 112 | |
| 113 | /** do a backflip if possible. */ |
| 114 | void do_backflip(); |
| 115 | |
| 116 | /** jump in the air if possible |
| 117 | sensible values for yspeed are negative - unless we want to jump |
| 118 | into the ground of course */ |
| 119 | void do_jump(float yspeed); |
| 120 | |
| 121 | /** Adds velocity to the player (be careful when using this) */ |
| 122 | void add_velocity(const Vector& velocity); |
| 123 | |
| 124 | /** Adds velocity to the player until given end speed is reached */ |
| 125 | void add_velocity(const Vector& velocity, const Vector& end_speed); |
| 126 | |
| 127 | /** Returns the current velocity of the player */ |
| 128 | Vector get_velocity() const; |
| 129 | |
| 130 | void bounce(BadGuy& badguy); |
| 131 | |
| 132 | bool is_dead() const { return m_dead; } |
| 133 | bool is_big() const; |
| 134 | bool is_stone() const { return m_stone; } |
| 135 | |
| 136 | void set_visible(bool visible); |
| 137 | bool get_visible() const; |
| 138 | |
| 139 | bool on_ground() const; |
| 140 | |
| 141 | Portable* get_grabbed_object() const { return m_grabbed_object; } |
| 142 | void stop_grabbing() { m_grabbed_object = nullptr; } |
| 143 | |
| 144 | /** Checks whether the player has grabbed a certain object |
| 145 | @param name Name of the object to check */ |
| 146 | bool has_grabbed(const std::string& object_name) const; |
| 147 | |
| 148 | /** Switches ghost mode on/off. |
| 149 | Lets Tux float around and through solid objects. */ |
| 150 | void set_ghost_mode(bool enable); |
| 151 | |
| 152 | /** Switches edit mode on/off. |
| 153 | In edit mode, Tux will enter ghost_mode instead of dying. */ |
| 154 | void set_edit_mode(bool enable); |
| 155 | |
| 156 | /** Returns whether ghost mode is currently enabled */ |
| 157 | bool get_ghost_mode() const { return m_ghost_mode; } |
| 158 | |
| 159 | /** Changes height of bounding box. |
| 160 | Returns true if successful, false otherwise */ |
| 161 | bool adjust_height(float new_height); |
| 162 | |
| 163 | /** Orders the current GameSession to start a sequence |
| 164 | @param sequence_name Name of the sequence to start |
| 165 | @param data Custom additional sequence data */ |
| 166 | void trigger_sequence(const std::string& sequence_name, const SequenceData* data = nullptr); |
| 167 | |
| 168 | /** Orders the current GameSession to start a sequence |
| 169 | @param sequence Sequence to start |
| 170 | @param data Custom additional sequence data */ |
| 171 | void trigger_sequence(Sequence seq, const SequenceData* data = nullptr); |
| 172 | |
| 173 | /** Requests that the player start climbing the given Climbable */ |
| 174 | void start_climbing(Climbable& climbable); |
| 175 | |
| 176 | /** Requests that the player stop climbing the given Climbable */ |
| 177 | void stop_climbing(Climbable& climbable); |
| 178 | |
| 179 | Physic& get_physic() { return m_physic; } |
| 180 | |
| 181 | void activate(); |
| 182 | void deactivate(); |
| 183 | |
| 184 | void walk(float speed); |
| 185 | void set_dir(bool right); |
| 186 | void stop_backflipping(); |
| 187 | |
| 188 | void position_grabbed_object(); |
| 189 | void try_grab(); |
| 190 | |
| 191 | private: |
| 192 | void handle_input(); |
| 193 | void handle_input_ghost(); /**< input handling while in ghost mode */ |
| 194 | void handle_input_climbing(); /**< input handling while climbing */ |
| 195 | |
| 196 | void handle_horizontal_input(); |
| 197 | void handle_vertical_input(); |
| 198 | |
| 199 | void do_jump_apex(); |
| 200 | void early_jump_apex(); |
| 201 | |
| 202 | bool slightly_above_ground() const; |
| 203 | |
| 204 | BonusType string_to_bonus(const std::string& bonus) const; |
| 205 | |
| 206 | /** slows Tux down a little, based on where he's standing */ |
| 207 | void apply_friction(); |
| 208 | |
| 209 | void check_bounds(); |
| 210 | |
| 211 | private: |
| 212 | bool m_deactivated; |
| 213 | |
| 214 | const Controller* m_controller; |
| 215 | std::unique_ptr<CodeController> m_scripting_controller; /**< This controller is used when the Player is controlled via scripting */ |
| 216 | PlayerStatus& m_player_status; |
| 217 | bool m_duck; |
| 218 | bool m_dead; |
| 219 | bool m_dying; |
| 220 | bool m_winning; |
| 221 | bool m_backflipping; |
| 222 | int m_backflip_direction; |
| 223 | Direction m_peekingX; |
| 224 | Direction m_peekingY; |
| 225 | float m_ability_time; |
| 226 | bool m_stone; |
| 227 | bool m_swimming; |
| 228 | float m_speedlimit; |
| 229 | const Controller* m_scripting_controller_old; /**< Saves the old controller while the scripting_controller is used */ |
| 230 | bool m_jump_early_apex; |
| 231 | bool m_on_ice; |
| 232 | bool m_ice_this_frame; |
| 233 | SpritePtr m_lightsprite; |
| 234 | SpritePtr m_powersprite; |
| 235 | |
| 236 | public: |
| 237 | Direction m_dir; |
| 238 | |
| 239 | private: |
| 240 | Direction m_old_dir; |
| 241 | |
| 242 | public: |
| 243 | float m_last_ground_y; |
| 244 | FallMode m_fall_mode; |
| 245 | |
| 246 | private: |
| 247 | bool m_on_ground_flag; |
| 248 | bool m_jumping; |
| 249 | bool m_can_jump; |
| 250 | Timer m_jump_button_timer; /**< started when player presses the jump button; runs until Tux jumps or JUMP_GRACE_TIME runs out */ |
| 251 | bool m_wants_buttjump; |
| 252 | |
| 253 | public: |
| 254 | bool m_does_buttjump; |
| 255 | Timer m_invincible_timer; |
| 256 | |
| 257 | private: |
| 258 | Timer m_skidding_timer; |
| 259 | Timer m_safe_timer; |
| 260 | Timer m_kick_timer; |
| 261 | Timer m_shooting_timer; // used to show the arm when Tux is shooting |
| 262 | Timer m_ability_timer; // maximum lengh of time that special abilities can last |
| 263 | Timer m_cooldown_timer; // minimum time period between successive uses of a special ability |
| 264 | |
| 265 | public: |
| 266 | Timer m_dying_timer; |
| 267 | |
| 268 | private: |
| 269 | Timer m_second_growup_sound_timer; |
| 270 | bool m_growing; |
| 271 | Timer m_backflip_timer; |
| 272 | |
| 273 | Physic m_physic; |
| 274 | |
| 275 | bool m_visible; |
| 276 | |
| 277 | Portable* m_grabbed_object; |
| 278 | |
| 279 | SpritePtr m_sprite; /**< The main sprite representing Tux */ |
| 280 | |
| 281 | SurfacePtr m_airarrow; /**< arrow indicating Tux' position when he's above the camera */ |
| 282 | |
| 283 | Vector m_floor_normal; |
| 284 | |
| 285 | bool m_ghost_mode; /**< indicates if Tux should float around and through solid objects */ |
| 286 | bool m_edit_mode; /**< indicates if Tux should switch to ghost mode rather than dying */ |
| 287 | |
| 288 | Timer m_unduck_hurt_timer; /**< if Tux wants to stand up again after ducking and cannot, this timer is started */ |
| 289 | |
| 290 | Timer m_idle_timer; |
| 291 | unsigned int m_idle_stage; |
| 292 | |
| 293 | Climbable* m_climbing; /**< Climbable object we are currently climbing, null if none */ |
| 294 | |
| 295 | private: |
| 296 | Player(const Player&) = delete; |
| 297 | Player& operator=(const Player&) = delete; |
| 298 | }; |
| 299 | |
| 300 | #endif |
| 301 | |
| 302 | /* EOF */ |
| 303 | |