From ed51c9c974fe748420844158b8ce572a1f8ea284 Mon Sep 17 00:00:00 2001 From: Christoph Sommer Date: Fri, 26 May 2006 22:17:47 +0000 Subject: [PATCH] Added ghost mode for easier level debugging SVN-Revision: 3597 --- src/object/player.cpp | 38 ++++++++++++++++++- src/object/player.hpp | 14 +++++++ src/scripting/functions.cpp | 8 ++++ src/scripting/functions.hpp | 7 +++- src/scripting/player.hpp | 12 ++++++ src/scripting/wrapper.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 166 insertions(+), 2 deletions(-) diff --git a/src/object/player.cpp b/src/object/player.cpp index 80046081a..13b41012b 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -102,7 +102,7 @@ TuxBodyParts::draw(DrawingContext& context, const Vector& pos, int layer) } Player::Player(PlayerStatus* _player_status) - : player_status(_player_status), grabbed_object(NULL) + : player_status(_player_status), grabbed_object(NULL), ghost_mode(false) { controller = main_controller; smalltux_gameover = sprite_manager->create("images/creatures/tux_small/smalltux-gameover.sprite"); @@ -467,6 +467,11 @@ Player::handle_vertical_input() void Player::handle_input() { + if (ghost_mode) { + handle_input_ghost(); + return; + } + if(!controller->hold(Controller::ACTION) && grabbed_object) { // move the grabbed object a bit away from tux Vector pos = get_pos() + @@ -535,6 +540,20 @@ Player::handle_input() } void +Player::handle_input_ghost() +{ + float vx = 0; + float vy = 0; + if (controller->hold(Controller::LEFT)) vx -= MAX_RUN_XM; + if (controller->hold(Controller::RIGHT)) vx += MAX_RUN_XM; + if ((controller->hold(Controller::UP)) || (controller->hold(Controller::JUMP))) vy += MAX_RUN_XM; + if (controller->hold(Controller::DOWN)) vy -= MAX_RUN_XM; + if (controller->hold(Controller::ACTION)) set_ghost_mode(false); + physic.set_velocity(vx, vy); + physic.set_acceleration(0, 0); +} + +void Player::add_coins(int count) { player_status->add_coins(count); @@ -1016,3 +1035,20 @@ void Player::walk(float speed) physic.set_velocity_x(speed); } +void +Player::set_ghost_mode(bool enable) +{ + if (ghost_mode == enable) return; + if (enable) { + ghost_mode = true; + set_group(COLGROUP_DISABLED); + physic.enable_gravity(false); + log_debug << "You feel lightheaded. Use movement controls to float around, press ACTION to scare badguys." << std::endl; + } else { + ghost_mode = false; + set_group(COLGROUP_MOVING); + physic.enable_gravity(true); + log_debug << "You feel solid again." << std::endl; + } +} + diff --git a/src/object/player.hpp b/src/object/player.hpp index 2581c9f4a..5a0a8b944 100644 --- a/src/object/player.hpp +++ b/src/object/player.hpp @@ -183,8 +183,20 @@ public: return grabbed_object; } + /** + * Switches ghost mode on/off. + * Lets Tux float around and through solid objects. + */ + void set_ghost_mode(bool enable); + + /** + * Returns whether ghost mode is currently enabled + */ + bool get_ghost_mode() { return ghost_mode; } + private: void handle_input(); + void handle_input_ghost(); /**< input handling while in ghost mode */ bool deactivated; void init(); @@ -206,6 +218,8 @@ private: Sprite* smalltux_star; Sprite* bigtux_star; Vector floor_normal; + + bool ghost_mode; /**< indicates if Tux should float around and through solid objects */ }; #endif /*SUPERTUX_PLAYER_H*/ diff --git a/src/scripting/functions.cpp b/src/scripting/functions.cpp index 1778beec1..44887e5ca 100644 --- a/src/scripting/functions.cpp +++ b/src/scripting/functions.cpp @@ -213,11 +213,19 @@ void invincible() tux->invincible_timer.start(10000); } +void ghost() +{ + if (!validate_sector_player()) return; + ::Player* tux = Sector::current()->player; + tux->set_ghost_mode(true); +} + void mortal() { if (!validate_sector_player()) return; ::Player* tux = Sector::current()->player; tux->invincible_timer.stop(); + tux->set_ghost_mode(false); } void restart() diff --git a/src/scripting/functions.hpp b/src/scripting/functions.hpp index fe5c656b3..b5fbec3c2 100644 --- a/src/scripting/functions.hpp +++ b/src/scripting/functions.hpp @@ -140,7 +140,12 @@ void grease(); void invincible(); /** - * recall Tux's invincibility + * makes Tux a ghost, i.e. lets him float around and through solid objects + */ +void ghost(); + +/** + * recall Tux's invincibility and ghost status */ void mortal(); diff --git a/src/scripting/player.hpp b/src/scripting/player.hpp index 729ead911..34a6d1f7e 100644 --- a/src/scripting/player.hpp +++ b/src/scripting/player.hpp @@ -71,6 +71,18 @@ public: * if he had grow or fireflower bonus */ virtual void kill(bool completely) = 0; + + /** + * Switches ghost mode on/off. + * Lets Tux float around and through solid objects. + */ + virtual void set_ghost_mode(bool enable) = 0; + + /** + * Returns whether ghost mode is currently enabled + */ + virtual bool get_ghost_mode() = 0; + }; } diff --git a/src/scripting/wrapper.cpp b/src/scripting/wrapper.cpp index fd1f5705a..51334463c 100644 --- a/src/scripting/wrapper.cpp +++ b/src/scripting/wrapper.cpp @@ -1192,6 +1192,58 @@ static SQInteger Player_kill_wrapper(HSQUIRRELVM vm) } +static SQInteger Player_set_ghost_mode_wrapper(HSQUIRRELVM vm) +{ + Scripting::Player* _this; + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_ghost_mode' called without instance")); + return SQ_ERROR; + } + SQBool arg0; + if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a bool")); + return SQ_ERROR; + } + + try { + _this->set_ghost_mode(arg0 == SQTrue); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_ghost_mode'")); + return SQ_ERROR; + } + +} + +static SQInteger Player_get_ghost_mode_wrapper(HSQUIRRELVM vm) +{ + Scripting::Player* _this; + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_ghost_mode' called without instance")); + return SQ_ERROR; + } + + try { + bool return_value = _this->get_ghost_mode(); + + sq_pushbool(vm, return_value); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_ghost_mode'")); + return SQ_ERROR; + } + +} + static SQInteger FloatingImage_release_hook(SQUserPointer ptr, SQInteger ) { Scripting::FloatingImage* _this = reinterpret_cast (ptr); @@ -2033,6 +2085,25 @@ static SQInteger invincible_wrapper(HSQUIRRELVM vm) } +static SQInteger ghost_wrapper(HSQUIRRELVM vm) +{ + (void) vm; + + try { + Scripting::ghost(); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'ghost'")); + return SQ_ERROR; + } + +} + static SQInteger mortal_wrapper(HSQUIRRELVM vm) { (void) vm; @@ -2560,6 +2631,12 @@ void register_supertux_wrapper(HSQUIRRELVM v) throw SquirrelError(v, "Couldn't register function 'invincible'"); } + sq_pushstring(v, "ghost", -1); + sq_newclosure(v, &ghost_wrapper, 0); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'ghost'"); + } + sq_pushstring(v, "mortal", -1); sq_newclosure(v, &mortal_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { @@ -2910,6 +2987,18 @@ void register_supertux_wrapper(HSQUIRRELVM v) throw SquirrelError(v, "Couldn't register function 'kill'"); } + sq_pushstring(v, "set_ghost_mode", -1); + sq_newclosure(v, &Player_set_ghost_mode_wrapper, 0); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'set_ghost_mode'"); + } + + sq_pushstring(v, "get_ghost_mode", -1); + sq_newclosure(v, &Player_get_ghost_mode_wrapper, 0); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'get_ghost_mode'"); + } + if(SQ_FAILED(sq_createslot(v, -3))) { throw SquirrelError(v, "Couldn't register class 'Player'"); } -- 2.11.0