From: Matthias Braun Date: Mon, 24 May 2004 22:36:56 +0000 (+0000) Subject: make badguys reappear when scrolling back X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=439727da7695d42e55a008268bcfa860262eee4c;p=supertux.git make badguys reappear when scrolling back SVN-Revision: 1315 --- diff --git a/src/badguy.cpp b/src/badguy.cpp index 0e4b7de68..e8062321a 100644 --- a/src/badguy.cpp +++ b/src/badguy.cpp @@ -151,12 +151,8 @@ BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_, { display_manager.add_drawable(this, LAYER_OBJECTS); - base.x = 0; - base.y = 0; - lispreader.read_float("x", &base.x); - lispreader.read_float("y", &base.y); - base.width = 0; - base.height = 0; + lispreader.read_float("x", &start_position.x); + lispreader.read_float("y", &start_position.y); kind = kind_; @@ -171,10 +167,8 @@ BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_, { display_manager.add_drawable(this, LAYER_OBJECTS); - base.x = x; - base.y = y; - base.width = 0; - base.height = 0; + start_position.x = x; + start_position.y = y; stay_on_platform = false; kind = kind_; @@ -189,35 +183,78 @@ BadGuy::~BadGuy() void BadGuy::init() { + base.x = 0; + base.y = 0; + base.width = 0; + base.height = 0; + mode = NORMAL; dying = DYING_NOT; old_base = base; dir = LEFT; seen = false; - frozen_timer.init(true); animation_offset = 0; sprite_left = sprite_right = 0; physic.reset(); + frozen_timer.init(true); + timer.init(true); + + // if we're in a solid tile at start correct that now + if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(base)) + { + std::cout << "Warning: badguy started in wall: kind: " << badguykind_to_string(kind) + << " pos: (" << base.x << ", " << base.y << ")" << std::endl; + while(collision_object_map(base)) + --base.y; + } + + // just activate the badguy, since he might be on screen already. If not he + // gets deactivated anyway + activate(LEFT); +} + +void +BadGuy::write(LispWriter& writer) +{ + writer.start_list(badguykind_to_string(kind)); + + writer.write_float("x", base.x); + writer.write_float("y", base.y); + writer.write_bool("stay-on-platform", stay_on_platform); + + writer.end_list(badguykind_to_string(kind)); +} + +void +BadGuy::activate(Direction activation_dir) +{ + mode = NORMAL; + animation_offset = 0; + physic.reset(); + frozen_timer.init(true); timer.init(true); + dir = activation_dir; + float dirsign = activation_dir == LEFT ? -1 : 1; + if(kind == BAD_MRBOMB) { - physic.set_velocity(-BADGUY_WALK_SPEED, 0); + physic.set_velocity(dirsign * BADGUY_WALK_SPEED, 0); set_sprite(img_mrbomb_left, img_mrbomb_right); } else if (kind == BAD_MRICEBLOCK) { - physic.set_velocity(-BADGUY_WALK_SPEED, 0); + physic.set_velocity(dirsign * BADGUY_WALK_SPEED, 0); set_sprite(img_mriceblock_left, img_mriceblock_right); } else if(kind == BAD_JUMPY) { set_sprite(img_jumpy_left_up, img_jumpy_left_up); } else if(kind == BAD_BOMB) { set_sprite(img_mrbomb_ticking_left, img_mrbomb_ticking_right); - // hack so that the bomb doesn't hurt until it expldes... + // hack so that the bomb doesn't hurt until it expldes... dying = DYING_SQUISHED; } else if(kind == BAD_FLAME) { angle = 0; physic.enable_gravity(false); set_sprite(img_flame, img_flame); } else if(kind == BAD_BOUNCINGSNOWBALL) { - physic.set_velocity(-1.3, 0); + physic.set_velocity(dirsign * 1.3, 0); set_sprite(img_bouncingsnowball_left, img_bouncingsnowball_right); } else if(kind == BAD_STALACTITE) { physic.enable_gravity(false); @@ -229,33 +266,17 @@ BadGuy::init() set_sprite(img_flyingsnowball, img_flyingsnowball); physic.enable_gravity(false); } else if(kind == BAD_SPIKY) { - physic.set_velocity(-BADGUY_WALK_SPEED, 0); + physic.set_velocity(dirsign * BADGUY_WALK_SPEED, 0); set_sprite(img_spiky_left, img_spiky_right); } else if(kind == BAD_SNOWBALL) { - physic.set_velocity(-BADGUY_WALK_SPEED, 0); + physic.set_velocity(dirsign * BADGUY_WALK_SPEED, 0); set_sprite(img_snowball_left, img_snowball_right); } - // if we're in a solid tile at start correct that now - if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(base)) - { - std::cout << "Warning: badguy started in wall: kind: " << badguykind_to_string(kind) - << " pos: (" << base.x << ", " << base.y << ")" << std::endl; - while(collision_object_map(base)) - --base.y; - } -} - -void -BadGuy::write(LispWriter& writer) -{ - writer.start_list(badguykind_to_string(kind)); - - writer.write_float("x", base.x); - writer.write_float("y", base.y); - writer.write_bool("stay-on-platform", stay_on_platform); - - writer.end_list(badguykind_to_string(kind)); + base.x = start_position.x; + base.y = start_position.y; + old_base = base; + seen = true; } void @@ -661,11 +682,7 @@ BadGuy::action_bouncingsnowball(double elapsed_time) // Handle dying timer: if (dying == DYING_SQUISHED && !timer.check()) - { - /* Remove it if time's up: */ - remove_me(); - return; - } + remove_me(); } void @@ -701,11 +718,7 @@ BadGuy::action_flyingsnowball(double elapsed_time) // Handle dying timer: if (dying == DYING_SQUISHED && !timer.check()) - { - /* Remove it if time's up: */ - remove_me(); - return; - } + remove_me(); } void @@ -746,6 +759,10 @@ BadGuy::action_snowball(double elapsed_time) physic.apply(elapsed_time, base.x, base.y); if (dying != DYING_FALLING) collision_swept_object_map(&old_base,&base); + + // Handle dying timer: + if (dying == DYING_SQUISHED && !timer.check()) + remove_me(); } void @@ -771,16 +788,37 @@ BadGuy::action(float elapsed_time) kill_me(0); } - // Once it's on screen, it's activated! - if (base.x > scroll_x - X_OFFSCREEN_DISTANCE && - base.x < scroll_x + screen->w + X_OFFSCREEN_DISTANCE && - base.y > scroll_y - Y_OFFSCREEN_DISTANCE && - base.y < scroll_y + screen->h + Y_OFFSCREEN_DISTANCE) - seen = true; - + if(!seen) { + /* activate badguys if they're just inside the offscreen_distance around the + * screen. Don't activate them inside the screen, since that might have the + * effect of badguys suddenly popping up from nowhere + */ + if (start_position.x > scroll_x - X_OFFSCREEN_DISTANCE && + start_position.x < scroll_x - base.width) + activate(RIGHT); + else if(start_position.x > scroll_y - Y_OFFSCREEN_DISTANCE && + start_position.y < scroll_y - base.height) + activate(LEFT); + else if(start_position.x > scroll_x + screen->w && + start_position.x < scroll_x + screen->w + X_OFFSCREEN_DISTANCE) + activate(LEFT); + else if(start_position.y > scroll_y + screen->h && + start_position.y < scroll_y + screen->h + Y_OFFSCREEN_DISTANCE) + activate(LEFT); + } else { + if(base.x + base.width < scroll_x - X_OFFSCREEN_DISTANCE + || base.x > scroll_x + screen->w + X_OFFSCREEN_DISTANCE + || base.y + base.height < scroll_y - Y_OFFSCREEN_DISTANCE + || base.y > scroll_y + screen->h + Y_OFFSCREEN_DISTANCE) { + seen = false; + if(dying != DYING_NOT) + remove_me(); + } + } + if(!seen) return; - + switch (kind) { case BAD_MRICEBLOCK: @@ -968,7 +1006,7 @@ BadGuy::squish(Player* player) player_status.score_multiplier++; - // check for maximum number of squiches + // check for maximum number of squishes squishcount++; if(squishcount >= MAX_ICEBLOCK_SQUICHES) { kill_me(50); diff --git a/src/badguy.h b/src/badguy.h index 9c504e821..b4c3f527f 100644 --- a/src/badguy.h +++ b/src/badguy.h @@ -102,6 +102,7 @@ private: bool seen; int squishcount; /// number of times this enemy was squiched Timer timer; + Vector start_position; Physic physic; float angle; @@ -144,6 +145,9 @@ private: void action_spiky(double frame_ratio); void action_snowball(double frame_ratio); + /** initializes the badguy (when he appears on screen) */ + void activate(Direction direction); + /** handles falling down. disables gravity calculation when we're back on * ground */ void fall(); diff --git a/src/world.cpp b/src/world.cpp index d8a4f7c26..9ba5d1867 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -203,7 +203,8 @@ World::action(float elapsed_time) * during the iteration) */ for(size_t i = 0; i < gameobjects.size(); ++i) - gameobjects[i]->action(elapsed_time); + if(gameobjects[i]->is_valid()) + gameobjects[i]->action(elapsed_time); /* Handle all possible collisions. */ collision_handler();