From: Christoph Sommer Date: Thu, 18 Jan 2007 18:53:19 +0000 (+0000) Subject: Separated EndSequence logic from GameSession. This will allow for nice hierarchy... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=f2d345c3ccec7743e39df2f59e546ad415257b81;p=supertux.git Separated EndSequence logic from GameSession. This will allow for nice hierarchy of different EndSequence classes. SVN-Revision: 4593 --- diff --git a/src/game_session.cpp b/src/game_session.cpp index 5caed2e23..69a1265ed 100644 --- a/src/game_session.cpp +++ b/src/game_session.cpp @@ -83,7 +83,7 @@ GameSession* GameSession::current_ = NULL; GameSession::GameSession(const std::string& levelfile_, Statistics* statistics) : level(0), currentsector(0), - end_sequence(NO_ENDSEQUENCE), end_sequence_controller(0), + end_sequence(0), levelfile(levelfile_), best_level_statistics(statistics), capture_demo_stream(0), playback_demo_stream(0), demo_controller(0), play_time(0) @@ -110,7 +110,7 @@ void GameSession::restart_level(bool fromBeginning) { game_pause = false; - end_sequence = NO_ENDSEQUENCE; + end_sequence = 0; main_controller->reset(); @@ -160,8 +160,6 @@ GameSession::~GameSession() delete playback_demo_stream; delete demo_controller; - delete end_sequence_controller; - current_ = NULL; } @@ -271,10 +269,10 @@ GameSession::levelintro() void GameSession::on_escape_press() { - if(currentsector->player->is_dying() || end_sequence != NO_ENDSEQUENCE) + if(currentsector->player->is_dying() || end_sequence) { // Let the timers run out, we fast-forward them to force past a sequence - endsequence_timer.start(FLT_EPSILON); + if (end_sequence) end_sequence->stop(); currentsector->player->dying_timer.start(FLT_EPSILON); return; // don't let the player open the menu, when he is dying } @@ -333,26 +331,11 @@ GameSession::run_script(std::istream& in, const std::string& sourcename) void GameSession::process_events() { - Player& tux = *currentsector->player; - // end of pause mode? if(!Menu::current() && game_pause) { game_pause = false; } - if (end_sequence != NO_ENDSEQUENCE) { - if(end_sequence_controller == 0) { - end_sequence_controller = new CodeController(); - tux.set_controller(end_sequence_controller); - } - - end_sequence_controller->press(Controller::RIGHT); - - if (int(last_x_pos) == int(tux.get_pos().x)) - end_sequence_controller->press(Controller::JUMP); - last_x_pos = tux.get_pos().x; - } - // playback a demo? if(playback_demo_stream != 0) { demo_controller->update(); @@ -393,7 +376,7 @@ GameSession::check_end_conditions() Player* tux = currentsector->player; /* End of level? */ - if(end_sequence && endsequence_timer.check()) { + if(end_sequence && end_sequence->is_done()) { finish(true); return; } else if (!end_sequence && tux->is_dead()) { @@ -489,12 +472,16 @@ GameSession::update(float elapsed_time) // Update the world state and all objects in the world if(!game_pause) { // Update the world - if (end_sequence == ENDSEQUENCE_RUNNING) { - currentsector->update(elapsed_time/2); - } else if(end_sequence == NO_ENDSEQUENCE) { + if (!end_sequence) { play_time += elapsed_time; //TODO: make sure we don't count cutscene time level->stats.time = play_time; currentsector->update(elapsed_time); + } else { + if (!end_sequence->is_tux_stopped()) { + currentsector->update(elapsed_time/2); + } else { + end_sequence->update(elapsed_time/2); + } } } @@ -594,9 +581,10 @@ GameSession::start_sequence(const std::string& sequencename) if(end_sequence) return; - end_sequence = ENDSEQUENCE_RUNNING; - endsequence_timer.start(7.3); - last_x_pos = -1; + end_sequence = new EndSequence(); + currentsector->add_object(end_sequence); + end_sequence->start(); + sound_manager->play_music("music/leveldone.ogg", false); currentsector->player->invincible_timer.start(7.3); @@ -619,7 +607,7 @@ GameSession::start_sequence(const std::string& sequencename) log_warning << "Final target reached without an active end sequence" << std::endl; this->start_sequence("endsequence"); } - end_sequence = ENDSEQUENCE_WAITING; + if (end_sequence) end_sequence->stop_tux(); } else { log_warning << "Unknown sequence '" << sequencename << "'" << std::endl; } diff --git a/src/game_session.hpp b/src/game_session.hpp index 3c5e5dbab..87d0b3e0a 100644 --- a/src/game_session.hpp +++ b/src/game_session.hpp @@ -27,6 +27,7 @@ #include "math/vector.hpp" #include "console.hpp" #include "video/surface.hpp" +#include "object/endsequence.hpp" class Level; class Sector; @@ -101,7 +102,6 @@ private: void on_escape_press(); void process_menu(); - Timer endsequence_timer; std::auto_ptr level; std::auto_ptr statistics_backdrop; @@ -114,16 +114,7 @@ private: int levelnb; int pause_menu_frame; - /** If true the end_sequence will be played, user input will be - ignored while doing that */ - enum EndSequenceState { - NO_ENDSEQUENCE, - ENDSEQUENCE_RUNNING, // tux is running right - ENDSEQUENCE_WAITING // waiting for the end of the music - }; - EndSequenceState end_sequence; - float last_x_pos; - CodeController* end_sequence_controller; + EndSequence* end_sequence; bool game_pause; diff --git a/src/object/endsequence.cpp b/src/object/endsequence.cpp new file mode 100644 index 000000000..3a56cac46 --- /dev/null +++ b/src/object/endsequence.cpp @@ -0,0 +1,131 @@ +// $Id$ +// +// SuperTux - End Sequence +// Copyright (C) 2007 Christoph Sommer +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include + +#include "endsequence.hpp" + +#include +#include +#include +#include "main.hpp" +#include "resources.hpp" +#include "sector.hpp" +#include "gettext.hpp" +#include "object_factory.hpp" +#include "object/player.hpp" +#include "video/drawing_context.hpp" +#include "lisp/list_iterator.hpp" +#include "log.hpp" +#include "scripting/level_time.hpp" +#include "scripting/squirrel_util.hpp" + +EndSequence::EndSequence() +: isrunning(false), isdone(false), tux_may_walk(true) +{ + end_sequence_controller = 0; +} + +EndSequence::~EndSequence() +{ + delete end_sequence_controller; +} + +void +EndSequence::update(float elapsed_time) +{ + if (!isrunning) return; + running(elapsed_time); +} + +void +EndSequence::draw(DrawingContext& /*context*/) +{ +} + +void +EndSequence::start() +{ + if (isrunning) return; + isrunning = true; + isdone = false; + + Player& tux = *Sector::current()->player; + end_sequence_controller = new CodeController(); + tux.set_controller(end_sequence_controller); + + starting(); +} + +void +EndSequence::stop_tux() +{ + tux_may_walk = false; +} + +void +EndSequence::stop() +{ + if (!isrunning) return; + isrunning = false; + isdone = true; + stopping(); +} + +bool +EndSequence::is_tux_stopped() +{ + return !tux_may_walk; +} + + bool +EndSequence::is_done() +{ + return isdone; +} + +void +EndSequence::starting() +{ + last_x_pos = -1; + endsequence_timer.start(7.3); +} + +void +EndSequence::running(float /*elapsed_time*/) +{ + Player& tux = *Sector::current()->player; + + if (tux_may_walk) { + end_sequence_controller->press(Controller::RIGHT); + if (int(last_x_pos) == int(tux.get_pos().x)) { + end_sequence_controller->press(Controller::JUMP); + } + } + + last_x_pos = tux.get_pos().x; + + if (endsequence_timer.check()) isdone = true; +} + +void +EndSequence::stopping() +{ +} + diff --git a/src/object/endsequence.hpp b/src/object/endsequence.hpp new file mode 100644 index 000000000..07f1267c7 --- /dev/null +++ b/src/object/endsequence.hpp @@ -0,0 +1,60 @@ +// $Id$ +// +// SuperTux - End Sequence +// Copyright (C) 2007 Christoph Sommer +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef __ENDSEQUENCE_H__ +#define __ENDSEQUENCE_H__ + +#include +#include "game_object.hpp" +#include "timer.hpp" +#include "lisp/lisp.hpp" +#include "control/codecontroller.hpp" + +class EndSequence : public GameObject +{ +public: + EndSequence(); + virtual ~EndSequence(); + + virtual void update(float elapsed_time); + virtual void draw(DrawingContext& context); + + void start(); /**< play EndSequence */ + void stop_tux(); /**< called when Tux has reached his final position */ + void stop(); /**< stop playing EndSequence, mark it as done playing */ + bool is_tux_stopped(); /**< returns true if Tux has reached his final position */ + bool is_done(); /**< returns true if EndSequence has finished playing */ + +protected: + virtual void starting(); /**< called when EndSequence starts */ + virtual void running(float elapsed_time); /**< called while the EndSequence is running */ + virtual void stopping(); /**< called when EndSequence stops */ + + CodeController* end_sequence_controller; + float last_x_pos; + Timer endsequence_timer; + +private: + bool isrunning; /**< true while EndSequence plays */ + bool isdone; /**< true if EndSequence has finished playing */ + bool tux_may_walk; /**< true while tux is allowed to walk */ + +}; + +#endif diff --git a/src/object/player.cpp b/src/object/player.cpp index 66fa32cdc..46588010d 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -215,6 +215,12 @@ Player::adjust_height(float new_height) } void +Player::trigger_sequence(std::string sequence_name) +{ + GameSession::current()->start_sequence(sequence_name); +} + +void Player::update(float elapsed_time) { if( no_water ){ diff --git a/src/object/player.hpp b/src/object/player.hpp index 73027ecc6..fec7007cb 100644 --- a/src/object/player.hpp +++ b/src/object/player.hpp @@ -251,6 +251,11 @@ public: */ bool adjust_height(float new_height); + /** + * Orders the current GameSession to start a sequence + */ + void trigger_sequence(std::string sequence_name); + private: void handle_input(); void handle_input_ghost(); /**< input handling while in ghost mode */ diff --git a/src/scripting/player.hpp b/src/scripting/player.hpp index 8b36aa7f5..5fe871340 100644 --- a/src/scripting/player.hpp +++ b/src/scripting/player.hpp @@ -111,6 +111,10 @@ public: */ virtual void do_jump(float yspeed) = 0; + /** + * Orders the current GameSession to start a sequence + */ + virtual void trigger_sequence(std::string sequence_name) = 0; }; diff --git a/src/trigger/sequence_trigger.cpp b/src/trigger/sequence_trigger.cpp index 0f66a838c..5a94419b8 100644 --- a/src/trigger/sequence_trigger.cpp +++ b/src/trigger/sequence_trigger.cpp @@ -65,10 +65,10 @@ SequenceTrigger::write(lisp::Writer& writer) } void -SequenceTrigger::event(Player& , EventType type) +SequenceTrigger::event(Player& player, EventType type) { if(type == triggerevent) { - GameSession::current()->start_sequence(sequence_name); + player.trigger_sequence(sequence_name); } } diff --git a/src/trigger/sequence_trigger.hpp b/src/trigger/sequence_trigger.hpp index 5b8c02205..34ec2517b 100644 --- a/src/trigger/sequence_trigger.hpp +++ b/src/trigger/sequence_trigger.hpp @@ -23,6 +23,7 @@ #include "trigger_base.hpp" #include "serializable.hpp" +#include "object/player.hpp" class SequenceTrigger : public TriggerBase, public Serializable {