From a5123e6e7071da6d73a1ef0b19bf4acb19981605 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Mon, 26 Apr 2004 19:11:54 +0000 Subject: [PATCH] - new more bulletprof endsequence code patch from MatzeB SVN-Revision: 760 --- src/collision.cpp | 25 +++++++++++++++++++++++++ src/collision.h | 9 +++++++++ src/gameloop.cpp | 46 +++++++++++++++++++++++++--------------------- src/gameloop.h | 1 + src/level.cpp | 12 ------------ src/level.h | 2 -- src/tile.cpp | 3 +++ src/tile.h | 6 ++++++ src/timer.cpp | 5 +++++ src/timer.h | 2 ++ 10 files changed, 76 insertions(+), 35 deletions(-) diff --git a/src/collision.cpp b/src/collision.cpp index 1c96d9178..540e40634 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -79,6 +79,31 @@ bool collision_object_map(const base_type& pbase) return false; } +void* collision_func(const base_type& base, tiletestfunction function) +{ + for(float x = base.x; x < base.x + base.width; x += 32) { + for(float y = base.y; y < base.y + base.height; y += 32) { + Tile* tile = gettile(x, y); + void* result = function(tile); + if(result != 0) + return result; + } + } + + return 0; +} + +static void* test_goal_tile_function(Tile* tile) +{ + if(tile->goal) + return tile; + return 0; +} + +Tile* collision_goal(const base_type& base) +{ + return (Tile*) collision_func(base, test_goal_tile_function); +} void collision_swept_object_map(base_type* old, base_type* current) { diff --git a/src/collision.h b/src/collision.h index 4a009e576..f813f2a12 100644 --- a/src/collision.h +++ b/src/collision.h @@ -55,5 +55,14 @@ bool isbrick(float x, float y); bool isice(float x, float y); bool isfullbox(float x, float y); +typedef void* (*tiletestfunction)(Tile* tile); +/** invokes the function for each tile the baserectangle collides with. The + * function aborts and returns true as soon as the tiletestfunction returns + * != 0 then this value is returned. returns 0 if all tests failed. + */ +void* collision_func(const base_type& base, tiletestfunction* function); + +Tile* collision_goal(const base_type& base); + #endif /*SUPERTUX_COLLISION_H*/ diff --git a/src/gameloop.cpp b/src/gameloop.cpp index d523bdaff..efc3c9405 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -407,43 +407,47 @@ GameSession::process_events() } } - void GameSession::check_end_conditions() { Player* tux = world->get_tux(); /* End of level? */ - if (tux->base.x >= World::current()->get_level()->endpos + 32 * (get_level()->use_endsequence ? 22 : 10)) + int endpos = (World::current()->get_level()->width-10) * 32; + Tile* endtile = collision_goal(tux->base); + printf("EndTile: %p.\n", endtile); + // fallback in case the other endpositions don't trigger + if (tux->base.x >= endpos || (endtile && endtile->data >= 1) + || (end_sequence && !endsequence_timer.check())) { exit_status = LEVEL_FINISHED; + return; } - else if (tux->base.x >= World::current()->get_level()->endpos && !end_sequence) + else if(!end_sequence && endtile && endtile->data == 0) { end_sequence = true; last_x_pos = -1; music_manager->halt_music(); + endsequence_timer.start(5000); // 5 seconds until we finish the map } - else + else if (!end_sequence && tux->is_dead()) { - // Check End conditions - if (tux->is_dead()) - { - player_status.lives -= 1; - - if (player_status.lives < 0) - { // No more lives!? - if(st_gl_mode != ST_GL_TEST) - drawendscreen(); - - exit_status = GAME_OVER; - } - else - { // Still has lives, so reset Tux to the levelstart - restart_level(); - } + player_status.lives -= 1; + + if (player_status.lives < 0) + { // No more lives!? + if(st_gl_mode != ST_GL_TEST) + drawendscreen(); + + exit_status = GAME_OVER; } - } + else + { // Still has lives, so reset Tux to the levelstart + restart_level(); + } + + return; + } } void diff --git a/src/gameloop.h b/src/gameloop.h index 7f25998e9..dda4fbbb1 100644 --- a/src/gameloop.h +++ b/src/gameloop.h @@ -47,6 +47,7 @@ class GameSession private: Timer fps_timer; Timer frame_timer; + Timer endsequence_timer; World* world; int st_gl_mode; int levelnb; diff --git a/src/level.cpp b/src/level.cpp index d8d40e584..8ab407891 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -245,8 +245,6 @@ Level::init_defaults() bkgd_bottom.red = 255; bkgd_bottom.green = 255; bkgd_bottom.blue = 255; - endpos = 0; - use_endsequence = false; for(int i = 0; i < 15; ++i) { @@ -312,8 +310,6 @@ Level::load(const std::string& filename) LispReader reader(lisp_cdr(root_obj)); version = 0; reader.read_int("version", &version); - use_endsequence = false; - reader.read_bool("use-endsequence", &use_endsequence); if(!reader.read_int("width", &width)) st_abort("No width specified for level.", ""); if (!reader.read_int("start_pos_x", &start_pos_x)) start_pos_x = 100; @@ -513,14 +509,6 @@ Level::load(const std::string& filename) } } - // Mark the end position of this level! - // FIXME: -10 is a rather random value, we still need some kind of - // real levelend gola - if (use_endsequence) - endpos = 32*(width-30); - else - endpos = 32*(width-15); - lisp_free(root_obj); fclose(fi); return 0; diff --git a/src/level.h b/src/level.h index ac503ed16..11d818135 100644 --- a/src/level.h +++ b/src/level.h @@ -87,8 +87,6 @@ class Level int width; int start_pos_x; int start_pos_y; - int endpos; - bool use_endsequence; float gravity; std::vector badguy_data; diff --git a/src/tile.cpp b/src/tile.cpp index 7d07e431e..0966e0808 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -93,6 +93,7 @@ void TileManager::load_tileset(std::string filename) tile->water = false; tile->fullbox = false; tile->distro = false; + tile->goal = false; tile->data = 0; tile->next_tile = 0; tile->anim_speed = 25; @@ -105,6 +106,8 @@ void TileManager::load_tileset(std::string filename) reader.read_bool("water", &tile->water); reader.read_bool("fullbox", &tile->fullbox); reader.read_bool("distro", &tile->distro); + reader.read_bool("goal", &tile->goal); + if(tile->goal) printf("Goal!.\n"); reader.read_int("data", &tile->data); reader.read_int("anim-speed", &tile->anim_speed); reader.read_int("next-tile", &tile->next_tile); diff --git a/src/tile.h b/src/tile.h index b95842288..ee6a0f66b 100644 --- a/src/tile.h +++ b/src/tile.h @@ -62,6 +62,12 @@ public: /** Tile is a distro/coin */ bool distro; + /** the level should be finished when touching a goaltile. + * if data is 0 then the endsequence should be triggered, if data is 1 + * then we can finish the level instantly. + */ + bool goal; + /** General purpose data attached to a tile (content of a box, type of coin) */ int data; diff --git a/src/timer.cpp b/src/timer.cpp index a8f2d754a..5b22c1393 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -53,6 +53,11 @@ return; st_pause_count = 0; } +Timer::Timer() +{ + init(true); +} + void Timer::init(bool st_ticks) { diff --git a/src/timer.h b/src/timer.h index b12d32e8e..eb516c09c 100644 --- a/src/timer.h +++ b/src/timer.h @@ -36,6 +36,8 @@ class Timer unsigned int (*get_ticks) (void); public: + Timer(); + void init(bool st_ticks); void start(unsigned int period); void stop(); -- 2.11.0