X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fworld.cpp;h=0c28cb0011097e6180969176b7cf025c6dfd8467;hb=157cef71aeb9ae25b7bb90f37dda11bc09329d11;hp=257b71bc74625a5a7cb0077f134eae1b54b3d676;hpb=7e3d22eda4aef5950ab194d36e5500e79c42402e;p=supertux.git diff --git a/src/world.cpp b/src/world.cpp index 257b71bc7..0c28cb001 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -33,7 +33,7 @@ #include "tile.h" #include "resources.h" #include "gameobjs.h" -#include "viewport.h" +#include "camera.h" #include "display_manager.h" #include "background.h" #include "tilemap.h" @@ -42,109 +42,69 @@ Surface* img_distro[4]; World* World::current_ = 0; -World::World(const std::string& filename) +World::World(const std::string& filename, int level_nr) { // FIXME: Move this to action and draw and everywhere else where the // world calls child functions current_ = this; - level = new Level(filename); - tux = new Player(displaymanager); - gameobjects.push_back(tux); - - set_defaults(); + add_object(tux); + + level = new Level(); + camera = new Camera(tux, level); + add_object(camera); - get_level()->load_gfx(); - activate_bad_guys(); - // add background - activate_particle_systems(); - Background* bg = new Background(displaymanager); - if(level->img_bkgd) { - bg->set_image(level->img_bkgd, level->bkgd_speed); + if(level_nr >= 0) { + level->load(filename, level_nr, this); } else { - bg->set_gradient(level->bkgd_top, level->bkgd_bottom); + level->load(filename, this); } - gameobjects.push_back(bg); - - // add tilemap - gameobjects.push_back(new TileMap(displaymanager, get_level())); - activate_objects(); - get_level()->load_song(); - - apply_bonuses(); - - scrolling_timer.init(true); -} - -World::World(const std::string& subset, int level_nr) -{ - // FIXME: Move this to action and draw and everywhere else where the - // world calls child functions - current_ = this; - - level = new Level(subset, level_nr); - tux->init(); - + tux->move(level->start_pos); + set_defaults(); - get_level()->load_gfx(); - activate_bad_guys(); - activate_objects(); + level->load_gfx(); + // add background activate_particle_systems(); - Background* bg = new Background(displaymanager); + background = new Background(displaymanager); if(level->img_bkgd) { - bg->set_image(level->img_bkgd, level->bkgd_speed); + background->set_image(level->img_bkgd, level->bkgd_speed); } else { - bg->set_gradient(level->bkgd_top, level->bkgd_bottom); + background->set_gradient(level->bkgd_top, level->bkgd_bottom); } - gameobjects.push_back(bg); + add_object(background); + // add tilemap - gameobjects.push_back(new TileMap(displaymanager, get_level())); - get_level()->load_song(); + add_object(new TileMap(displaymanager, level)); + level->load_song(); apply_bonuses(); - - scrolling_timer.init(true); } void World::apply_bonuses() { -#if 0 // Apply bonuses from former levels switch (player_status.bonus) { case PlayerStatus::NO_BONUS: break; - + case PlayerStatus::FLOWER_BONUS: - tux->got_power = tux.FIRE_POWER; // FIXME: add ice power to here + tux->got_power = Player::FIRE_POWER; // FIXME: add ice power to here // fall through - + case PlayerStatus::GROWUP_BONUS: - // FIXME: Move this to Player class - tux->size = BIG; - tux->base.height = 64; - tux->base.y -= 32; + tux->grow(); break; } -#endif } World::~World() { - for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) - delete *i; - - for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i) - delete *i; - - for (std::vector<_GameObject*>::iterator i = gameobjects.begin(); + for (std::vector::iterator i = gameobjects.begin(); i != gameobjects.end(); ++i) { - Drawable* drawable = dynamic_cast (*i); - if(drawable) - displaymanager.remove_drawable(drawable); delete *i; } @@ -154,9 +114,6 @@ World::~World() void World::set_defaults() { - // Set defaults: - scroll_x = 0; - player_status.score_multiplier = 1; counting_distros = false; @@ -167,25 +124,50 @@ World::set_defaults() } void -World::activate_bad_guys() +World::add_object(GameObject* object) { - for (std::vector::iterator i = level->badguy_data.begin(); - i != level->badguy_data.end(); - ++i) - { - add_bad_guy(i->x, i->y, i->kind, i->stay_on_platform); - } + // XXX hack for now until new collision code is ready + BadGuy* badguy = dynamic_cast (object); + if(badguy) + bad_guys.push_back(badguy); + Bullet* bullet = dynamic_cast (object); + if(bullet) + bullets.push_back(bullet); + Upgrade* upgrade = dynamic_cast (object); + if(upgrade) + upgrades.push_back(upgrade); + Trampoline* trampoline = dynamic_cast (object); + if(trampoline) + trampolines.push_back(trampoline); + FlyingPlatform* flying_platform = dynamic_cast (object); + if(flying_platform) + flying_platforms.push_back(flying_platform); + + gameobjects.push_back(object); } void -World::activate_objects() +World::parse_objects(lisp_object_t* cur) { - for (std::vector< ObjectData >::iterator i = level->trampoline_data.begin(); - i != level->trampoline_data.end(); - ++i) - { - add_object >(*i); - } + while(!lisp_nil_p(cur)) { + lisp_object_t* data = lisp_car(cur); + std::string object_type = lisp_symbol(lisp_car(data)); + + LispReader reader(lisp_cdr(data)); + + if(object_type == "trampoline") { + add_object(new Trampoline(displaymanager, reader)); + } + else if(object_type == "flying-platform") { + add_object(new FlyingPlatform(displaymanager, reader)); + } + else { + BadGuyKind kind = badguykind_from_string(object_type); + add_object(new BadGuy(displaymanager, kind, reader)); + } + + cur = lisp_cdr(cur); + } } void @@ -193,11 +175,11 @@ World::activate_particle_systems() { if (level->particle_system == "clouds") { - gameobjects.push_back(new CloudParticleSystem(displaymanager)); + add_object(new CloudParticleSystem(displaymanager)); } else if (level->particle_system == "snow") { - gameobjects.push_back(new SnowParticleSystem(displaymanager)); + add_object(new SnowParticleSystem(displaymanager)); } else if (level->particle_system != "") { @@ -209,66 +191,61 @@ void World::draw() { /* Draw objects */ - displaymanager.get_viewport().set_translation(Vector(scroll_x, scroll_y)); - displaymanager.draw(); - - for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) - (*i)->draw(); - - for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i) - (*i)->draw(); - - for (unsigned int i = 0; i < bullets.size(); ++i) - bullets[i].draw(); - - for (unsigned int i = 0; i < upgrades.size(); ++i) - upgrades[i].draw(); + displaymanager.draw(*camera); } void -World::action(double frame_ratio) +World::action(float elapsed_time) { - tux->check_bounds(level->back_scrolling, (bool)level->hor_autoscroll_speed); - scrolling(frame_ratio); - - for (unsigned int i = 0; i < bullets.size(); ++i) - bullets[i].action(frame_ratio); - - for (unsigned int i = 0; i < upgrades.size(); i++) - upgrades[i].action(frame_ratio); - - for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) - (*i)->action(frame_ratio); - - for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i) - (*i)->action(frame_ratio); - + tux->check_bounds(*camera, + level->back_scrolling, (bool)level->hor_autoscroll_speed); + /* update objects (don't use iterators here, because the list might change * during the iteration) */ for(size_t i = 0; i < gameobjects.size(); ++i) - gameobjects[i]->action(frame_ratio); + if(gameobjects[i]->is_valid()) + gameobjects[i]->action(elapsed_time); /* Handle all possible collisions. */ collision_handler(); - - // Cleanup marked badguys - for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); - /* ++i handled at end of the loop */) { - if ((*i)->is_removable()) { - delete *i; - i = bad_guys.erase(i); - } else { - ++i; - } - } - - for(std::vector<_GameObject*>::iterator i = gameobjects.begin(); + + /** cleanup marked objects */ + for(std::vector::iterator i = gameobjects.begin(); i != gameobjects.end(); /* nothing */) { if((*i)->is_valid() == false) { Drawable* drawable = dynamic_cast (*i); if(drawable) displaymanager.remove_drawable(drawable); + BadGuy* badguy = dynamic_cast (*i); + if(badguy) { + bad_guys.erase(std::remove(bad_guys.begin(), bad_guys.end(), badguy), + bad_guys.end()); + } + Bullet* bullet = dynamic_cast (*i); + if(bullet) { + bullets.erase( + std::remove(bullets.begin(), bullets.end(), bullet), + bullets.end()); + } + Upgrade* upgrade = dynamic_cast (*i); + if(upgrade) { + upgrades.erase( + std::remove(upgrades.begin(), upgrades.end(), upgrade), + upgrades.end()); + } + Trampoline* trampoline = dynamic_cast (*i); + if(trampoline) { + trampolines.erase( + std::remove(trampolines.begin(), trampolines.end(), trampoline), + trampolines.end()); + } + FlyingPlatform* flying_platform= dynamic_cast (*i); + if(flying_platform) { + flying_platforms.erase( + std::remove(flying_platforms.begin(), flying_platforms.end(), flying_platform), + flying_platforms.end()); + } delete *i; i = gameobjects.erase(i); @@ -278,115 +255,6 @@ World::action(double frame_ratio) } } -/* the space that it takes for the screen to start scrolling, regarding */ -/* screen bounds (in pixels) */ -// should be higher than screen->w/2 (400) -#define X_SPACE (500-16) -// should be less than screen->h/2 (300) -#define Y_SPACE 250 - -// the time it takes to move the camera (in ms) -#define CHANGE_DIR_SCROLL_SPEED 2000 - -/* This functions takes cares of the scrolling */ -void World::scrolling(double frame_ratio) -{ - /* Y-axis scrolling */ - - float tux_pos_y = tux->base.y + (tux->base.height/2); - - if(level->height > VISIBLE_TILES_Y-1 && !tux->dying) - { - if (scroll_y < tux_pos_y - (screen->h - Y_SPACE)) - scroll_y = tux_pos_y - (screen->h - Y_SPACE); - else if (scroll_y > tux_pos_y - Y_SPACE) - scroll_y = tux_pos_y - Y_SPACE; - } - - // this code prevent the screen to scroll before the start or after the level's end - if(scroll_y > level->height * 32 - screen->h) - scroll_y = level->height * 32 - screen->h; - if(scroll_y < 0) - scroll_y = 0; - - /* X-axis scrolling */ - - /* Auto scrolling */ - if(level->hor_autoscroll_speed) - { - scroll_x += level->hor_autoscroll_speed * frame_ratio; - return; - } - - - /* Horizontal backscrolling */ - float tux_pos_x = tux->base.x + (tux->base.width/2); - - if(tux->old_dir != tux->dir && level->back_scrolling) - scrolling_timer.start(CHANGE_DIR_SCROLL_SPEED); - - bool right = false; - bool left = false; - if (tux->physic.get_velocity_x() > 0) - right = true; - else if (tux->physic.get_velocity_x() < 0) - left = true; - else - { - if (tux->dir == RIGHT) - right = true; - else - left = true; - } - - if(scrolling_timer.check()) - { - float final_scroll_x; - float constant1; - float constant2; - if (right) - final_scroll_x = tux_pos_x - (screen->w - X_SPACE); - else - final_scroll_x = tux_pos_x - X_SPACE; - - if((tux->physic.get_velocity_x() > 0 && tux->dir == RIGHT) - || (tux->physic.get_velocity_x() < 0 && tux->dir == LEFT)) - { - constant1 = 1.0; - constant2 = .4; - } - else - { - constant1 = 0.; - constant2 = 0.; - } - - float number = 2.5/(frame_ratio * CHANGE_DIR_SCROLL_SPEED/1000)*exp((CHANGE_DIR_SCROLL_SPEED-scrolling_timer.get_left())/1400.); - if(left) number *= -1.; - - scroll_x += number - + constant1 * tux->physic.get_velocity_x() * frame_ratio - + constant2 * tux->physic.get_acceleration_x() * frame_ratio * frame_ratio; - - if ((right && final_scroll_x - scroll_x < 0) || (left && final_scroll_x - scroll_x > 0)) - scroll_x = final_scroll_x; - - } - else - { - if (right && scroll_x < tux_pos_x - (screen->w - X_SPACE)) - scroll_x = tux_pos_x - (screen->w - X_SPACE); - else if (left && scroll_x > tux_pos_x - X_SPACE && level->back_scrolling) - scroll_x = tux_pos_x - X_SPACE; - } - - // this code prevent the screen to scroll before the start or after the level's end - if(scroll_x > level->width * 32 - screen->w) - scroll_x = level->width * 32 - screen->w; - if(scroll_x < 0) - scroll_x = 0; -} - void World::collision_handler() { @@ -398,14 +266,12 @@ World::collision_handler() if((*j)->dying != DYING_NOT) continue; - if(rectcollision(bullets[i].base, (*j)->base)) + if(rectcollision(bullets[i]->base, (*j)->base)) { // We have detected a collision and now call the // collision functions of the collided objects. - // collide with bad_guy first, since bullet_collision will - // delete the bullet - (*j)->collision(&bullets[i], CO_BULLET); - bullets[i].collision(CO_BADGUY); + (*j)->collision(bullets[i], CO_BULLET, COLLISION_NORMAL); + bullets[i]->collision(CO_BADGUY); break; // bullet is invalid now, so break } } @@ -464,11 +330,11 @@ World::collision_handler() // CO_UPGRADE & CO_PLAYER check for(unsigned int i = 0; i < upgrades.size(); ++i) { - if(rectcollision(upgrades[i].base, tux->base)) + if(rectcollision(upgrades[i]->base, tux->base)) { // We have detected a collision and now call the collision // functions of the collided objects. - upgrades[i].collision(tux, CO_PLAYER, COLLISION_NORMAL); + upgrades[i]->collision(tux, CO_PLAYER, COLLISION_NORMAL); } } @@ -490,6 +356,24 @@ World::collision_handler() } } } + + // CO_FLYING_PLATFORM & (CO_PLAYER or CO_BADGUY) + for (FlyingPlatforms::iterator i = flying_platforms.begin(); i != flying_platforms.end(); ++i) + { + if (rectcollision((*i)->base, tux->base)) + { + if (tux->previous_base.y < tux->base.y && + tux->previous_base.y + tux->previous_base.height + < (*i)->base.y + (*i)->base.height/2) + { + (*i)->collision(tux, CO_PLAYER, COLLISION_SQUISH); + tux->collision(*i, CO_FLYING_PLATFORM); + } +/* else if (tux->previous_base.y <= tux->base.y) + { + }*/ + } + } } void @@ -497,13 +381,13 @@ World::add_score(const Vector& pos, int s) { player_status.score += s; - gameobjects.push_back(new FloatingScore(displaymanager, pos, s)); + add_object(new FloatingScore(displaymanager, pos, s)); } void World::add_bouncy_distro(const Vector& pos) { - gameobjects.push_back(new BouncyDistro(displaymanager, pos)); + add_object(new BouncyDistro(displaymanager, pos)); } void @@ -520,65 +404,55 @@ void World::add_broken_brick_piece(const Vector& pos, const Vector& movement, Tile* tile) { - gameobjects.push_back(new BrokenBrick(displaymanager, tile, pos, movement)); + add_object(new BrokenBrick(displaymanager, tile, pos, movement)); } void World::add_bouncy_brick(const Vector& pos) { - gameobjects.push_back(new BouncyBrick(displaymanager, pos)); + add_object(new BouncyBrick(displaymanager, pos)); } BadGuy* -World::add_bad_guy(float x, float y, BadGuyKind kind, bool stay_on_platform) +World::add_bad_guy(float x, float y, BadGuyKind kind) { - BadGuy* badguy = new BadGuy(x,y,kind, stay_on_platform); - bad_guys.push_back(badguy); + BadGuy* badguy = new BadGuy(displaymanager, kind, x, y); + add_object(badguy); return badguy; } -template -T* -World::add_object(U data) -{ - T* tobject = new T(data); - - if (data.type == OBJ_TRAMPOLINE) - trampolines.push_back(tobject); - - return tobject; -} - void -World::add_upgrade(float x, float y, Direction dir, UpgradeKind kind) +World::add_upgrade(const Vector& pos, Direction dir, UpgradeKind kind) { - Upgrade new_upgrade; - new_upgrade.init(x,y,dir,kind); - upgrades.push_back(new_upgrade); + add_object(new Upgrade(displaymanager, pos, dir, kind)); } -void -World::add_bullet(float x, float y, float xm, Direction dir) +bool +World::add_bullet(const Vector& pos, float xm, Direction dir) { if(tux->got_power == Player::FIRE_POWER) { if(bullets.size() > MAX_FIRE_BULLETS-1) - return; + return false; } else if(tux->got_power == Player::ICE_POWER) { if(bullets.size() > MAX_ICE_BULLETS-1) - return; + return false; } - Bullet new_bullet; + Bullet* new_bullet = 0; if(tux->got_power == Player::FIRE_POWER) - new_bullet.init(x,y,xm,dir, FIRE_BULLET); + new_bullet = new Bullet(displaymanager, pos, xm, dir, FIRE_BULLET); else if(tux->got_power == Player::ICE_POWER) - new_bullet.init(x,y,xm,dir, ICE_BULLET); - bullets.push_back(new_bullet); + new_bullet = new Bullet(displaymanager, pos, xm, dir, ICE_BULLET); + else + st_abort("wrong bullet type.", ""); + add_object(new_bullet); play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER); + + return true; } void @@ -692,26 +566,26 @@ World::tryemptybox(float x, float y, Direction col_side) case 2: // Add a fire flower upgrade! if (tux->size == SMALL) /* Tux is small, add mints! */ - add_upgrade(posx, posy, col_side, UPGRADE_GROWUP); + add_upgrade(Vector(posx, posy), col_side, UPGRADE_GROWUP); else /* Tux is big, add a fireflower: */ - add_upgrade(posx, posy, col_side, UPGRADE_FIREFLOWER); + add_upgrade(Vector(posx, posy), col_side, UPGRADE_FIREFLOWER); play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER); break; case 5: // Add an ice flower upgrade! if (tux->size == SMALL) /* Tux is small, add mints! */ - add_upgrade(posx, posy, col_side, UPGRADE_GROWUP); + add_upgrade(Vector(posx, posy), col_side, UPGRADE_GROWUP); else /* Tux is big, add an iceflower: */ - add_upgrade(posx, posy, col_side, UPGRADE_ICEFLOWER); + add_upgrade(Vector(posx, posy), col_side, UPGRADE_ICEFLOWER); play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER); break; case 3: // Add a golden herring - add_upgrade(posx, posy, col_side, UPGRADE_HERRING); + add_upgrade(Vector(posx, posy), col_side, UPGRADE_HERRING); break; case 4: // Add a 1up extra - add_upgrade(posx, posy, col_side, UPGRADE_1UP); + add_upgrade(Vector(posx, posy), col_side, UPGRADE_1UP); break; default: break; @@ -759,11 +633,11 @@ World::trybumpbadguy(float x, float y) // Upgrades: for (unsigned int i = 0; i < upgrades.size(); i++) { - if (upgrades[i].base.height == 32 && - upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 && - upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16) + if (upgrades[i]->base.height == 32 && + upgrades[i]->base.x >= x - 32 && upgrades[i]->base.x <= x + 32 && + upgrades[i]->base.y >= y - 16 && upgrades[i]->base.y <= y + 16) { - upgrades[i].collision(tux, CO_PLAYER, COLLISION_BUMP); + upgrades[i]->collision(tux, CO_PLAYER, COLLISION_BUMP); } } }