From ebda3ab7ce3e30d8225228ffe8df3316b4f73645 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Sat, 7 May 2005 00:58:24 +0000 Subject: [PATCH] - Change ScriptInterpreter to a gameobject, so we can now have several script 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 --- data/levels/test/script.stl | 2 - data/levels/test/yeti.stl | 17 +++++++- src/badguy/yeti.cpp | 19 ++++++++- src/badguy/yeti.h | 1 + src/game_session.cpp | 6 +++ src/game_session.h | 2 + src/object/scripted_object.cpp | 9 ++++- src/object/scripted_object.h | 2 + src/scripting/functions.cpp | 2 +- src/scripting/level.cpp | 9 ++--- src/scripting/script_interpreter.cpp | 66 ++++++++++++++++++++++++++----- src/scripting/script_interpreter.h | 22 ++++++++--- src/scripting/scripted_object.cpp | 75 ------------------------------------ src/scripting/scripted_object.h | 4 +- src/sector.cpp | 39 +++---------------- src/sector.h | 1 - 16 files changed, 136 insertions(+), 140 deletions(-) delete mode 100644 src/scripting/scripted_object.cpp diff --git a/data/levels/test/script.stl b/data/levels/test/script.stl index d56402440..c14894885 100644 --- a/data/levels/test/script.stl +++ b/data/levels/test/script.stl @@ -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); diff --git a/data/levels/test/yeti.stl b/data/levels/test/yeti.stl index bb0103ba2..0673514ea 100644 --- a/data/levels/test/yeti.stl +++ b/data/levels/test/yeti.stl @@ -100,7 +100,22 @@ (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)) diff --git a/src/badguy/yeti.cpp b/src/badguy/yeti.cpp index 2bbf5d71b..8e9f72c76 100644 --- a/src/badguy/yeti.cpp +++ b/src/badguy/yeti.cpp @@ -21,10 +21,12 @@ #include #include +#include #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); } diff --git a/src/badguy/yeti.h b/src/badguy/yeti.h index 4716ddcab..f62b5164a 100644 --- a/src/badguy/yeti.h +++ b/src/badguy/yeti.h @@ -55,6 +55,7 @@ private: Timer safe_timer; int jumpcount; int hit_points; + std::string dead_script; }; #endif diff --git a/src/game_session.cpp b/src/game_session.cpp index cec4a015f..edf057fef 100644 --- a/src/game_session.cpp +++ b/src/game_session.cpp @@ -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; diff --git a/src/game_session.h b/src/game_session.h index 5c1ec8af6..3357fd18a 100644 --- a/src/game_session.h +++ b/src/game_session.h @@ -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, diff --git a/src/object/scripted_object.cpp b/src/object/scripted_object.cpp index 82f72e98e..db7295797 100644 --- a/src/object/scripted_object.cpp +++ b/src/object/scripted_object.cpp @@ -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); } diff --git a/src/object/scripted_object.h b/src/object/scripted_object.h index 4ee05006f..7d3031f2d 100644 --- a/src/object/scripted_object.h +++ b/src/object/scripted_object.h @@ -40,6 +40,8 @@ private: bool solid; bool physic_enabled; bool visible; + bool new_vel_set; + Vector new_vel; Physic physic; Sprite* sprite; }; diff --git a/src/scripting/functions.cpp b/src/scripting/functions.cpp index 99e2c9af3..5b24c9249 100644 --- a/src/scripting/functions.cpp +++ b/src/scripting/functions.cpp @@ -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) diff --git a/src/scripting/level.cpp b/src/scripting/level.cpp index d29e18b65..9b6749fbf 100644 --- a/src/scripting/level.cpp +++ b/src/scripting/level.cpp @@ -3,8 +3,7 @@ #include #include #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); } } diff --git a/src/scripting/script_interpreter.cpp b/src/scripting/script_interpreter.cpp index 64feaa70b..d9662d5dd 100644 --- a/src/scripting/script_interpreter.cpp +++ b/src/scripting/script_interpreter.cpp @@ -14,6 +14,11 @@ #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 (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 (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& ) +{ +} diff --git a/src/scripting/script_interpreter.h b/src/scripting/script_interpreter.h index ff3d77ec6..73f596bd9 100644 --- a/src/scripting/script_interpreter.h +++ b/src/scripting/script_interpreter.h @@ -4,21 +4,28 @@ #include #include #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 index 269475193..000000000 --- a/src/scripting/scripted_object.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include - -#include -#include -#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; - } -} diff --git a/src/scripting/scripted_object.h b/src/scripting/scripted_object.h index c39def192..9bb0b4411 100644 --- a/src/scripting/scripted_object.h +++ b/src/scripting/scripted_object.h @@ -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; diff --git a/src/sector.cpp b/src/sector.cpp index aeb453022..80f76c83e 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -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 (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 (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 diff --git a/src/sector.h b/src/sector.h index 8cec44ceb..ad735f48d 100644 --- a/src/sector.h +++ b/src/sector.h @@ -135,7 +135,6 @@ public: private: std::vector bullets; - ScriptInterpreter* interpreter; std::string init_script; public: // TODO make this private again -- 2.11.0