- Change ScriptInterpreter to a gameobject, so we can now have several script
authorMatthias Braun <matze@braunis.de>
Sat, 7 May 2005 00:58:24 +0000 (00:58 +0000)
committerMatthias Braun <matze@braunis.de>
Sat, 7 May 2005 00:58:24 +0000 (00:58 +0000)
interpreters running
- Added a dead-script option to the yeti and added a small script when the
yeti is dead
- worked a bit more on the yeti
- Implement Level::spawn and Level::finish scripting API

SVN-Revision: 2428

16 files changed:
data/levels/test/script.stl
data/levels/test/yeti.stl
src/badguy/yeti.cpp
src/badguy/yeti.h
src/game_session.cpp
src/game_session.h
src/object/scripted_object.cpp
src/object/scripted_object.h
src/scripting/functions.cpp
src/scripting/level.cpp
src/scripting/script_interpreter.cpp
src/scripting/script_interpreter.h
src/scripting/scripted_object.cpp [deleted file]
src/scripting/scripted_object.h
src/sector.cpp
src/sector.h

index d564024..c148948 100644 (file)
@@ -128,7 +128,6 @@ function wait(time) {
     set_wakeup_time(time);
     suspend();
 }
-
 Text.set_text(translate(\"The Crazy Nolok Dance\"));
 Text.fade_in(2);
 TUX.set_animation(\"jump\");
@@ -136,7 +135,6 @@ wait(4);
 Text.fade_out(1);
 wait(1);
 NOLOK.set_visible(true);
-PENNY.set_velocity(-200, 200);
 tuxjumps <- 2;
 while(true) {
   wait(0.8);
index bb0103b..0673514 100644 (file)
          (speed 0.500000)
        )
        (spawnpoint (name "main") (x 480) (y 448))
-       (yeti (x 2) (y 177))
+       (yeti
+         (x 2)
+         (y 177)
+         (dead-script "
+Sound.play_sound(\"invincible\");
+Text.set_text(\"You made it!\");
+Text.set_font(\"big\");
+Text.fade_in(1.5);
+set_wakeup_time(4);
+suspend();
+Text.fade_out(1);
+set_wakeup_time(1.5);
+suspend();
+Level.finish();
+")
+        )
        (particles-snow
        )
        (yeti_stalactite (x 97) (y 46))
index 2bbf5d7..8e9f72c 100644 (file)
 #include <config.h>
 
 #include <float.h>
+#include <sstream>
 #include "yeti.h"
 #include "object/camera.h"
 #include "yeti_stalactite.h"
 #include "bouncing_snowball.h"
+#include "scripting/script_interpreter.h"
 
 static const float JUMP_VEL1 = 250;
 static const float JUMP_VEL2 = 700;
@@ -46,6 +48,7 @@ Yeti::Yeti(const lisp::Lisp& reader)
   sound_manager->preload_sound("yeti_gna");
   sound_manager->preload_sound("yeti_roar");
   hit_points = INITIAL_HITPOINTS;
+  reader.get("dead-script", dead_script);
 }
 
 Yeti::~Yeti()
@@ -136,8 +139,22 @@ Yeti::collision_squished(Player& player)
   sound_manager->play_sound("yeti_roar");
   hit_points--;
   if(hit_points <= 0) {
-    sprite->set_action("dead"); 
+    sprite->set_action("dead");
     kill_squished(player);
+
+    // start script
+    if(dead_script != "") {
+      try {
+        ScriptInterpreter* interpreter 
+          = new ScriptInterpreter(Sector::current());
+        std::istringstream in(dead_script);
+        interpreter->load_script(in, "Yeti - dead-script");
+        interpreter->start_script();
+        Sector::current()->add_object(interpreter);
+      } catch(std::exception& e) {
+        std::cerr << "Couldn't execute yeti dead script: " << e.what() << "\n";
+      }
+    }
   } else {
     safe_timer.start(SAFE_TIME);
   }
index 4716ddc..f62b516 100644 (file)
@@ -55,6 +55,7 @@ private:
   Timer safe_timer;
   int jumpcount;
   int hit_points;
+  std::string dead_script;
 };
 
 #endif
index cec4a01..edf057f 100644 (file)
@@ -636,6 +636,12 @@ GameSession::run()
 }
 
 void
+GameSession::finish()
+{
+  exit_status = ES_LEVEL_FINISHED;
+}
+
+void
 GameSession::respawn(const std::string& sector, const std::string& spawnpoint)
 {
   newsector = sector;
index 5c1ec8a..3357fd1 100644 (file)
@@ -77,6 +77,8 @@ public:
   { current_ = this; }
   static GameSession* current() { return current_; }
 
+  /// ends the level as finished
+  void finish();
   void respawn(const std::string& sectorname,
       const std::string& spawnpointname);
   void set_reset_point(const std::string& sectorname,
index 82f72e9..db72957 100644 (file)
@@ -10,7 +10,7 @@
 #include "math/vector.h"
 
 ScriptedObject::ScriptedObject(const lisp::Lisp& lisp)
-  : solid(true), physic_enabled(true), visible(true)
+  : solid(true), physic_enabled(true), visible(true), new_vel_set(false)
 {
   lisp.get("name", name);
   if(name == "")
@@ -69,7 +69,8 @@ ScriptedObject::get_pos_y()
 void
 ScriptedObject::set_velocity(float x, float y)
 {
-  physic.set_velocity(x, y);
+  new_vel = Vector(x, y);
+  new_vel_set = true;
 }
 
 float
@@ -120,6 +121,10 @@ ScriptedObject::action(float elapsed_time)
   if(!physic_enabled)
     return;
 
+  if(new_vel_set) {
+    physic.set_velocity(new_vel.x, new_vel.y);
+    new_vel_set = false;
+  }
   movement = physic.get_movement(elapsed_time);
 }
 
index 4ee0500..7d3031f 100644 (file)
@@ -40,6 +40,8 @@ private:
   bool solid;
   bool physic_enabled;
   bool visible;
+  bool new_vel_set;
+  Vector new_vel;
   Physic physic;
   Sprite* sprite;
 };
index 99e2c9a..5b24c92 100644 (file)
@@ -11,7 +11,7 @@ namespace Scripting
 
 void set_wakeup_time(float seconds)
 {
-  ScriptInterpreter::current()->suspend(seconds);
+  ScriptInterpreter::current()->set_wakeup_time(seconds);
 }
 
 std::string translate(const std::string& text)
index d29e18b..9b6749f 100644 (file)
@@ -3,8 +3,7 @@
 #include <string>
 #include <stdio.h>
 #include "level.h"
-
-#define NOIMPL      printf("%s not implemented.\n", __PRETTY_FUNCTION__);
+#include "game_session.h"
 
 namespace Scripting
 {
@@ -17,12 +16,12 @@ namespace Scripting
   void
   Level::finish()
   {
-    NOIMPL;
+    GameSession::current()->finish();
   }
 
   void
-  Level::spawn(const std::string& , const std::string& )
+  Level::spawn(const std::string& sector, const std::string& spawnpoint)
   {
-    NOIMPL;
+    GameSession::current()->respawn(sector, spawnpoint);
   }
 }
index 64feaa7..d9662d5 100644 (file)
 
 #include "wrapper.h"
 #include "wrapper_util.h"
+#include "sector.h"
+#include "object/text_object.h"
+#include "object/scripted_object.h"
+#include "scripting/sound.h"
+#include "scripting/scripted_object.h"
 
 static void printfunc(HSQUIRRELVM, const char* str, ...)
 {
@@ -25,7 +30,8 @@ static void printfunc(HSQUIRRELVM, const char* str, ...)
 
 ScriptInterpreter* ScriptInterpreter::_current = 0;
 
-ScriptInterpreter::ScriptInterpreter()
+ScriptInterpreter::ScriptInterpreter(Sector* sector)
+  : sound(0), level(0)
 {
   v = sq_open(1024);
   if(v == 0)
@@ -52,10 +58,36 @@ ScriptInterpreter::ScriptInterpreter()
   // register supertux API
   register_functions(v, supertux_global_functions);
   register_classes(v, supertux_classes);  
+
+  // expose ScriptedObjects to the script
+  for(Sector::GameObjects::iterator i = sector->gameobjects.begin();
+      i != sector->gameobjects.end(); ++i) {
+    GameObject* object = *i;
+    Scripting::ScriptedObject* scripted_object
+      = dynamic_cast<Scripting::ScriptedObject*> (object);
+    if(!scripted_object)
+      continue;
+    
+    std::cout << "Exposing " << scripted_object->get_name() << "\n";
+    expose_object(scripted_object, scripted_object->get_name(), 
+        "ScriptedObject");
+  }
+  // expose some "global" objects
+  sound = new Scripting::Sound();
+  expose_object(sound, "Sound", "Sound");
+  level = new Scripting::Level();
+  expose_object(level, "Level", "Level");
+  TextObject* text_object = new TextObject();
+  sector->add_object(text_object);
+  Scripting::Text* text = static_cast<Scripting::Text*> (text_object);
+  expose_object(text, "Text", "Text");
 }
 
 ScriptInterpreter::~ScriptInterpreter()
 {
+  sq_close(v);
+  delete sound;
+  delete level;
 }
 
 static SQInteger squirrel_read_char(SQUserPointer file)
@@ -76,13 +108,17 @@ ScriptInterpreter::load_script(std::istream& in, const std::string& sourcename)
 }
 
 void
-ScriptInterpreter::run_script()
+ScriptInterpreter::start_script()
 {
   _current = this;
   sq_push(v, -2);
   if(sq_call(v, 1, false) < 0)
     throw SquirrelError(v, "Couldn't start script");
   _current = 0;
+  if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) {
+    printf("script ended...\n");
+    remove_me();
+  }  
 }
 
 void
@@ -119,18 +155,28 @@ ScriptInterpreter::expose_object(void* object, const std::string& name,
 }
 
 void
-ScriptInterpreter::suspend(float seconds)
+ScriptInterpreter::set_wakeup_time(float seconds)
 {
-  resume_timer.start(seconds);
+  wakeup_timer.start(seconds);
 }
 
 void
-ScriptInterpreter::update()
+ScriptInterpreter::action(float )
 {
-  if(resume_timer.check()) {
-    _current = this;
-    if(sq_wakeupvm(v, false, false) < 0)
-      throw SquirrelError(v, "Couldn't resume script");
-    _current = 0;
+  if(!wakeup_timer.check())
+    return;
+  
+  _current = this;
+  if(sq_wakeupvm(v, false, false) < 0)
+    throw SquirrelError(v, "Couldn't resume script");
+  _current = 0;
+  if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) {
+    printf("script ended...\n");
+    remove_me();
   }
 }
+
+void
+ScriptInterpreter::draw(DrawingContext& )
+{
+}
index ff3d77e..73f596b 100644 (file)
@@ -4,21 +4,28 @@
 #include <squirrel.h>
 #include <iostream>
 #include "timer.h"
+#include "game_object.h"
+#include "scripting/sound.h"
+#include "scripting/level.h"
 
-class ScriptInterpreter
+class Sector;
+
+class ScriptInterpreter : public GameObject
 {
 public:
-  ScriptInterpreter();
+  ScriptInterpreter(Sector* sector);
   ~ScriptInterpreter();
 
+  void draw(DrawingContext& );
+  void action(float );
+
   void load_script(std::istream& in, const std::string& sourcename = "");
-  void run_script();
+  void start_script();
   
   void expose_object(void* object, const std::string& name,
                      const std::string& type);
 
-  void suspend(float seconds);
-  void update();
+  void set_wakeup_time(float seconds);
 
   static ScriptInterpreter* current()
   {
@@ -28,7 +35,10 @@ public:
 private:
   HSQUIRRELVM v;
   static ScriptInterpreter* _current;
-  Timer resume_timer;
+  Timer wakeup_timer;
+
+  Scripting::Sound* sound;
+  Scripting::Level* level;
 };
 
 #endif
diff --git a/src/scripting/scripted_object.cpp b/src/scripting/scripted_object.cpp
deleted file mode 100644 (file)
index 2694751..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <config.h>
-
-#include <string>
-#include <stdio.h>
-#include "scripted_object.h"
-
-#define NOIMPL      printf("%s not implemented.\n", __PRETTY_FUNCTION__)
-
-namespace Scripting
-{
-  ScriptedObject::ScriptedObject()
-  {}
-
-  ScriptedObject::~ScriptedObject()
-  {}
-
-  void
-  ScriptedObject::set_animation(const std::string& )
-  {
-    NOIMPL;
-  }
-
-  std::string
-  ScriptedObject::get_animation()
-  {
-    NOIMPL;
-    return "";
-  }
-
-  void
-  ScriptedObject::move(float , float )
-  {
-    NOIMPL;
-  }
-
-  void
-  ScriptedObject::set_pos(float , float )
-  {
-    NOIMPL;
-  }
-
-  float
-  ScriptedObject::get_pos_x()
-  {
-    NOIMPL;
-    return -1;
-  }
-
-  float
-  ScriptedObject::get_pos_y()
-  {
-    NOIMPL;
-    return -1;
-  }
-
-  void
-  ScriptedObject::set_velocity(float , float )
-  {
-    NOIMPL;
-  }
-
-  float
-  ScriptedObject::get_velocity_x()
-  {
-    NOIMPL;
-    return -1;
-  }
-
-  float
-  ScriptedObject::get_velocity_y()
-  {
-    NOIMPL;
-    return -1;
-  }
-}
index c39def1..9bb0b44 100644 (file)
@@ -8,8 +8,8 @@ class ScriptedObject
 {
 public:
 #ifndef SCRIPTING_API
-  ScriptedObject();
-  virtual ~ScriptedObject();
+  virtual ~ScriptedObject()
+  {}
 #endif
 
   virtual void set_animation(const std::string& animation) = 0;
index aeb4530..80f76c8 100644 (file)
@@ -68,7 +68,7 @@ Sector* Sector::_current = 0;
 
 Sector::Sector()
   : gravity(10), player(0), solids(0), camera(0),
-    interpreter(0), currentmusic(LEVEL_MUSIC)
+    currentmusic(LEVEL_MUSIC)
 {
   song_title = "Mortimers_chipdisko.mod";
   player = new Player(&player_status);
@@ -422,39 +422,13 @@ Sector::activate(const std::string& spawnpoint)
   // Run init script
   if(init_script != "") {
     try {
-      // TODO we should keep the interpreter across sessions (or some variables)
-      // so that you can store information across levels/sectors...
-      delete interpreter;
-      interpreter = 0;
-      interpreter = new ScriptInterpreter();
-
-      // expose ScriptedObjects to the script
-      for(GameObjects::iterator i = gameobjects.begin();
-          i != gameobjects.end(); ++i) {
-        GameObject* object = *i;
-        Scripting::ScriptedObject* scripted_object
-          = dynamic_cast<Scripting::ScriptedObject*> (object);
-        if(!scripted_object)
-          continue;
-
-        std::cout << "Exposing " << scripted_object->get_name() << "\n";
-        interpreter->expose_object(scripted_object,
-                                   scripted_object->get_name(),
-                                   "ScriptedObject");
-      }
-      Scripting::Sound* sound = new Scripting::Sound();
-      interpreter->expose_object(sound, "Sound", "Sound");
-      TextObject* text_object = new TextObject();
-      add_object(text_object);
-      Scripting::Text* text = static_cast<Scripting::Text*> (text_object);
-      interpreter->expose_object(text, "Text", "Text");
-
+      ScriptInterpreter* interpreter = new ScriptInterpreter(this);
       std::string sourcename = std::string("Sector(") + name + ") - init";
       std::istringstream in(init_script);
-      printf("Load script.\n");
       interpreter->load_script(in, sourcename);
-      printf("run script.\n");
-      interpreter->run_script();
+      interpreter->start_script();
+      add_object(interpreter);
+      init_script = "";
     } catch(std::exception& e) {
       std::cerr << "Couldn't execute init script: " << e.what() << "\n";
     }
@@ -481,9 +455,6 @@ Sector::get_active_region()
 void
 Sector::action(float elapsed_time)
 {
-  if(interpreter)
-    interpreter->update();
-  
   player->check_bounds(camera);
 
 #if 0
index 8cec44c..ad735f4 100644 (file)
@@ -135,7 +135,6 @@ public:
 private:
   std::vector<Bullet*> bullets;
 
-  ScriptInterpreter* interpreter;
   std::string init_script;
 
 public: // TODO make this private again