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)
GameSession::restart_level(bool fromBeginning)
{
game_pause = false;
- end_sequence = NO_ENDSEQUENCE;
+ end_sequence = 0;
main_controller->reset();
delete playback_demo_stream;
delete demo_controller;
- delete end_sequence_controller;
-
current_ = NULL;
}
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
}
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();
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()) {
// 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);
+ }
}
}
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);
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;
}
#include "math/vector.hpp"
#include "console.hpp"
#include "video/surface.hpp"
+#include "object/endsequence.hpp"
class Level;
class Sector;
void on_escape_press();
void process_menu();
- Timer endsequence_timer;
std::auto_ptr<Level> level;
std::auto_ptr<Surface> statistics_backdrop;
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;
--- /dev/null
+// $Id$
+//
+// SuperTux - End Sequence
+// Copyright (C) 2007 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// 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 <config.h>
+
+#include "endsequence.hpp"
+
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+#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()
+{
+}
+
--- /dev/null
+// $Id$
+//
+// SuperTux - End Sequence
+// Copyright (C) 2007 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// 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 <memory>
+#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
}
void
+Player::trigger_sequence(std::string sequence_name)
+{
+ GameSession::current()->start_sequence(sequence_name);
+}
+
+void
Player::update(float elapsed_time)
{
if( no_water ){
*/
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 */
*/
virtual void do_jump(float yspeed) = 0;
+ /**
+ * Orders the current GameSession to start a sequence
+ */
+ virtual void trigger_sequence(std::string sequence_name) = 0;
};
}
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);
}
}
#include "trigger_base.hpp"
#include "serializable.hpp"
+#include "object/player.hpp"
class SequenceTrigger : public TriggerBase, public Serializable
{