X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fworldmap%2Fworldmap.cpp;h=36159059addeebe4fcde518a6a39fd13f122c3ff;hb=05d168f5e5bbd46e44b1b1ad857d2d8c59b230c1;hp=3bda837844ab1e23d176a0d1c0716fd36091d0d1;hpb=c996b997ab4a3f8fb8409b8a372eb989e71423a3;p=supertux.git diff --git a/src/worldmap/worldmap.cpp b/src/worldmap/worldmap.cpp index 3bda83784..36159059a 100644 --- a/src/worldmap/worldmap.cpp +++ b/src/worldmap/worldmap.cpp @@ -40,18 +40,21 @@ #include "object/decal.hpp" #include "object/tilemap.hpp" #include "physfs/ifile_streambuf.hpp" +#include "scripting/scripting.hpp" #include "scripting/squirrel_error.hpp" #include "scripting/squirrel_util.hpp" #include "sprite/sprite.hpp" #include "sprite/sprite_manager.hpp" #include "supertux/game_session.hpp" +#include "supertux/gameconfig.hpp" #include "supertux/globals.hpp" -#include "supertux/screen_manager.hpp" #include "supertux/menu/menu_storage.hpp" #include "supertux/menu/options_menu.hpp" #include "supertux/menu/worldmap_menu.hpp" #include "supertux/player_status.hpp" #include "supertux/resources.hpp" +#include "supertux/savegame.hpp" +#include "supertux/screen_manager.hpp" #include "supertux/sector.hpp" #include "supertux/shrinkfade.hpp" #include "supertux/spawn_point.hpp" @@ -77,9 +80,9 @@ namespace worldmap { WorldMap* WorldMap::current_ = NULL; -WorldMap::WorldMap(const std::string& filename, PlayerStatus* player_status, const std::string& force_spawnpoint) : - tux(0), - player_status(player_status), +WorldMap::WorldMap(const std::string& filename, Savegame& savegame, const std::string& force_spawnpoint_) : + tux(), + m_savegame(savegame), tileset(NULL), free_tileset(false), camera_offset(), @@ -101,14 +104,14 @@ WorldMap::WorldMap(const std::string& filename, PlayerStatus* player_status, con worldmap_table(), scripts(), ambient_light( 1.0f, 1.0f, 1.0f, 1.0f ), - force_spawnpoint(force_spawnpoint), + force_spawnpoint(force_spawnpoint_), in_level(false), pan_pos(), panning(false), last_position(), last_target_time() { - tux = new Tux(this); + tux = std::make_shared(this); add_object(tux); name = ""; @@ -132,7 +135,7 @@ WorldMap::WorldMap(const std::string& filename, PlayerStatus* player_status, con sq_addref(global_vm, &worldmap_table); sq_pop(global_vm, 1); - sound_manager->preload("sounds/warp.wav"); + SoundManager::current()->preload("sounds/warp.wav"); // load worldmap objects load(filename); @@ -147,9 +150,8 @@ WorldMap::~WorldMap() for(GameObjects::iterator i = game_objects.begin(); i != game_objects.end(); ++i) { - GameObject* object = *i; + GameObjectPtr& object = *i; try_unexpose(object); - object->unref(); } for(SpawnPoints::iterator i = spawn_points.begin(); @@ -171,22 +173,21 @@ WorldMap::~WorldMap() } void -WorldMap::add_object(GameObject* object) +WorldMap::add_object(GameObjectPtr object) { - TileMap* tilemap = dynamic_cast (object); + TileMap* tilemap = dynamic_cast(object.get()); if(tilemap != 0 && tilemap->is_solid()) { solid_tilemaps.push_back(tilemap); } - object->ref(); try_expose(object); game_objects.push_back(object); } void -WorldMap::try_expose(GameObject* object) +WorldMap::try_expose(const GameObjectPtr& object) { - ScriptInterface* object_ = dynamic_cast (object); + ScriptInterface* object_ = dynamic_cast(object.get()); if(object_ != NULL) { HSQUIRRELVM vm = scripting::global_vm; sq_pushobject(vm, worldmap_table); @@ -196,9 +197,9 @@ WorldMap::try_expose(GameObject* object) } void -WorldMap::try_unexpose(GameObject* object) +WorldMap::try_unexpose(const GameObjectPtr& object) { - ScriptInterface* object_ = dynamic_cast (object); + ScriptInterface* object_ = dynamic_cast(object.get()); if(object_ != NULL) { HSQUIRRELVM vm = scripting::global_vm; SQInteger oldtop = sq_gettop(vm); @@ -236,10 +237,10 @@ WorldMap::move_to_spawnpoint(const std::string& spawnpoint, bool pan) } void -WorldMap::change(const std::string& filename, const std::string& force_spawnpoint) +WorldMap::change(const std::string& filename, const std::string& force_spawnpoint_) { - g_screen_manager->pop_screen(); - g_screen_manager->push_screen(std::unique_ptr(new WorldMap(filename, player_status, force_spawnpoint))); + ScreenManager::current()->pop_screen(); + ScreenManager::current()->push_screen(std::unique_ptr(new WorldMap(filename, m_savegame, force_spawnpoint_))); } void @@ -252,41 +253,41 @@ WorldMap::load(const std::string& filename) lisp::Parser parser; const lisp::Lisp* root = parser.parse(map_filename); - const lisp::Lisp* level = root->get_lisp("supertux-level"); - if(level == NULL) + const lisp::Lisp* level_ = root->get_lisp("supertux-level"); + if(level_ == NULL) throw std::runtime_error("file isn't a supertux-level file."); - level->get("name", name); + level_->get("name", name); - const lisp::Lisp* sector = level->get_lisp("sector"); + const lisp::Lisp* sector = level_->get_lisp("sector"); if(!sector) throw std::runtime_error("No sector specified in worldmap file."); - const lisp::Lisp* tilesets_lisp = level->get_lisp("tilesets"); + const lisp::Lisp* tilesets_lisp = level_->get_lisp("tilesets"); if(tilesets_lisp != NULL) { - tileset = tile_manager->parse_tileset_definition(*tilesets_lisp); + tileset = TileManager::current()->parse_tileset_definition(*tilesets_lisp).release(); free_tileset = true; } std::string tileset_name; - if(level->get("tileset", tileset_name)) { + if(level_->get("tileset", tileset_name)) { if(tileset != NULL) { - log_warning << "multiple tilesets specified in level" << std::endl; + log_warning << "multiple tilesets specified in level_" << std::endl; } else { - tileset = tile_manager->get_tileset(tileset_name); + tileset = TileManager::current()->get_tileset(tileset_name); } } /* load default tileset */ if(tileset == NULL) { - tileset = tile_manager->get_tileset("images/worldmap.strf"); + tileset = TileManager::current()->get_tileset("images/worldmap.strf"); } current_tileset = tileset; lisp::ListIterator iter(sector); while(iter.next()) { if(iter.item() == "tilemap") { - add_object(new TileMap(*(iter.lisp()))); + add_object(std::make_shared(*(iter.lisp()))); } else if(iter.item() == "background") { - add_object(new Background(*(iter.lisp()))); + add_object(std::make_shared(*(iter.lisp()))); } else if(iter.item() == "music") { iter.value()->get(music); } else if(iter.item() == "init-script") { @@ -295,23 +296,23 @@ WorldMap::load(const std::string& filename) SpawnPoint* sp = new SpawnPoint(*iter.lisp()); spawn_points.push_back(sp); } else if(iter.item() == "level") { - LevelTile* level = new LevelTile(levels_path, *iter.lisp()); - levels.push_back(level); + auto level = std::make_shared(levels_path, *iter.lisp()); + levels.push_back(level.get()); add_object(level); } else if(iter.item() == "special-tile") { - SpecialTile* special_tile = new SpecialTile(*iter.lisp()); - special_tiles.push_back(special_tile); + auto special_tile = std::make_shared(*iter.lisp()); + special_tiles.push_back(special_tile.get()); add_object(special_tile); } else if(iter.item() == "sprite-change") { - SpriteChange* sprite_change = new SpriteChange(*iter.lisp()); - sprite_changes.push_back(sprite_change); + auto sprite_change = std::make_shared(*iter.lisp()); + sprite_changes.push_back(sprite_change.get()); add_object(sprite_change); } else if(iter.item() == "teleporter") { - Teleporter* teleporter = new Teleporter(*iter.lisp()); - teleporters.push_back(teleporter); + auto teleporter = std::make_shared(*iter.lisp()); + teleporters.push_back(teleporter.get()); add_object(teleporter); } else if(iter.item() == "decal") { - Decal* decal = new Decal(*iter.lisp()); + auto decal = std::make_shared(*iter.lisp()); add_object(decal); } else if(iter.item() == "ambient-light") { std::vector vColor; @@ -329,7 +330,7 @@ WorldMap::load(const std::string& filename) } current_tileset = NULL; - if(solid_tilemaps.size() == 0) + if(solid_tilemaps.empty()) throw std::runtime_error("No solid tilemap specified"); move_to_spawnpoint("main"); @@ -480,6 +481,10 @@ WorldMap::finished_level(Level* gamelevel) // TODO use Level* parameter here? LevelTile* level = at_level(); + if(level == NULL) { + return; + } + bool old_level_state = level->solved; level->solved = true; level->sprite->set_action("solved"); @@ -539,11 +544,11 @@ WorldMap::finished_level(Level* gamelevel) Vector WorldMap::get_camera_pos_for_tux() { - Vector camera_offset; + Vector camera_offset_; Vector tux_pos = tux->get_pos(); - camera_offset.x = tux_pos.x - SCREEN_WIDTH/2; - camera_offset.y = tux_pos.y - SCREEN_HEIGHT/2; - return camera_offset; + camera_offset_.x = tux_pos.x - SCREEN_WIDTH/2; + camera_offset_.y = tux_pos.y - SCREEN_HEIGHT/2; + return camera_offset_; } void @@ -567,15 +572,11 @@ WorldMap::clamp_camera_position(Vector& c) { void WorldMap::update(float delta) { - if(!in_level) { - if (MenuManager::instance().check_menu()) - { - return; - } - + if (!in_level && !MenuManager::instance().is_active()) + { // update GameObjects for(size_t i = 0; i < game_objects.size(); ++i) { - GameObject* object = game_objects[i]; + GameObjectPtr& object = game_objects[i]; if(!panning || object != tux) { object->update(delta); } @@ -584,10 +585,9 @@ WorldMap::update(float delta) // remove old GameObjects for(GameObjects::iterator i = game_objects.begin(); i != game_objects.end(); ) { - GameObject* object = *i; + GameObjectPtr& object = *i; if(!object->is_valid()) { try_unexpose(object); - object->unref(); i = game_objects.erase(i); } else { ++i; @@ -597,10 +597,9 @@ WorldMap::update(float delta) /* update solid_tilemaps list */ //FIXME: this could be more efficient solid_tilemaps.clear(); - for(std::vector::iterator i = game_objects.begin(); - i != game_objects.end(); ++i) + for(auto i = game_objects.begin(); i != game_objects.end(); ++i) { - TileMap* tm = dynamic_cast(*i); + TileMap* tm = dynamic_cast(i->get()); if (!tm) continue; if (tm->is_solid()) solid_tilemaps.push_back(tm); } @@ -611,12 +610,12 @@ WorldMap::update(float delta) if(!panning) { camera_offset = get_camera_pos_for_tux(); } else { - Vector delta = pan_pos - camera_offset; - float mag = delta.norm(); + Vector delta__ = pan_pos - camera_offset; + float mag = delta__.norm(); if(mag > CAMERA_PAN_SPEED) { - delta *= CAMERA_PAN_SPEED/mag; + delta__ *= CAMERA_PAN_SPEED/mag; } - camera_offset += delta; + camera_offset += delta__; if(camera_offset == pan_pos) { panning = false; } @@ -635,7 +634,7 @@ WorldMap::update(float delta) } // handle input - Controller *controller = g_input_manager->get_controller(); + Controller *controller = InputManager::current()->get_controller(); bool enter_level = false; if(controller->pressed(Controller::ACTION) || controller->pressed(Controller::JUMP) @@ -644,8 +643,17 @@ WorldMap::update(float delta) if(!controller->pressed(Controller::UP)) enter_level = true; } - if(controller->pressed(Controller::PAUSE_MENU)) + if(controller->pressed(Controller::START) || + controller->pressed(Controller::ESCAPE)) + { on_escape_press(); + } + + if(controller->pressed(Controller::CHEAT_MENU) && + g_config->developer_mode) + { + MenuManager::instance().set_menu(MenuStorage::WORLDMAP_CHEAT_MENU); + } // check for teleporters Teleporter* teleporter = at_teleporter(tux->get_tile_pos()); @@ -655,7 +663,7 @@ WorldMap::update(float delta) change(teleporter->worldmap, teleporter->spawnpoint); } else { // TODO: an animation, camera scrolling or a fading would be a nice touch - sound_manager->play("sounds/warp.wav"); + SoundManager::current()->play("sounds/warp.wav"); tux->back_direction = D_NONE; move_to_spawnpoint(teleporter->spawnpoint, true); } @@ -672,8 +680,8 @@ WorldMap::update(float delta) if (enter_level && !tux->is_moving()) { /* Check level action */ - LevelTile* level = at_level(); - if (!level) { + LevelTile* level_ = at_level(); + if (!level_) { //Respawn if player on a tile with no level and nowhere to go. int tile_data = tile_data_at(tux->get_tile_pos()); if(!( tile_data & ( Tile::WORLDMAP_NORTH | Tile::WORLDMAP_SOUTH | Tile::WORLDMAP_WEST | Tile::WORLDMAP_EAST ))){ @@ -685,16 +693,16 @@ WorldMap::update(float delta) return; } - if (level->pos == tux->get_tile_pos()) { + if (level_->pos == tux->get_tile_pos()) { try { - Vector shrinkpos = Vector(level->pos.x*32 + 16 - camera_offset.x, - level->pos.y*32 + 8 - camera_offset.y); - std::string levelfile = levels_path + level->get_name(); + Vector shrinkpos = Vector(level_->pos.x*32 + 16 - camera_offset.x, + level_->pos.y*32 + 8 - camera_offset.y); + std::string levelfile = levels_path + level_->get_name(); // update state and savegame save_state(); - g_screen_manager->push_screen(std::unique_ptr(new GameSession(levelfile, player_status, &level->statistics)), + ScreenManager::current()->push_screen(std::unique_ptr(new GameSession(levelfile, m_savegame, &level_->statistics)), std::unique_ptr(new ShrinkFade(shrinkpos, 1.0f))); in_level = true; } catch(std::exception& e) { @@ -714,7 +722,7 @@ WorldMap::tile_data_at(Vector p) { int dirs = 0; - for(std::list::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) { + for(std::list::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); ++i) { TileMap* tilemap = *i; const Tile* tile = tilemap->get_tile((int)p.x, (int)p.y); int dirdata = tile->getData(); @@ -790,9 +798,9 @@ WorldMap::draw(DrawingContext& context) context.push_transform(); context.set_translation(camera_offset); - for(GameObjects::iterator i = game_objects.begin(); - i != game_objects.end(); ++i) { - GameObject* object = *i; + for(auto i = game_objects.begin(); i != game_objects.end(); ++i) + { + GameObjectPtr& object = *i; if(!panning || object != tux) { object->draw(context); } @@ -829,7 +837,7 @@ WorldMap::draw_status(DrawingContext& context) context.push_transform(); context.set_translation(Vector(0, 0)); - player_status->draw(context); + m_savegame.get_player_status()->draw(context); if (!tux->is_moving()) { for(LevelTiles::iterator i = levels.begin(); i != levels.end(); ++i) { @@ -900,7 +908,7 @@ WorldMap::draw_status(DrawingContext& context) void WorldMap::setup() { - sound_manager->play_music(music); + SoundManager::current()->play_music(music); MenuManager::instance().clear_menu_stack(); current_ = this; @@ -956,6 +964,16 @@ WorldMap::leave() } void +WorldMap::set_levels_solved(bool solved, bool perfect) +{ + for(auto& level : levels) + { + level->set_solved(solved); + level->set_perfect(perfect); + } +} + +void WorldMap::save_state() { using namespace scripting; @@ -985,7 +1003,8 @@ WorldMap::save_state() sq_pushstring(vm, map_filename.c_str(), map_filename.length()); if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse))) - sq_pop(vm, 1); + { + } // construct new table for this worldmap sq_pushstring(vm, map_filename.c_str(), map_filename.length()); @@ -1015,24 +1034,32 @@ WorldMap::save_state() store_bool(vm, "perfect", level->perfect); level->statistics.serialize_to_squirrel(vm); - sq_createslot(vm, -3); + if(SQ_FAILED(sq_createslot(vm, -3))) + { + throw std::runtime_error("failed to create '" + name + "' table entry"); + } } - sq_createslot(vm, -3); + if(SQ_FAILED(sq_createslot(vm, -3))) + { + throw std::runtime_error("failed to create '" + name + "' table entry"); + } // overall statistics... total_stats.serialize_to_squirrel(vm); // push world into worlds table - sq_createslot(vm, -3); + if(SQ_FAILED(sq_createslot(vm, -3))) + { + throw std::runtime_error("failed to create '" + name + "' table entry"); + } } catch(std::exception& ) { sq_settop(vm, oldtop); } sq_settop(vm, oldtop); - if(World::current() != NULL) - World::current()->save_state(); + m_savegame.save(); } void @@ -1166,7 +1193,7 @@ float WorldMap::get_width() const { float width = 0; - for(std::list::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) { + for(std::list::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); ++i) { TileMap* solids = *i; if (solids->get_width() > width) width = solids->get_width(); } @@ -1177,7 +1204,7 @@ float WorldMap::get_height() const { float height = 0; - for(std::list::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) { + for(std::list::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); ++i) { TileMap* solids = *i; if (solids->get_height() > height) height = solids->get_height(); }