Added ghost mode for easier level debugging
authorChristoph Sommer <mail@christoph-sommer.de>
Fri, 26 May 2006 22:17:47 +0000 (22:17 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Fri, 26 May 2006 22:17:47 +0000 (22:17 +0000)
SVN-Revision: 3597

src/object/player.cpp
src/object/player.hpp
src/scripting/functions.cpp
src/scripting/functions.hpp
src/scripting/player.hpp
src/scripting/wrapper.cpp

index 8004608..13b4101 100644 (file)
@@ -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;
+  }
+}
+
index 2581c9f..5a0a8b9 100644 (file)
@@ -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*/
index 1778bee..44887e5 100644 (file)
@@ -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()
index fe5c656..b5fbec3 100644 (file)
@@ -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();
 
index 729ead9..34a6d1f 100644 (file)
@@ -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;
+
 };
 
 }
index fd1f570..5133446 100644 (file)
@@ -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<SQUserPointer*> (&_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<SQUserPointer*> (&_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<Scripting::FloatingImage*> (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'");
   }