From: Tobias Gläßer Date: Sun, 4 Apr 2004 00:32:10 +0000 (+0000) Subject: - Physic C++ rewrite (Matze Braun) X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=a2715d2de23913e3bd458cbea162924e2f379495;p=supertux.git - Physic C++ rewrite (Matze Braun) - Added new badguys (Matze Braun) - Fixed minor bugs (Matze Braun) SVN-Revision: 430 --- diff --git a/src/badguy.cpp b/src/badguy.cpp index ce393bf56..37d196813 100644 --- a/src/badguy.cpp +++ b/src/badguy.cpp @@ -16,15 +16,16 @@ #include "badguy.h" #include "scene.h" #include "screen.h" - -texture_type img_bsod_squished_left; -texture_type img_bsod_squished_right; -texture_type img_bsod_falling_left; -texture_type img_bsod_falling_right; -texture_type img_laptop_flat_left; -texture_type img_laptop_flat_right; -texture_type img_laptop_falling_left; -texture_type img_laptop_falling_right; +#include "tile.h" + +texture_type img_bsod_squished_left[1]; +texture_type img_bsod_squished_right[1]; +texture_type img_bsod_falling_left[1]; +texture_type img_bsod_falling_right[1]; +texture_type img_laptop_flat_left[1]; +texture_type img_laptop_flat_right[1]; +texture_type img_laptop_falling_left[1]; +texture_type img_laptop_falling_right[1]; texture_type img_bsod_left[4]; texture_type img_bsod_right[4]; texture_type img_laptop_left[3]; @@ -33,12 +34,24 @@ texture_type img_money_left[2]; texture_type img_money_right[2]; texture_type img_mrbomb_left[4]; texture_type img_mrbomb_right[4]; -texture_type img_mrbomb_ticking_left; -texture_type img_mrbomb_ticking_right; -texture_type img_mrbomb_explosion; -texture_type img_stalactite; -texture_type img_stalactite_broken; +texture_type img_mrbomb_ticking_left[1]; +texture_type img_mrbomb_ticking_right[1]; +texture_type img_mrbomb_explosion[1]; +texture_type img_stalactite[1]; +texture_type img_stalactite_broken[1]; texture_type img_flame[2]; +texture_type img_fish[2]; +texture_type img_bouncingsnowball_left[6]; +texture_type img_bouncingsnowball_right[6]; +texture_type img_bouncingsnowball_squished[1]; +texture_type img_flyingsnowball[2]; +texture_type img_flyingsnowball_squished[1]; +texture_type img_spiky_left[3]; +texture_type img_spiky_right[3]; +texture_type img_snowball_left[3]; +texture_type img_snowball_right[3]; +texture_type img_snowball_squished_left[1]; +texture_type img_snowball_squished_right[1]; BadGuyKind badguykind_from_string(const std::string& str) { @@ -54,9 +67,19 @@ BadGuyKind badguykind_from_string(const std::string& str) return BAD_STALACTITE; else if (str == "flame") return BAD_FLAME; + else if (str == "fish") + return BAD_FISH; + else if (str == "bouncingsnowball") + return BAD_BOUNCINGSNOWBALL; + else if (str == "flyingsnowball") + return BAD_FLYINGSNOWBALL; + else if (str == "spiky") + return BAD_SPIKY; + else if (str == "snowball") + return BAD_SNOWBALL; else { - printf("Couldn't convert badguy: %s\n", str.c_str()); + printf("Couldn't convert badguy: '%s'\n", str.c_str()); return BAD_BSOD; } } @@ -83,6 +106,21 @@ std::string badguykind_to_string(BadGuyKind kind) case BAD_FLAME: return "flame"; break; + case BAD_FISH: + return "fish"; + break; + case BAD_BOUNCINGSNOWBALL: + return "bouncingsnowball"; + break; + case BAD_FLYINGSNOWBALL: + return "flyingsnowball"; + break; + case BAD_SPIKY: + return "spiky"; + break; + case BAD_SNOWBALL: + return "snowball"; + break; default: return "bsod"; } @@ -93,51 +131,87 @@ BadGuy::init(float x, float y, BadGuyKind kind_) { base.x = x; base.y = y; - base.width = 32; - base.height = 32; + base.width = 0; + base.height = 0; + base.xm = 0; + base.ym = 0; + mode = NORMAL; dying = DYING_NOT; kind = kind_; - base.xm = -1.3; - base.ym = 0; old_base = base; dir = LEFT; seen = false; + animation_speed = 1; + animation_length = 1; + animation_offset = 0; + texture_left = texture_right = 0; + physic.reset(); timer_init(&timer, true); - physic_init(&physic); - if(kind == BAD_BOMB) { - timer_start(&timer, 1000); - mode = BOMB_TICKING; + if(kind == BAD_BSOD) { + physic.set_velocity(-1.3, 0); + set_texture(img_bsod_left, img_bsod_right, 4); + } else if(kind == BAD_MRBOMB) { + physic.set_velocity(-1.3, 0); + set_texture(img_mrbomb_left, img_mrbomb_right, 4); + } else if (kind == BAD_LAPTOP) { + physic.set_velocity(-1.3, 0); + set_texture(img_laptop_left, img_laptop_right, 3); + } else if(kind == BAD_MONEY) { + set_texture(img_money_left, img_money_right, 1); + } else if(kind == BAD_BOMB) { + set_texture(img_mrbomb_ticking_left, img_mrbomb_ticking_right, 1); // hack so that the bomb doesn't hurt until it expldes... dying = DYING_SQUISHED; } else if(kind == BAD_FLAME) { base.ym = 0; // we misuse base.ym as angle for the flame - } else if(kind == BAD_MONEY) { - base.ym = 4.8; + physic.enable_gravity(false); + set_texture(img_flame, img_flame, 2, 0.5); + } else if(kind == BAD_BOUNCINGSNOWBALL) { + physic.set_velocity(-1.3, 0); + set_texture(img_bouncingsnowball_left, img_bouncingsnowball_right, 6); + } else if(kind == BAD_STALACTITE) { + physic.enable_gravity(false); + set_texture(img_stalactite, img_stalactite, 1); + } else if(kind == BAD_FISH) { + set_texture(img_fish, img_fish, 2, 1); + physic.enable_gravity(true); + } else if(kind == BAD_FLYINGSNOWBALL) { + set_texture(img_flyingsnowball, img_flyingsnowball, 2); + physic.enable_gravity(false); + } else if(kind == BAD_SPIKY) { + physic.set_velocity(-1.3, 0); + set_texture(img_spiky_left, img_spiky_right, 3); + } else if(kind == BAD_SNOWBALL) { + physic.set_velocity(-1.3, 0); + set_texture(img_snowball_left, img_snowball_right, 3); + } + + // if we're in a solid tile at start correct that now + if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(&base)) { + printf("Warning: badguy started in wall!.\n"); + while(collision_object_map(&base)) + --base.y; } } -void BadGuy::action_bsod() +void +BadGuy::action_bsod() { - /* --- BLUE SCREEN OF DEATH MONSTER: --- */ - - /* Move left/right: */ - if (dying == DYING_NOT || dying == DYING_FALLING) - { - base.x += base.xm * frame_ratio; - } - - /* Move vertically: */ - base.y += base.ym * frame_ratio; - - if (dying != DYING_FALLING) - collision_swept_object_map(&old_base,&base); - - if (!dying) + static const float BSODJUMP = 2; + + if (dying == DYING_NOT) check_horizontal_bump(); - fall(true); + fall(); + + // jump when we're about to fall + if (physic.get_velocity_y() == 0 && + !issolid(base.x+base.width/2, base.y + base.height)) { + physic.enable_gravity(true); + physic.set_velocity(physic.get_velocity_x(), BSODJUMP); + } // Handle dying timer: if (dying == DYING_SQUISHED && !timer_check(&timer)) @@ -146,18 +220,25 @@ void BadGuy::action_bsod() remove_me(); return; } + + // move + physic.apply(base.x, base.y); + if(dying != DYING_FALLING) + collision_swept_object_map(&old_base, &base); } -void BadGuy::action_laptop() +void +BadGuy::action_laptop() { + fall(); + /* Move left/right: */ if (mode == NORMAL || mode == KICK) { - if (dying == DYING_NOT || - dying == DYING_FALLING) - { - base.x += base.xm * frame_ratio; - } + // move + physic.apply(base.x, base.y); + if (dying != DYING_FALLING) + collision_swept_object_map(&old_base,&base); } else if (mode == HELD) { /* FIXME: The pbad object shouldn't know about pplayer objects. */ @@ -187,21 +268,12 @@ void BadGuy::action_laptop() base.x += 24; mode=KICK; - base.xm = 8; - base.ym = 8; + set_texture(img_laptop_flat_left, img_laptop_flat_right, 1); + physic.set_velocity((dir == LEFT) ? -8 : 8, -8); play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER); } } - - /* Move vertically: */ - if(mode != HELD) - base.y = base.y + base.ym * frame_ratio; - - if (dying != DYING_FALLING) - collision_swept_object_map(&old_base,&base); - /* Bump into things horizontally: */ - if (!dying) { int changed = dir; @@ -218,101 +290,87 @@ void BadGuy::action_laptop() } } - fall(); - /* Handle mode timer: */ if (mode == FLAT) { if(!timer_check(&timer)) { mode = NORMAL; - base.xm = (dir == LEFT) ? -1.3 : 1.3; + set_texture(img_laptop_left, img_laptop_right, 3); + physic.set_velocity( (dir == LEFT) ? -1.3 : 1.3, 0); } } } -void BadGuy::check_horizontal_bump(bool checkcliff) +void +BadGuy::check_horizontal_bump(bool checkcliff) { - if (dir == LEFT && issolid( base.x, (int) base.y + 16)) + float halfheight = base.height / 2; + if (dir == LEFT && issolid( base.x, (int) base.y + halfheight)) { dir = RIGHT; - base.xm = -base.xm; + physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y()); return; } - if (dir == RIGHT && issolid( base.x + base.width, (int) base.y + 16)) + if (dir == RIGHT && issolid( base.x + base.width, (int)base.y + halfheight)) { dir = LEFT; - base.xm = -base.xm; + physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y()); return; } // don't check for cliffs when we're falling if(!checkcliff) return; - if(!issolid(base.x + base.width/2, base.y + base.height + 16)) + if(!issolid(base.x + base.width/2, base.y + base.height)) return; - if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + 16)) + if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + halfheight)) { - printf("Cliffcol left\n"); dir = RIGHT; - base.xm = -base.xm; + physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y()); return; } if(dir == RIGHT && !issolid(base.x + base.width, - (int) base.y + base.height + 16)) + (int) base.y + base.height + halfheight)) { - printf("Cliffcol right\n"); dir = LEFT; - base.xm = -base.xm; + physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y()); return; } } -void BadGuy::fall(bool dojump) +void +BadGuy::fall() { /* Fall if we get off the ground: */ if (dying != DYING_FALLING) { if (!issolid(base.x+base.width/2, base.y + base.height)) { - if(!physic_is_set(&physic)) - { - physic_set_state(&physic,PH_VT); - physic_set_start_vy(&physic, dojump ? 2. : 0.); - } - - base.ym = physic_get_velocity(&physic); + // not solid below us? enable gravity + physic.enable_gravity(true); } else { /* Land: */ - if (base.ym > 0) + if (physic.get_velocity_y() < 0) { base.y = int((base.y + base.height)/32) * 32 - base.height; - base.ym = 0; + physic.set_velocity(physic.get_velocity_x(), 0); } - physic_init(&physic); + // no gravity anymore please + physic.enable_gravity(false); } } else { - if(!physic_is_set(&physic)) - { - physic_set_state(&physic,PH_VT); - physic_set_start_vy(&physic,0.); - } - base.ym = physic_get_velocity(&physic); + physic.enable_gravity(true); } - - // BadGuy fall below the ground - if (base.y > screen->h) { - remove_me(); - return; - } } -void BadGuy::remove_me() +void +BadGuy::remove_me() { std::vector::iterator i; for(i = bad_guys.begin(); i != bad_guys.end(); ++i) { @@ -323,102 +381,91 @@ void BadGuy::remove_me() } } -void BadGuy::action_money() +void +BadGuy::action_money() { - /* Move vertically: */ - base.y = base.y + base.ym * frame_ratio; - - if (dying != DYING_FALLING) - collision_swept_object_map(&old_base,&base); - - if (base.y > screen->h) { - remove_me(); - return; - } - - if(physic_get_state(&physic) == -1) + static const float JUMPV = 6; + + fall(); + // jump when on ground + if(dying == DYING_NOT && issolid(base.x, base.y+32)) { - physic_set_state(&physic,PH_VT); - physic_set_start_vy(&physic,0.); + physic.set_velocity(physic.get_velocity_x(), JUMPV); + physic.enable_gravity(true); + set_texture(&img_money_left[1], &img_money_right[1], 1); + mode = MONEY_JUMP; } - - if (dying != DYING_FALLING) + else if(mode == MONEY_JUMP) { - - if(issolid(base.x, base.y + 32)) - { - physic_set_state(&physic,PH_VT); - physic_set_start_vy(&physic,6.); - base.ym = physic_get_velocity(&physic); - mode = MONEY_JUMP; - } - else - { - base.ym = physic_get_velocity(&physic); - mode = NORMAL; - } + set_texture(&img_money_left[0], &img_money_right[0], 1); + mode = NORMAL; } + + // set direction based on tux + if(tux.base.x > base.x) + dir = RIGHT; else - { - if(!physic_is_set(&physic)) - { - physic_set_state(&physic,PH_VT); - physic_set_start_vy(&physic,0.); - } - base.ym = physic_get_velocity(&physic); - } + dir = LEFT; + + // move + physic.apply(base.x, base.y); + if(dying == DYING_NOT) + collision_swept_object_map(&old_base, &base); } -void BadGuy::action_mrbomb() +void +BadGuy::action_mrbomb() { - if(mode == NORMAL) { - base.x += base.xm * frame_ratio; - } + if (dying == DYING_NOT) + check_horizontal_bump(true); - /* Move vertically: */ - base.y += base.ym * frame_ratio; + fall(); + physic.apply(base.x, base.y); if (dying != DYING_FALLING) - collision_swept_object_map(&old_base,&base); - - check_horizontal_bump(true); - fall(); + collision_swept_object_map(&old_base,&base); } -void BadGuy::action_bomb() +void +BadGuy::action_bomb() { - // eventually fall down - base.y += base.ym * frame_ratio; - collision_swept_object_map(&old_base,&base); + static const int TICKINGTIME = 1000; + static const int EXPLODETIME = 1000; + fall(); - if(!timer_check(&timer)) { + if(mode == NORMAL) { + mode = BOMB_TICKING; + timer_start(&timer, TICKINGTIME); + } else if(!timer_check(&timer)) { if(mode == BOMB_TICKING) { mode = BOMB_EXPLODE; + set_texture(img_mrbomb_explosion, img_mrbomb_explosion, 1); dying = DYING_NOT; // now the bomb hurts - timer_start(&timer, 1000); - // explosion image has different size - base.x -= (img_mrbomb_explosion.w - base.width) / 2; - base.y -= img_mrbomb_explosion.h - base.height; - base.width = img_mrbomb_explosion.w; - base.height = img_mrbomb_explosion.h; - old_base = base; + timer_start(&timer, EXPLODETIME); } else if(mode == BOMB_EXPLODE) { remove_me(); return; } } + + // move + physic.apply(base.x, base.y); + collision_swept_object_map(&old_base,&base); } -void BadGuy::action_stalactite() +void +BadGuy::action_stalactite() { + static const int SHAKETIME = 800; + static const int RANGE = 40; + if(mode == NORMAL) { - static const int range = 40; // start shaking when tux is below the stalactite and at least 40 pixels // near - if(tux.base.x + 32 > base.x - range && tux.base.x < base.x + 32 + range + if(tux.base.x + 32 > base.x - RANGE && tux.base.x < base.x + 32 + RANGE && tux.base.y + tux.base.height > base.y) { - timer_start(&timer, 800); + timer_start(&timer, SHAKETIME); mode = STALACTITE_SHAKING; } } if(mode == STALACTITE_SHAKING) { @@ -427,20 +474,24 @@ void BadGuy::action_stalactite() mode = STALACTITE_FALL; } } else if(mode == STALACTITE_FALL) { - base.y += base.ym * frame_ratio; fall(); - /* Destroy if collides land */ - if(issolid(base.x+16, base.y+32)) + /* Destroy if we collides with land */ + if(issolid(base.x+base.width/2, base.y+base.height)) { - timer_start(&timer, 3000); + timer_start(&timer, 2000); dying = DYING_SQUISHED; mode = FLAT; + set_texture(img_stalactite_broken, img_stalactite_broken, 1); } } else if(mode == FLAT) { - if(!timer_check(&timer)) { - remove_me(); - } + fall(); } + + // move + physic.apply(base.x, base.y); + + if(dying == DYING_SQUISHED && !timer_check(&timer)) + remove_me(); } void @@ -455,6 +506,145 @@ BadGuy::action_flame() } void +BadGuy::action_fish() +{ + static const float JUMPV = 6; + static const int WAITTIME = 1000; + + // go in wait mode when back in water + if(dying == DYING_NOT && gettile(base.x, base.y+ base.height)->water + && physic.get_velocity_y() <= 0 && mode == NORMAL) + { + mode = FISH_WAIT; + set_texture(0, 0); + physic.set_velocity(0, 0); + physic.enable_gravity(false); + timer_start(&timer, WAITTIME); + } + else if(mode == FISH_WAIT && !timer_check(&timer)) + { + // jump again + set_texture(img_fish, img_fish, 2, 1.5); + animation_offset = global_frame_counter; // restart animation + mode = NORMAL; + physic.set_velocity(0, JUMPV); + physic.enable_gravity(true); + } + + physic.apply(base.x, base.y); + if(dying == DYING_NOT) + collision_swept_object_map(&old_base, &base); +} + +void +BadGuy::action_bouncingsnowball() +{ + static const float JUMPV = 4.5; + + fall(); + + // jump when on ground + if(dying == DYING_NOT && issolid(base.x, base.y+32)) + { + physic.set_velocity(physic.get_velocity_x(), JUMPV); + physic.enable_gravity(true); + } + else + { + mode = NORMAL; + } + + // check for right/left collisions + check_horizontal_bump(); + + physic.apply(base.x, base.y); + if(dying == DYING_NOT) + collision_swept_object_map(&old_base, &base); + + // Handle dying timer: + if (dying == DYING_SQUISHED && !timer_check(&timer)) + { + /* Remove it if time's up: */ + remove_me(); + return; + } +} + +void +BadGuy::action_flyingsnowball() +{ + static const float FLYINGSPEED = 1; + static const int DIRCHANGETIME = 1000; + + // go into flyup mode if none specified yet + if(dying == DYING_NOT && mode == NORMAL) { + mode = FLY_UP; + physic.set_velocity(physic.get_velocity_x(), FLYINGSPEED); + timer_start(&timer, DIRCHANGETIME/2); + } + + if(dying == DYING_NOT && !timer_check(&timer)) { + if(mode == FLY_UP) { + mode = FLY_DOWN; + physic.set_velocity(physic.get_velocity_x(), -FLYINGSPEED); + } else if(mode == FLY_DOWN) { + mode = FLY_UP; + physic.set_velocity(physic.get_velocity_x(), FLYINGSPEED); + } + timer_start(&timer, DIRCHANGETIME); + } + + if(dying != DYING_NOT) + physic.enable_gravity(true); + + physic.apply(base.x, base.y); + if(dying == DYING_NOT || dying == DYING_SQUISHED) + collision_swept_object_map(&old_base, &base); + + // Handle dying timer: + if (dying == DYING_SQUISHED && !timer_check(&timer)) + { + /* Remove it if time's up: */ + remove_me(); + return; + } +} + +void +BadGuy::action_spiky() +{ + if (dying == DYING_NOT) + check_horizontal_bump(); + + fall(); +#if 0 + // jump when we're about to fall + if (physic.get_velocity_y() == 0 && + !issolid(base.x+base.width/2, base.y + base.height)) { + physic.enable_gravity(true); + physic.set_velocity(physic.get_velocity_x(), 2); + } +#endif + + physic.apply(base.x, base.y); + if (dying != DYING_FALLING) + collision_swept_object_map(&old_base,&base); +} + +void +BadGuy::action_snowball() +{ + if (dying == DYING_NOT) + check_horizontal_bump(); + + fall(); + + physic.apply(base.x, base.y); + if (dying != DYING_FALLING) + collision_swept_object_map(&old_base,&base); +} + +void BadGuy::action() { // Remove if it's far off the screen: @@ -464,6 +654,12 @@ BadGuy::action() return; } + // BadGuy fall below the ground + if (base.y > screen->h) { + remove_me(); + return; + } + // Once it's on screen, it's activated! if (base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE) seen = true; @@ -500,176 +696,104 @@ BadGuy::action() case BAD_FLAME: action_flame(); break; - } -} -void -BadGuy::draw_bsod() -{ - texture_type* texture = 0; - - if(dying == DYING_NOT) { - size_t frame = (global_frame_counter / 5) % 4; - texture = (dir == LEFT) ? &img_bsod_left[frame] : &img_bsod_right[frame]; - } else if(dying == DYING_FALLING) { - texture = (dir == LEFT) ? &img_bsod_falling_left : &img_bsod_falling_right; - } else if(dying == DYING_SQUISHED) { - texture = (dir == LEFT) - ? &img_bsod_squished_left : &img_bsod_squished_right; - } - - texture_draw(texture, base.x - scroll_x, base.y); -} - -void -BadGuy::draw_laptop() -{ - texture_type* texture; - size_t frame = (global_frame_counter / 5) % 3; - - if(dying == DYING_NOT) { - if(mode == NORMAL) { - if(dir == LEFT) - texture = &img_laptop_left[frame]; - else - texture = &img_laptop_right[frame]; - } else { - texture = (dir == LEFT) ? &img_laptop_flat_left : &img_laptop_flat_right; - } - } else { - texture = (dir == LEFT) - ? &img_laptop_falling_left : &img_laptop_falling_right; - } + case BAD_FISH: + action_fish(); + break; - texture_draw(texture, base.x - scroll_x, base.y); -} + case BAD_BOUNCINGSNOWBALL: + action_bouncingsnowball(); + break; -void -BadGuy::draw_money() -{ - texture_type* texture; - size_t frame = (mode == NORMAL) ? 0 : 1; + case BAD_FLYINGSNOWBALL: + action_flyingsnowball(); + break; - if(tux.base.x + tux.base.width < base.x) { - texture = &img_money_left[frame]; - } else { - texture = &img_money_right[frame]; - } + case BAD_SPIKY: + action_spiky(); + break; - texture_draw(texture, base.x - scroll_x, base.y); + case BAD_SNOWBALL: + action_snowball(); + break; + } } - + void -BadGuy::draw_mrbomb() +BadGuy::draw() { - texture_type* texture; - size_t frame = (global_frame_counter/5) % 4; - - if(dir == LEFT) - texture = &img_mrbomb_left[frame]; - else - texture = &img_mrbomb_right[frame]; + // Don't try to draw stuff that is outside of the screen + if(base.x <= scroll_x - base.width || base.x >= scroll_x + screen->w) + return; + if(texture_left == 0 || texture_right == 0) + return; + float global_frame = (float(global_frame_counter - animation_offset) / 10); + global_frame *= animation_speed; + size_t frame = size_t(global_frame) % animation_length; + texture_type* texture = + (dir == LEFT) ? &texture_left[frame] : &texture_right[frame]; texture_draw(texture, base.x - scroll_x, base.y); } void -BadGuy::draw_bomb() +BadGuy::set_texture(texture_type* left, texture_type* right, + int nanimlength, float nanimspeed) { - texture_type* texture; - - // TODO add real bomb graphics - if(mode == BOMB_TICKING) { - texture = (dir == LEFT) - ? &img_mrbomb_ticking_left : &img_mrbomb_ticking_right; + if(left != 0) { + if(base.width == 0 && base.height == 0) { + base.width = left->w; + base.height = left->h; + } else if(base.width != left->w || base.height != left->h) { + base.x -= (left->w - base.width) / 2; + base.y -= left->h - base.height; + base.width = left->w; + base.height = left->h; + old_base = base; + } } else { - texture = &img_mrbomb_explosion; + base.width = base.height = 0; } - - texture_draw(texture, base.x - scroll_x, base.y); -} -void -BadGuy::draw_stalactite() -{ - texture_type* texture; - if(mode != FLAT) - texture = &img_stalactite; - else - texture = &img_stalactite_broken; - - texture_draw(texture, base.x - scroll_x, base.y); + animation_length = nanimlength; + animation_speed = nanimspeed; + animation_offset = 0; + texture_left = left; + texture_right = right; } void -BadGuy::draw_flame() +BadGuy::bump() { - size_t frame = (global_frame_counter / 10) % 2; - texture_type* texture = &img_flame[frame]; - - texture_draw(texture, base.x - scroll_x, base.y); + if(kind == BAD_BSOD || kind == BAD_LAPTOP || kind == BAD_MRBOMB + || kind == BAD_BOUNCINGSNOWBALL) { + kill_me(); + } } void -BadGuy::draw() +BadGuy::make_player_jump(Player* player) { - // Don't try to draw stuff that is outside of the screen - if (base.x <= scroll_x - base.width || base.x >= scroll_x + screen->w) - return; - - switch (kind) - { - case BAD_BSOD: - draw_bsod(); - break; - - case BAD_LAPTOP: - draw_laptop(); - break; - - case BAD_MONEY: - draw_money(); - break; - - case BAD_MRBOMB: - draw_mrbomb(); - break; - - case BAD_BOMB: - draw_bomb(); - break; - - case BAD_STALACTITE: - draw_stalactite(); - break; - - case BAD_FLAME: - draw_flame(); - break; - - } + player->physic.set_velocity(player->physic.get_velocity_x(), 2); + player->base.y = base.y - player->base.height - 2; } void -BadGuy::bump() +BadGuy::squish_me(Player* player) { - if(kind == BAD_BSOD || kind == BAD_LAPTOP || kind == BAD_BOMB) { - dying = DYING_FALLING; - base.ym = -8; - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - } -} + make_player_jump(player); + + add_score(base.x - scroll_x, base.y, 50 * score_multiplier); + play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER); + score_multiplier++; -void -BadGuy::make_player_jump(Player* player) -{ - physic_set_state(&player->vphysic,PH_VT); - physic_set_start_vy(&player->vphysic, 2.); - player->base.y = base.y - player->base.height - 2; + dying = DYING_SQUISHED; + timer_start(&timer, 2000); + physic.set_velocity(0, 0); } void -BadGuy::squich(Player* player) +BadGuy::squish(Player* player) { if(kind == BAD_MRBOMB) { // mrbomb transforms into a bomb now @@ -684,18 +808,9 @@ BadGuy::squich(Player* player) return; } else if(kind == BAD_BSOD) { - make_player_jump(player); - - add_score(base.x - scroll_x, base.y, 50 * score_multiplier); - play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER); - score_multiplier++; - - dying = DYING_SQUISHED; - timer_start(&timer, 2000); - base.y += base.height - img_bsod_squished_left.h; - base.height = img_bsod_squished_left.h; - base.xm = base.ym = 0; - old_base = base; + squish_me(player); + set_texture(img_bsod_squished_left, img_bsod_squished_right, 1); + physic.set_velocity(0, physic.get_velocity_y()); return; } else if (kind == BAD_LAPTOP) { @@ -704,7 +819,8 @@ BadGuy::squich(Player* player) /* Flatten! */ play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER); mode = FLAT; - base.xm = 0; + set_texture(img_laptop_flat_left, img_laptop_flat_right, 1); + physic.set_velocity(0, physic.get_velocity_y()); timer_start(&timer, 4000); } else if (mode == FLAT) { @@ -712,14 +828,15 @@ BadGuy::squich(Player* player) play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER); if (player->base.x < base.x + (base.width/2)) { - base.xm = 5; + physic.set_velocity(5, physic.get_velocity_y()); dir = RIGHT; } else { - base.xm = -5; + physic.set_velocity(-5, physic.get_velocity_y()); dir = LEFT; } mode = KICK; + set_texture(img_laptop_flat_left, img_laptop_flat_right, 1); } make_player_jump(player); @@ -727,10 +844,58 @@ BadGuy::squich(Player* player) add_score(base.x - scroll_x, base.y, 25 * score_multiplier); score_multiplier++; return; + } else if(kind == BAD_FISH) { + make_player_jump(player); + + add_score(base.x - scroll_x, base.y, 25 * score_multiplier); + score_multiplier++; + + // simply remove the fish... + remove_me(); + return; + } else if(kind == BAD_BOUNCINGSNOWBALL) { + squish_me(player); + set_texture(img_bouncingsnowball_squished,img_bouncingsnowball_squished,1); + return; + } else if(kind == BAD_FLYINGSNOWBALL) { + squish_me(player); + set_texture(img_flyingsnowball_squished,img_flyingsnowball_squished,1); + return; + } else if(kind == BAD_SNOWBALL) { + squish_me(player); + set_texture(img_snowball_squished_left, img_snowball_squished_right, 1); + return; } } void +BadGuy::kill_me() +{ + if(kind == BAD_BOMB || kind == BAD_STALACTITE || kind == BAD_FLAME) + return; + + dying = DYING_FALLING; + if(kind == BAD_LAPTOP) + set_texture(img_laptop_falling_left, img_laptop_falling_right, 1); + else if(kind == BAD_BSOD) + set_texture(img_bsod_falling_left, img_bsod_falling_right, 1); + + physic.enable_gravity(true); + physic.set_velocity(physic.get_velocity_x(), 0); + + /* Gain some points: */ + if (kind == BAD_BSOD) + add_score(base.x - scroll_x, base.y, + 50 * score_multiplier); + else + add_score(base.x - scroll_x, base.y, + 25 * score_multiplier); + + /* Play death sound: */ + play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); +} + +void BadGuy::collision(void *p_c_object, int c_object, CollisionType type) { BadGuy* pbad_c = NULL; @@ -739,55 +904,27 @@ BadGuy::collision(void *p_c_object, int c_object, CollisionType type) bump(); return; } - if(type == COLLISION_SQUICH) { + if(type == COLLISION_SQUISH) { Player* player = static_cast(p_c_object); - squich(player); + squish(player); return; } switch (c_object) { case CO_BULLET: - if(kind == BAD_BOMB || kind == BAD_STALACTITE || kind == BAD_FLAME) - return; - - dying = DYING_FALLING; - base.ym = -8; - - /* Gain some points: */ - if (kind == BAD_BSOD) - add_score(base.x - scroll_x, base.y, - 50 * score_multiplier); - else if (kind == BAD_LAPTOP) - add_score(base.x - scroll_x, base.y, - 25 * score_multiplier); - else if (kind == BAD_MONEY) - add_score(base.x - scroll_x, base.y, - 50 * score_multiplier); - - /* Play death sound: */ - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); + kill_me(); break; case CO_BADGUY: pbad_c = (BadGuy*) p_c_object; - if(kind == BAD_LAPTOP && mode == KICK) + if(kind == BAD_LAPTOP && mode == KICK && + pbad_c->kind != BAD_FLAME && pbad_c->kind != BAD_BOMB) { /* We're in kick mode, kill the other guy and yourself(wuahaha) : */ - - pbad_c->dying = DYING_FALLING; - pbad_c->base.ym = -8; - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - - add_score(base.x - scroll_x, - base.y, 100); - - dying = DYING_FALLING; - base.ym = -8; - - add_score(pbad_c->base.x - scroll_x, - pbad_c->base.y, 100); + pbad_c->kill_me(); + kill_me(); } break; } @@ -830,19 +967,19 @@ void load_badguy_gfx() "/images/shared/bsod-right-3.png", USE_ALPHA); - texture_load(&img_bsod_squished_left, datadir + + texture_load(&img_bsod_squished_left[0], datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA); - texture_load(&img_bsod_squished_right, datadir + + texture_load(&img_bsod_squished_right[0], datadir + "/images/shared/bsod-squished-right.png", USE_ALPHA); - texture_load(&img_bsod_falling_left, datadir + + texture_load(&img_bsod_falling_left[0], datadir + "/images/shared/bsod-falling-left.png", USE_ALPHA); - texture_load(&img_bsod_falling_right, datadir + + texture_load(&img_bsod_falling_right[0], datadir + "/images/shared/bsod-falling-right.png", USE_ALPHA); @@ -873,19 +1010,19 @@ void load_badguy_gfx() "/images/shared/laptop-right-2.png", USE_ALPHA); - texture_load(&img_laptop_flat_left, datadir + + texture_load(&img_laptop_flat_left[0], datadir + "/images/shared/laptop-flat-left.png", USE_ALPHA); - texture_load(&img_laptop_flat_right, datadir + + texture_load(&img_laptop_flat_right[0], datadir + "/images/shared/laptop-flat-right.png", USE_ALPHA); - texture_load(&img_laptop_falling_left, datadir + + texture_load(&img_laptop_falling_left[0], datadir + "/images/shared/laptop-falling-left.png", USE_ALPHA); - texture_load(&img_laptop_falling_right, datadir + + texture_load(&img_laptop_falling_right[0], datadir + "/images/shared/laptop-falling-right.png", USE_ALPHA); @@ -917,17 +1054,17 @@ void load_badguy_gfx() texture_load(&img_mrbomb_right[i], datadir + "/images/shared/mrbomb-right-" + num + ".png", USE_ALPHA); } - texture_load(&img_mrbomb_ticking_left, + texture_load(&img_mrbomb_ticking_left[0], datadir + "/images/shared/mrbombx-left-0.png", USE_ALPHA); - texture_load(&img_mrbomb_ticking_right, + texture_load(&img_mrbomb_ticking_right[0], datadir + "/images/shared/mrbombx-right-0.png", USE_ALPHA); - texture_load(&img_mrbomb_explosion, + texture_load(&img_mrbomb_explosion[0], datadir + "/images/shared/mrbomb-explosion.png", USE_ALPHA); /* stalactite */ - texture_load(&img_stalactite, + texture_load(&img_stalactite[0], datadir + "/images/shared/stalactite.png", USE_ALPHA); - texture_load(&img_stalactite_broken, + texture_load(&img_stalactite_broken[0], datadir + "/images/shared/stalactite-broken.png", USE_ALPHA); /* flame */ @@ -935,6 +1072,62 @@ void load_badguy_gfx() datadir + "/images/shared/flame-0.png", USE_ALPHA); texture_load(&img_flame[1], datadir + "/images/shared/flame-1.png", USE_ALPHA); + + /* fish */ + texture_load(&img_fish[0], + datadir + "/images/shared/fish-left-0.png", USE_ALPHA); + texture_load(&img_fish[1], + datadir + "/images/shared/fish-left-1.png", USE_ALPHA); + + /* bouncing snowball */ + for(int i=0; i<6; ++i) { + char num[4]; + snprintf(num, 4, "%d", i); + texture_load(&img_bouncingsnowball_left[i], + datadir + "/images/shared/bouncingsnowball-left-" + num + ".png", + USE_ALPHA); + texture_load(&img_bouncingsnowball_right[i], + datadir + "/images/shared/bouncingsnowball-right-" + num + ".png", + USE_ALPHA); + } + texture_load(&img_bouncingsnowball_squished[0], + datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA); + + /* flying snowball */ + texture_load(&img_flyingsnowball[0], + datadir + "/images/shared/flyingsnowball-left-0.png", USE_ALPHA); + texture_load(&img_flyingsnowball[1], + datadir + "/images/shared/flyingsnowball-left-1.png", USE_ALPHA); + texture_load(&img_flyingsnowball_squished[0], + datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA); + + /* spiky */ + for(int i = 0; i < 3; ++i) { + char num[4]; + snprintf(num, 4, "%d", i); + texture_load(&img_spiky_left[i], + datadir + "/images/shared/spiky-left-" + num + ".png", + USE_ALPHA); + texture_load(&img_spiky_right[i], + datadir + "/images/shared/spiky-right-" + num + ".png", + USE_ALPHA); + } + + /** snowball */ + for(int i = 0; i < 3; ++i) { + char num[4]; + snprintf(num, 4, "%d", i); + texture_load(&img_snowball_left[i], + datadir + "/images/shared/snowball-left-" + num + ".png", + USE_ALPHA); + texture_load(&img_snowball_right[i], + datadir + "/images/shared/snowball-right-" + num + ".png", + USE_ALPHA); + } + texture_load(&img_snowball_squished_left[0], + datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA); + texture_load(&img_snowball_squished_right[0], + datadir + "/images/shared/bsod-squished-right.png", USE_ALPHA); } void free_badguy_gfx() @@ -945,11 +1138,11 @@ void free_badguy_gfx() texture_free(&img_bsod_right[i]); } - texture_free(&img_bsod_squished_left); - texture_free(&img_bsod_squished_right); + texture_free(&img_bsod_squished_left[0]); + texture_free(&img_bsod_squished_right[0]); - texture_free(&img_bsod_falling_left); - texture_free(&img_bsod_falling_right); + texture_free(&img_bsod_falling_left[0]); + texture_free(&img_bsod_falling_right[0]); for (int i = 0; i < 3; i++) { @@ -957,11 +1150,11 @@ void free_badguy_gfx() texture_free(&img_laptop_right[i]); } - texture_free(&img_laptop_flat_left); - texture_free(&img_laptop_flat_right); + texture_free(&img_laptop_flat_left[0]); + texture_free(&img_laptop_flat_right[0]); - texture_free(&img_laptop_falling_left); - texture_free(&img_laptop_falling_right); + texture_free(&img_laptop_falling_left[0]); + texture_free(&img_laptop_falling_right[0]); for (int i = 0; i < 2; i++) { @@ -974,15 +1167,39 @@ void free_badguy_gfx() texture_free(&img_mrbomb_right[i]); } - texture_free(&img_mrbomb_ticking_left); - texture_free(&img_mrbomb_ticking_right); - texture_free(&img_mrbomb_explosion); + texture_free(&img_mrbomb_ticking_left[0]); + texture_free(&img_mrbomb_ticking_right[0]); + texture_free(&img_mrbomb_explosion[0]); - texture_free(&img_stalactite); - texture_free(&img_stalactite_broken); + texture_free(&img_stalactite[0]); + texture_free(&img_stalactite_broken[0]); texture_free(&img_flame[0]); texture_free(&img_flame[1]); + + texture_free(&img_fish[0]); + texture_free(&img_fish[1]); + + for(int i=0; i<6; ++i) { + texture_free(&img_bouncingsnowball_left[i]); + texture_free(&img_bouncingsnowball_right[i]); + } + texture_free(&img_bouncingsnowball_squished[0]); + + texture_free(&img_flyingsnowball[0]); + texture_free(&img_flyingsnowball[1]); + texture_free(&img_flyingsnowball_squished[0]); + + for(int i = 0; i<3; ++i) { + texture_free(&img_spiky_left[i]); + texture_free(&img_spiky_right[i]); + } + for(int i = 0; i<3; ++i) { + texture_free(&img_snowball_left[i]); + texture_free(&img_snowball_right[i]); + } + texture_free(&img_snowball_squished_left[0]); + texture_free(&img_snowball_squished_right[0]); } // EOF // diff --git a/src/badguy.h b/src/badguy.h index 71cf4d19f..5c7ed10e3 100644 --- a/src/badguy.h +++ b/src/badguy.h @@ -39,7 +39,12 @@ enum { BOMB_EXPLODE, STALACTITE_SHAKING, - STALACTITE_FALL + STALACTITE_FALL, + + FISH_WAIT, + + FLY_UP, + FLY_DOWN }; /* Bad guy kinds: */ @@ -50,7 +55,12 @@ enum BadGuyKind { BAD_MRBOMB, BAD_BOMB, BAD_STALACTITE, - BAD_FLAME + BAD_FLAME, + BAD_FISH, + BAD_BOUNCINGSNOWBALL, + BAD_FLYINGSNOWBALL, + BAD_SPIKY, + BAD_SNOWBALL }; BadGuyKind badguykind_from_string(const std::string& str); @@ -76,18 +86,26 @@ class Player; /* Badguy type: */ class BadGuy { - public: - int mode; +public: DyingType dying; + base_type base; BadGuyKind kind; - bool seen; + int mode; int dir; - base_type base; + +private: + bool seen; base_type old_base; timer_type timer; - physic_type physic; + Physic physic; - public: + texture_type* texture_left; + texture_type* texture_right; + int animation_offset; + size_t animation_length; + float animation_speed; + +public: void init(float x, float y, BadGuyKind kind); void action(); @@ -95,36 +113,49 @@ class BadGuy void collision(void* p_c_object, int c_object, CollisionType type = COLLISION_NORMAL); - - private: - void fall(bool dojump=false); - void remove_me(); + /** this functions tries to kill the badguy and lets him fall off the + * screen. Some badguys like the flame might ignore this. + */ + void kill_me(); + +private: void action_bsod(); - void draw_bsod(); - void action_laptop(); - void draw_laptop(); - void action_money(); - void draw_money(); - void action_bomb(); - void draw_bomb(); - void action_mrbomb(); - void draw_mrbomb(); - void action_stalactite(); - void draw_stalactite(); - void action_flame(); - void draw_flame(); - + void action_fish(); + void action_bouncingsnowball(); + void action_flyingsnowball(); + void action_spiky(); + void action_snowball(); + + /** handles falling down. disables gravity calculation when we're back on + * ground */ + void fall(); + /** remove ourself from the list of badguys. WARNING! This function will + * invalidate all members. So don't do anything else with member after calling + * this. + */ + void remove_me(); + /** let the player jump a bit (used when you hit a badguy) */ void make_player_jump(Player* player); + /** check if we're running left or right in a wall and eventually change + * direction + */ void check_horizontal_bump(bool checkcliff = false); + /** called when we're bumped from below with a block */ void bump(); - void squich(Player* player); + /** called when a player jumped on the badguy from above */ + void squish(Player* player); + /** squish ourself, give player score and set dying to DYING_SQICHED */ + void squish_me(Player* player); + /** set image of the badguy */ + void set_texture(texture_type* left, texture_type* right, + int animlength = 1, float animspeed = 1); }; #endif /*SUPERTUX_BADGUY_H*/ diff --git a/src/button.cpp b/src/button.cpp index f6541d90a..54f889e7e 100644 --- a/src/button.cpp +++ b/src/button.cpp @@ -17,8 +17,12 @@ #include "globals.h" #include "button.h" +timer_type Button::popup_timer; + Button::Button(std::string icon_file, std::string ninfo, SDLKey nshortcut, int x, int y, int mw, int mh) { + timer_init(&popup_timer,false); + char filename[1024]; if(!icon_file.empty()) @@ -85,6 +89,10 @@ void Button::change_icon(std::string icon_file, int mw, int mh) void Button::draw() { + if(state == BUTTON_HOVER) + if(!timer_check(&popup_timer)) + show_info = true; + fillrect(rect.x,rect.y,rect.w,rect.h,75,75,75,200); fillrect(rect.x+1,rect.y+1,rect.w-2,rect.h-2,175,175,175,200); if(bkgd != NULL) @@ -152,7 +160,7 @@ void Button::event(SDL_Event &event) mouse_cursor->set_state(MC_LINK); } } - else if(event.type != SDL_KEYDOWN && event.type != SDL_KEYUP) + else if((event.type != SDL_KEYDOWN && event.type != SDL_KEYUP) || event.type == SDL_MOUSEMOTION) { state = BUTTON_NONE; if(show_info) @@ -173,12 +181,14 @@ void Button::event(SDL_Event &event) } else if(event.type == SDL_MOUSEMOTION) { - + timer_start(&popup_timer, 1500); + if(show_info) { show_info = false; } } + } int Button::get_state() @@ -214,7 +224,7 @@ Button* ButtonPanel::event(SDL_Event& event) for(std::vector::iterator it = item.begin(); it != item.end(); ++it) { (*it)->event(event); - if((*it)->state != -1) + if((*it)->state != BUTTON_NONE) return (*it); } return NULL; @@ -236,6 +246,7 @@ ButtonPanel::~ButtonPanel() void ButtonPanel::draw() { + if(hidden == false) { fillrect(rect.x,rect.y,rect.w,rect.h,100,100,100,200); diff --git a/src/button.h b/src/button.h index d80e823d4..53dc8281c 100644 --- a/src/button.h +++ b/src/button.h @@ -42,6 +42,7 @@ class Button } private: + static timer_type popup_timer; texture_type icon; texture_type* bkgd; std::string info; diff --git a/src/collision.cpp b/src/collision.cpp index 5820db19f..c87590376 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -244,6 +244,8 @@ void collision_handler() } } + if(tux.dying != DYING_NOT) return; + // CO_BADGUY & CO_PLAYER check for(unsigned int i = 0; i < bad_guys.size(); ++i) { @@ -257,7 +259,7 @@ void collision_handler() if (tux.previous_base.y < tux.base.y && tux.previous_base.y + tux.previous_base.height < bad_guys[i].base.y + bad_guys[i].base.height/2) { - bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_SQUICH); + bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_SQUISH); } else { diff --git a/src/collision.h b/src/collision.h index 410e2e87e..3f048d342 100644 --- a/src/collision.h +++ b/src/collision.h @@ -25,7 +25,7 @@ enum enum CollisionType { COLLISION_NORMAL, COLLISION_BUMP, - COLLISION_SQUICH + COLLISION_SQUISH }; bool rectcollision(base_type* one, base_type* two); diff --git a/src/gameloop.cpp b/src/gameloop.cpp index 3dac681fe..6718c1348 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -469,9 +469,7 @@ void game_draw(void) int y,x; /* Draw screen: */ - if (tux.dying && (global_frame_counter % 4) == 0) - clearscreen(255, 255, 255); - else if(timer_check(&super_bkgd_timer)) + if(timer_check(&super_bkgd_timer)) texture_draw(&img_super_bkgd, 0, 0); else { @@ -611,6 +609,7 @@ int gameloop(const char * subset, int levelnb, int mode) } level_load_gfx(¤t_level); + loadshared(); activate_bad_guys(¤t_level); activate_particle_systems(); level_load_song(¤t_level); @@ -620,8 +619,6 @@ int gameloop(const char * subset, int levelnb, int mode) if(st_gl_mode != ST_GL_TEST) load_hs(); - loadshared(); - if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE) levelintro(); @@ -640,6 +637,7 @@ int gameloop(const char * subset, int levelnb, int mode) game_pause = 0; timer_init(&fps_timer,true); timer_init(&frame_timer,true); + last_update_time = st_get_ticks(); fps_cnt = 0; /* Clear screen: */ @@ -1177,65 +1175,6 @@ void drawshape(float x, float y, unsigned int c, Uint8 alpha) } } } - - /* - if (c == 'X' || c == 'x') - texture_draw(&img_brick[0], x, y); - else if (c == 'Y' || c == 'y') - texture_draw(&img_brick[1], x, y); - else if (c == 'A' || c =='B' || c == '!') - texture_draw(&img_box_full, x, y); - else if (c == 'a') - texture_draw(&img_box_empty, x, y); - else if (c >= 'C' && c <= 'F') - texture_draw(&img_cloud[0][c - 'C'], x, y); - else if (c >= 'c' && c <= 'f') - texture_draw(&img_cloud[1][c - 'c'], x, y); - else if (c >= 'G' && c <= 'J') - texture_draw(&img_bkgd_tile[0][c - 'G'], x, y); - else if (c >= 'g' && c <= 'j') - texture_draw(&img_bkgd_tile[1][c - 'g'], x, y); - else if (c == '#') - texture_draw(&img_solid[0], x, y); - else if (c == '[') - texture_draw(&img_solid[1], x, y); - else if (c == '=') - texture_draw(&img_solid[2], x, y); - else if (c == ']') - texture_draw(&img_solid[3], x, y); - else if (c == '$') - { - z = (global_frame_counter / 2) % 6; - - if (z < 4) - texture_draw(&img_distro[z], x, y); - else if (z == 4) - texture_draw(&img_distro[2], x, y); - else if (z == 5) - texture_draw(&img_distro[1], x, y); - } - else if (c == '^') - { - z = (global_frame_counter / 3) % 3; - - texture_draw(&img_waves[z], x, y); - } - else if (c == '*') - texture_draw(&img_poletop, x, y); - else if (c == '|') - { - texture_draw(&img_pole, x, y); - - } - else if (c == '\\') - { - z = (global_frame_counter / 3) % 2; - - texture_draw(&img_flag[z], x + 16, y); - } - else if (c == '&') - texture_draw(&img_water, x, y);*/ - } @@ -1657,8 +1596,6 @@ void loadgame(int slot) timer_fread(&tux.frame_timer,fi); timer_fread(&time_left,fi); fread(&ui,sizeof(int),1,fi); - tux.hphysic.start_time += st_get_ticks() - ui; - tux.vphysic.start_time += st_get_ticks() - ui; fclose(fi); } diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp index b0598be1c..25cf9be2d 100644 --- a/src/leveleditor.cpp +++ b/src/leveleditor.cpp @@ -861,20 +861,6 @@ void le_checkevents() } else if(event.button.button == SDL_BUTTON_RIGHT) { - switch(active_tm) - { - case TM_BG: - active_tm = TM_IA; - break; - case TM_IA: - active_tm = TM_FG; - break; - case TM_FG: - active_tm = TM_BG; - break; - default: - break; - } le_mouse_pressed[RIGHT] = true; } break; @@ -1066,7 +1052,7 @@ void le_checkevents() } else if(le_move_left_bt->get_state() == BUTTON_HOVER) { - pos_x -= 96; + pos_x -= 64; } if(le_move_right_bt->get_state() == BUTTON_PRESSED) @@ -1075,7 +1061,7 @@ void le_checkevents() } else if(le_move_right_bt->get_state() == BUTTON_HOVER) { - pos_x += 96; + pos_x += 64; } } @@ -1247,7 +1233,7 @@ void le_showhelp() text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2); for(i = 0; i < sizeof(text)/sizeof(char *); i++) - text_draw(&white_small_text, text[i], 5, 80+(i*12), 1); + text_draw(&white_text, text[i], 5, 80+(i*18), 1); text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1); @@ -1257,16 +1243,7 @@ void le_showhelp() while(done == 0) { - while(SDL_PollEvent(&event)) - switch(event.type) - { - case SDL_MOUSEBUTTONDOWN: // mouse pressed - case SDL_KEYDOWN: // key pressed - done = 1; - break; - default: - break; - } + done = wait_for_event(event); SDL_Delay(50); } } diff --git a/src/physic.cpp b/src/physic.cpp index 3b2813a48..f31566158 100644 --- a/src/physic.cpp +++ b/src/physic.cpp @@ -9,75 +9,86 @@ // Copyright: See COPYING file that comes with this distribution // // - #include + +#include "scene.h" #include "defines.h" #include "physic.h" +#include "timer.h" float gravity; -void physic_init(physic_type* pphysic) +Physic::Physic() + : ax(0), ay(0), vx(0), vy(0), gravity_enabled(true) { - pphysic->state = -1; - pphysic->start_time = 0; - pphysic->start_vy = 0; } -int physic_get_state(physic_type* pphysic) +Physic::~Physic() { - return pphysic->state; } -void physic_set_state(physic_type* pphysic, int nstate) +void +Physic::reset() { - pphysic->state = nstate; - pphysic->start_time = st_get_ticks(); + ax = ay = vx = vy = 0; + gravity_enabled = true; } -void physic_set_start_vy(physic_type* pphysic, float start_vy) +void +Physic::set_velocity(float nvx, float nvy) { - pphysic->start_vy = start_vy; + vx = nvx; + vy = -nvy; } -void physic_set_start_vx(physic_type* pphysic, float start_vx) +float +Physic::get_velocity_x() { - pphysic->start_vx = start_vx; + return vx; } -void physic_set_acceleration(physic_type* pphysic, float acceleration) +float +Physic::get_velocity_y() { - pphysic->acceleration = acceleration; + return -vy; } - -int physic_is_set(physic_type* pphysic) +void +Physic::set_acceleration(float nax, float nay) { - return (pphysic->state != -1); + ax = nax; + ay = -nay; } -float physic_get_velocity(physic_type* pphysic) +float +Physic::get_acceleration_x() { - if(pphysic->state == PH_VT) - return - (pphysic->start_vy - gravity* ((float)(st_get_ticks() - pphysic->start_time))/1000.); - else if(pphysic->state == PH_HA) - return - (pphysic->start_vx - pphysic->acceleration * ((float)(st_get_ticks() - pphysic->start_time))/1000.); - else - return 0; + return ax; } -float physic_get_max_distance(physic_type* pphysic) +float +Physic::get_acceleration_y() { - return (pphysic->start_vy * pphysic->start_vy / 2.*gravity); + return -ay; } -unsigned int physic_get_max_time(physic_type* pphysic) +void +Physic::enable_gravity(bool enable_gravity) { - return (unsigned int)((pphysic->start_vy / gravity) * 1000); + gravity_enabled = enable_gravity; } -unsigned int physic_get_time_gone(physic_type* pphysic) +void +Physic::apply(float &x, float &y) { - return st_get_ticks() - pphysic->start_time; + float grav; + if(gravity_enabled) + grav = gravity / 100.0; + else + grav = 0; + + x += vx * frame_ratio + ax * frame_ratio * frame_ratio; + y += vy * frame_ratio + (ay + grav) * frame_ratio * frame_ratio; + vx += ax * frame_ratio; + vy += (ay + grav) * frame_ratio; } - - diff --git a/src/physic.h b/src/physic.h index f980bcb8c..860802161 100644 --- a/src/physic.h +++ b/src/physic.h @@ -13,37 +13,48 @@ #ifndef SUPERTUX_PHYSIC_H #define SUPERTUX_PHYSIC_H -#include "timer.h" - -enum { - PH_VT, /* Vertical throw.*/ - PH_HA /* Horizontal acceleration. */ -}; - -/* Physic type: */ - -struct physic_type - { - int state; - float start_vy; - float start_vx; - float acceleration; - unsigned int start_time; +/** This is a very simplistic physics engine handling accelerated and constant + * movement along with gravity. + */ +class Physic +{ +public: + Physic(); + ~Physic(); + + /** resets all velocities and accelerations to 0 */ + void reset(); + + /** sets velocity to a fixed value */ + void set_velocity(float vx, float vy); + + float get_velocity_x(); + float get_velocity_y(); + + /** sets acceleration applied to the object. (Note that gravity is + * eventually added to the vertical acceleration) + */ + void set_acceleration(float ax, float ay); + + float get_acceleration_x(); + float get_acceleration_y(); + + /** enables or disables handling of gravity */ + void enable_gravity(bool gravity_enabled); + + /** applies the physical simulation to given x and y coordinates */ + void apply(float &x, float &y); + +private: + /// horizontal and vertical acceleration + float ax, ay; + /// horizontal and vertical velocity + float vx, vy; + /// should we respect gravity in out calculations? + bool gravity_enabled; }; /* global variables. */ extern float gravity; -void physic_init(physic_type* pphysic); -int physic_get_state(physic_type* pphysic); -void physic_set_state(physic_type* pphysic, int nstate); -void physic_set_start_vy(physic_type* pphysic, float start_vy); -void physic_set_start_vx(physic_type* pphysic, float start_vx); -void physic_set_acceleration(physic_type* pphysic, float acceleration); -int physic_is_set(physic_type* pphysic); -float physic_get_velocity(physic_type* pphysic); -float physic_get_max_distance(physic_type* pphysic); -unsigned int physic_get_max_time(physic_type* pphysic); -unsigned int physic_get_time_gone(physic_type* pphysic); - #endif /*SUPERTUX_PHYSIC_H*/ diff --git a/src/player.cpp b/src/player.cpp index 9b40c0174..f23dc6be8 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -9,6 +9,7 @@ // Copyright: See COPYING file that comes with this distribution // // +#include #include "gameloop.h" #include "globals.h" @@ -66,7 +67,6 @@ Player::init() // FIXME: Make the start position configurable via the levelfile base.x = 100; base.y = 240; - base.xm = 0; base.ym = 0; old_base = base; @@ -94,8 +94,7 @@ Player::init() timer_init(&skidding_timer,true); timer_init(&safe_timer,true); timer_init(&frame_timer,true); - physic_init(&hphysic); - physic_init(&vphysic); + physic.reset(); } int @@ -138,6 +137,9 @@ Player::level_begin() base.xm = 0; base.ym = 0; old_base = base; + previous_base = base; + + dying = DYING_NOT; player_input_init(&input); @@ -145,8 +147,7 @@ Player::level_begin() timer_init(&skidding_timer,true); timer_init(&safe_timer,true); timer_init(&frame_timer,true); - physic_init(&hphysic); - physic_init(&vphysic); + physic.reset(); } void @@ -160,12 +161,9 @@ Player::action() handle_input(); /* Move tux: */ - previous_base = base; - base.x += base.xm * frame_ratio; - base.y += base.ym * frame_ratio; - + physic.apply(base.x, base.y); if (!dying) { @@ -178,36 +176,25 @@ Player::action() if( !on_ground()) { + physic.enable_gravity(true); if(under_solid()) { - physic_set_state(&vphysic,PH_VT); - physic_set_start_vy(&vphysic,0); + // fall down + physic.set_velocity(physic.get_velocity_x(), 0); jumped_in_solid = true; } - else - { - if(!physic_is_set(&vphysic)) - { - physic_set_state(&vphysic,PH_VT); - physic_set_start_vy(&vphysic,0); - } - } - base.ym = physic_get_velocity(&vphysic); } else { /* Land: */ - - if (base.ym > 0) + if (physic.get_velocity_y() < 0) { base.y = (int)(((int)base.y / 32) * 32); - base.ym = 0; + physic.set_velocity(physic.get_velocity_x(), 0); } - physic_init(&vphysic); - + physic.enable_gravity(false); /* Reset score multiplier (for multi-hits): */ - score_multiplier = 1; } @@ -253,8 +240,6 @@ Player::action() } } - else - base.ym = physic_get_velocity(&vphysic); timer_check(&safe_timer); @@ -292,7 +277,7 @@ Player::action() /* Handle skidding: */ - timer_check(&skidding_timer); + // timer_check(&skidding_timer); // disabled /* End of level? */ @@ -322,80 +307,105 @@ Player::under_solid() void Player::handle_horizontal_input(int newdir) { - if ((newdir ? (base.xm < -SKID_XM) : (base.xm > SKID_XM)) && !timer_started(&skidding_timer) && - dir == !newdir && on_ground()) + if(duck) + return; + + float vx = physic.get_velocity_x(); + float vy = physic.get_velocity_y(); + dir = newdir; + + // skid if we're too fast + if(dir != newdir && on_ground() && fabs(physic.get_velocity_x()) > SKID_XM + && !timer_started(&skidding_timer)) { timer_start(&skidding_timer, SKID_TIME); - play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER); - + return; } - dir = newdir; - - if ((newdir ? (base.xm < 0) : (base.xm > 0)) && !isice(base.x, base.y + base.height) && + if ((newdir ? (vx < 0) : (vx > 0)) && !isice(base.x, base.y + base.height) && !timer_started(&skidding_timer)) { - base.xm = 0; + //vx = 0; } - if (!duck) + /* Facing the direction we're jumping? Go full-speed: */ + if (input.fire == UP) { - if (dir == newdir) + if(vx >= MAX_WALK_XM) { + vx = MAX_WALK_XM; + physic.set_acceleration(0, 0); // enough speedup + } else if(vx <= -MAX_WALK_XM) { + vx = -MAX_WALK_XM; + physic.set_acceleration(0, 0); + } + physic.set_acceleration(newdir ? 0.02 : -0.02, 0); + if(fabs(vx) < 1) // set some basic run speed + vx = newdir ? 1 : -1; +#if 0 + vx += ( newdir ? WALK_SPEED : -WALK_SPEED) * frame_ratio; + + if(newdir) { - /* Facing the direction we're jumping? Go full-speed: */ - - if (input.fire == UP) - { - base.xm = base.xm + ( newdir ? WALK_SPEED : -WALK_SPEED) * frame_ratio; - - if(newdir) - { - if (base.xm > MAX_WALK_XM) - base.xm = MAX_WALK_XM; - } - else - { - if (base.xm < -MAX_WALK_XM) - base.xm = -MAX_WALK_XM; - } - } - else if ( input.fire == DOWN) - { - base.xm = base.xm + ( newdir ? RUN_SPEED : -RUN_SPEED) * frame_ratio; - - if(newdir) - { - if (base.xm > MAX_RUN_XM) - base.xm = MAX_RUN_XM; - } - else - { - if (base.xm < -MAX_RUN_XM) - base.xm = -MAX_RUN_XM; - } - } - else - { - /* Not facing the direction we're jumping? - Go half-speed: */ - - base.xm = base.xm + ( newdir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio; - - if(newdir) - { - if (base.xm > MAX_WALK_XM / 2) - base.xm = MAX_WALK_XM / 2; - } - else - { - if (base.xm < -MAX_WALK_XM / 2) - base.xm = -MAX_WALK_XM / 2; - } - } + if (vx > MAX_WALK_XM) + vx = MAX_WALK_XM; + } + else + { + if (vx < -MAX_WALK_XM) + vx = -MAX_WALK_XM; + } +#endif + } + else if ( input.fire == DOWN) + { + if(vx >= MAX_RUN_XM) { + vx = MAX_RUN_XM; + physic.set_acceleration(0, 0); // enough speedup + } else if(vx <= -MAX_RUN_XM) { + vx = -MAX_RUN_XM; + physic.set_acceleration(0, 0); + } + physic.set_acceleration(newdir ? 0.03 : -0.03, 0); + if(fabs(vx) < 1) // set some basic run speed + vx = newdir ? 1 : -1; + +#if 0 + vx = vx + ( newdir ? RUN_SPEED : -RUN_SPEED) * frame_ratio; + + if(newdir) + { + if (vx > MAX_RUN_XM) + vx = MAX_RUN_XM; + } + else + { + if (vx < -MAX_RUN_XM) + vx = -MAX_RUN_XM; } +#endif + } + else + { +#if 0 + /* Not facing the direction we're jumping? + Go half-speed: */ + vx = vx + ( newdir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio; + if(newdir) + { + if (vx > MAX_WALK_XM / 2) + vx = MAX_WALK_XM / 2; + } + else + { + if (vx < -MAX_WALK_XM / 2) + vx = -MAX_WALK_XM / 2; + } +#endif } + + physic.set_velocity(vx, vy); } void @@ -405,45 +415,22 @@ Player::handle_vertical_input() { if (on_ground()) { - if(!physic_is_set(&vphysic)) - { - physic_set_state(&vphysic,PH_VT); - physic_set_start_vy(&vphysic,5.5); - --base.y; - jumping = true; - if (size == SMALL) - play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER); - else - play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER); - } + // jump + physic.set_velocity(physic.get_velocity_x(), 5.5); + --base.y; + jumping = true; + if (size == SMALL) + play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER); + else + play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER); } } else if(input.up == UP && jumping) { - if (on_ground()) - { - physic_init(&vphysic); - jumping = false; - } - else - { - jumping = false; - if(physic_is_set(&vphysic)) - { - if(physic_get_velocity(&vphysic) < 0.) - { - physic_set_state(&vphysic,PH_VT); - physic_set_start_vy(&vphysic,0); - } - } - else - { - if(!physic_is_set(&vphysic)) - { - physic_set_state(&vphysic,PH_VT); - } - } - } + jumping = false; + if(physic.get_velocity_y() > 0) { + physic.set_velocity(physic.get_velocity_x(), 0); + } } } @@ -463,18 +450,15 @@ Player::handle_input() } else { - if(base.xm > 0) - { - base.xm = (int)(base.xm - frame_ratio); - if(base.xm < 0) - base.xm = 0; - } - else if(base.xm < 0) - { - base.xm = (int)(base.xm + frame_ratio); - if(base.xm > 0) - base.xm = 0; - } + float vx = physic.get_velocity_x(); + if(fabs(vx) < 0.01) { + physic.set_velocity(0, physic.get_velocity_y()); + physic.set_acceleration(0, 0); + } else if(vx < 0) { + physic.set_acceleration(0.1, 0); + } else { + physic.set_acceleration(-0.1, 0); + } } } @@ -489,7 +473,7 @@ Player::handle_input() if (input.fire == DOWN && input.old_fire == UP && got_coffee) { - add_bullet(base.x, base.y, base.xm, dir); + add_bullet(base.x, base.y, physic.get_velocity_x(), dir); } @@ -659,7 +643,7 @@ Player::draw() { if (!timer_started(&skidding_timer)) { - if (!jumping || base.ym > 0) + if (!jumping || physic.get_velocity_y() > 0) { if (dir == RIGHT) { @@ -720,7 +704,7 @@ Player::draw() { if (!timer_started(&skidding_timer)) { - if (!jumping || base.ym > 0) + if (!jumping || physic.get_velocity_y() > 0) { if (dir == RIGHT) { @@ -775,6 +759,7 @@ Player::draw() } } } + if(dying) text_drawf(&gold_text,"Penguins can fly !:",0,0,A_HMIDDLE,A_VMIDDLE,1); } @@ -794,60 +779,34 @@ Player::collision(void* p_c_object, int c_object) !timer_started(&safe_timer) && pbad_c->mode != HELD) { - if (pbad_c->mode == FLAT && input.fire != DOWN) - { - /* Kick: */ - - pbad_c->mode = KICK; - play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER); - - if (base.x < pbad_c->base.x + (pbad_c->base.width/2)) - { - pbad_c->dir = RIGHT; - pbad_c->base.x = pbad_c->base.x + 16; - } - else - { - pbad_c->dir = LEFT; - pbad_c->base.x = pbad_c->base.x - 32; - } - - timer_start(&pbad_c->timer,5000); - } - else if (pbad_c->mode == FLAT && input.fire == DOWN) + if (pbad_c->mode == FLAT && input.fire == DOWN) { pbad_c->mode = HELD; pbad_c->base.y-=8; } else if (pbad_c->mode == KICK) { - if (base.y < pbad_c->base.y - 16 && - timer_started(&pbad_c->timer)) + if (base.y < pbad_c->base.y - 16) { /* Step on (stop being kicked) */ pbad_c->mode = FLAT; play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER); - timer_start(&pbad_c->timer, 10000); } else { /* Hurt if you get hit by kicked laptop: */ - - if (timer_started(&pbad_c->timer)) + if (!timer_started(&invincible_timer)) { - if (!timer_started(&invincible_timer)) - { - kill(SHRINK); - } - else - { - pbad_c->dying = DYING_FALLING; - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - add_score(pbad_c->base.x - scroll_x, - pbad_c->base.y, - 25 * score_multiplier); - } + kill(SHRINK); + } + else + { + pbad_c->dying = DYING_FALLING; + play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); + add_score(pbad_c->base.x - scroll_x, + pbad_c->base.y, + 25 * score_multiplier); } } } @@ -859,11 +818,7 @@ Player::collision(void* p_c_object, int c_object) } else { - pbad_c->dying = DYING_FALLING; - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - add_score(pbad_c->base.x - scroll_x, - pbad_c->base.y, - 25 * score_multiplier); + pbad_c->kill_me(); } } score_multiplier++; @@ -880,10 +835,9 @@ Player::collision(void* p_c_object, int c_object) void Player::kill(int mode) { - play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER); - base.xm = 0; + physic.set_velocity(0, physic.get_velocity_y()); if (mode == SHRINK && size == BIG) { @@ -899,8 +853,10 @@ Player::kill(int mode) { if(size == BIG) duck = true; - physic_set_state(&vphysic,PH_VT); - physic_set_start_vy(&vphysic,7); + + physic.enable_gravity(true); + physic.set_acceleration(0, 0); + physic.set_velocity(0, 7); dying = DYING_SQUISHED; } } @@ -908,8 +864,6 @@ Player::kill(int mode) void Player::is_dying() { - base.ym = base.ym + gravity; - /* He died :^( */ --lives; diff --git a/src/player.h b/src/player.h index f22257907..7f481b9d7 100644 --- a/src/player.h +++ b/src/player.h @@ -107,8 +107,7 @@ class Player timer_type skidding_timer; timer_type safe_timer; timer_type frame_timer; - physic_type vphysic; - physic_type hphysic; + Physic physic; public: void init(); diff --git a/src/scene.cpp b/src/scene.cpp index 3fab8693b..c39fcfa58 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -121,9 +121,10 @@ void add_bouncy_brick(float x, float y) void add_bad_guy(float x, float y, BadGuyKind kind) { - BadGuy new_bad_guy; + bad_guys.push_back(BadGuy()); + BadGuy& new_bad_guy = bad_guys.back(); + new_bad_guy.init(x,y,kind); - bad_guys.push_back(new_bad_guy); } void add_upgrade(float x, float y, int dir, int kind) diff --git a/src/tile.cpp b/src/tile.cpp index efe97776a..3ced8ef9b 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -46,6 +46,7 @@ void TileManager::load_tileset(std::string filename) tile->solid = false; tile->brick = false; tile->ice = false; + tile->water = false; tile->fullbox = false; tile->distro = false; tile->data = 0; @@ -57,6 +58,7 @@ void TileManager::load_tileset(std::string filename) reader.read_bool("solid", &tile->solid); reader.read_bool("brick", &tile->brick); reader.read_bool("ice", &tile->ice); + reader.read_bool("water", &tile->water); reader.read_bool("fullbox", &tile->fullbox); reader.read_bool("distro", &tile->distro); reader.read_int("data", &tile->data); diff --git a/src/tile.h b/src/tile.h index 721b010b9..2175b2b1f 100644 --- a/src/tile.h +++ b/src/tile.h @@ -40,6 +40,9 @@ struct Tile /** FIXME: ? */ bool ice; + /** water */ + bool water; + /** Bonusbox, content is stored in \a data */ bool fullbox; diff --git a/src/timer.cpp b/src/timer.cpp index 858f3fedc..52b1b0861 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -19,7 +19,7 @@ unsigned int st_pause_ticks, st_pause_count; unsigned int st_get_ticks(void) { if(st_pause_count != 0) - return SDL_GetTicks() - st_pause_ticks - SDL_GetTicks() + st_pause_count; + return /*SDL_GetTicks()*/ - st_pause_ticks /*- SDL_GetTicks()*/ + st_pause_count; else return SDL_GetTicks() - st_pause_ticks; } @@ -37,6 +37,9 @@ void st_pause_ticks_start(void) void st_pause_ticks_stop(void) { +if(st_pause_count == 0) +return; + st_pause_ticks += SDL_GetTicks() - st_pause_count; st_pause_count = 0; } diff --git a/src/title.cpp b/src/title.cpp index a6f24fd67..5b5523501 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -84,13 +84,12 @@ int title(void) Player titletux; titletux.init(); st_pause_ticks_init(); - st_pause_ticks_stop(); level_load(¤t_level, (datadir + "/levels/misc/menu.stl").c_str()); loadshared(); activate_particle_systems(); /* Lower the gravity that tux doesn't jump to hectically through the demo */ - gravity = 5; + //gravity = 5; /* Reset menu variables */ menu_reset(); @@ -301,6 +300,10 @@ int title(void) } } } + // reset tux + scroll_x = 0; + titletux.level_begin(); + update_time = st_get_ticks(); break; case 3: update_load_save_game_menu(load_game_menu, true);