BonusBlock::BonusBlock(const ReaderMapping& lisp) : Block(SpriteManager::current()->create("images/objects/bonus_block/bonusblock.sprite")), contents(), object(0), hit_counter(1), sprite_name(), script(), lightsprite() { Vector pos; contents = CONTENT_COIN; auto iter = lisp.get_iter(); while(iter.next()) { const std::string& token = iter.get_key(); if(token == "x") { iter.get(pos.x); } else if(token == "y") { iter.get(pos.y); } else if(token == "sprite") { iter.get(sprite_name); sprite = SpriteManager::current()->create(sprite_name); } else if(token == "count") { iter.get(hit_counter); } else if(token == "script") { iter.get(script); } else if(token == "data") { int d = 0; iter.get(d); get_content_by_data(d); } else if(token == "contents") { std::string contentstring; iter.get(contentstring); contents = get_content_from_string(contentstring); } else { if(contents == CONTENT_CUSTOM) { ReaderMapping object_mapping = iter.as_mapping(); GameObjectPtr game_object = ObjectFactory::instance().create(token, object_mapping); object = std::dynamic_pointer_cast<MovingObject>(game_object); if(object == 0) throw std::runtime_error( "Only MovingObjects are allowed inside BonusBlocks"); } else { log_warning << "Invalid element '" << token << "' in bonusblock" << std::endl; } } } if(contents == CONTENT_CUSTOM && object == 0) throw std::runtime_error("Need to specify content object for custom block"); if(contents == CONTENT_LIGHT) { SoundManager::current()->preload("sounds/switch.ogg"); lightsprite = Surface::create("/images/objects/lightmap_light/bonusblock_light.png"); } bbox.set_pos(pos); }
void JoystickConfig::read(const ReaderMapping& joystick_lisp) { joystick_lisp.get("dead-zone", dead_zone); joystick_lisp.get("jump-with-up", jump_with_up_joy); joystick_lisp.get("use-game-controller", use_game_controller); auto iter = joystick_lisp.get_iter(); while(iter.next()) { if (iter.get_key() == "map") { int button = -1; int axis = 0; int hat = -1; std::string control; auto map = iter.as_mapping(); map.get("control", control); int i = 0; for(i = 0; Controller::controlNames[i] != 0; ++i) { if (control == Controller::controlNames[i]) break; } if (Controller::controlNames[i] == 0) { log_info << "Invalid control '" << control << "' in buttonmap" << std::endl; } else { if (map.get("button", button)) { bind_joybutton(0, button, Controller::Control(i)); } else if (map.get("axis", axis)) { bind_joyaxis(0, axis, Controller::Control(i)); } else if (map.get("hat", hat)) { if (hat != SDL_HAT_UP && hat != SDL_HAT_DOWN && hat != SDL_HAT_LEFT && hat != SDL_HAT_RIGHT) { log_info << "Invalid axis '" << axis << "' in axismap" << std::endl; } else { bind_joyhat(0, hat, Controller::Control(i)); } } } } } }
void Path::read(const ReaderMapping& reader) { auto iter = reader.get_iter(); mode = CIRCULAR; while(iter.next()) { if(iter.get_key() == "mode") { std::string mode_string; iter.get(mode_string); if(mode_string == "oneshot") mode = ONE_SHOT; else if(mode_string == "pingpong") mode = PING_PONG; else if(mode_string == "circular") mode = CIRCULAR; else if(mode_string == "unordered") mode = UNORDERED; else { std::ostringstream msg; msg << "Unknown pathmode '" << mode_string << "' found"; throw std::runtime_error(msg.str()); } continue; } else if (iter.get_key() == "node") { ReaderMapping node_mapping = iter.as_mapping(); // each new node will inherit all values from the last one Node node; node.time = 1; if( (!node_mapping.get("x", node.position.x) || !node_mapping.get("y", node.position.y))) throw std::runtime_error("Path node without x and y coordinate specified"); node_mapping.get("time", node.time); if(node.time <= 0) throw std::runtime_error("Path node with non-positive time"); nodes.push_back(node); } else { log_warning << "unknown token '" << iter.get_key() << "' in Path nodes list. Ignored." << std::endl; } } if (nodes.empty()) throw std::runtime_error("Path with zero nodes"); }
SpriteData::SpriteData(const ReaderMapping& lisp, const std::string& basedir) : actions(), name() { auto iter = lisp.get_iter(); while(iter.next()) { if(iter.get_key() == "name") { iter.get(name); } else if(iter.get_key() == "action") { parse_action(iter.as_mapping(), basedir); } else { log_warning << "Unknown sprite field: " << iter.get_key() << std::endl; } } if(actions.empty()) throw std::runtime_error("Error: Sprite without actions."); }
ObjectGroup::ObjectGroup(const ReaderMapping& reader) : name(), icons(), for_worldmap(false) { icons.clear(); icons.push_back( ObjectIcon("#move", "images/engine/editor/arrow.png") ); reader.get("name", name); reader.get("worldmap", for_worldmap); auto iter = reader.get_iter(); while(iter.next()) { const std::string& token = iter.get_key(); if (token == "object") { icons.push_back( ObjectIcon( iter.as_mapping() ) ); } } }
void SectorParser::parse_old_format(const ReaderMapping& reader) { m_sector.name = "main"; reader.get("gravity", m_sector.gravity); std::string backgroundimage; if (reader.get("background", backgroundimage) && (backgroundimage != "")) { if (backgroundimage == "arctis.png") backgroundimage = "arctis.jpg"; if (backgroundimage == "arctis2.jpg") backgroundimage = "arctis.jpg"; if (backgroundimage == "ocean.png") backgroundimage = "ocean.jpg"; backgroundimage = "images/background/" + backgroundimage; if (!PHYSFS_exists(backgroundimage.c_str())) { log_warning << "Background image \"" << backgroundimage << "\" not found. Ignoring." << std::endl; backgroundimage = ""; } } float bgspeed = .5; reader.get("bkgd_speed", bgspeed); bgspeed /= 100; Color bkgd_top, bkgd_bottom; int r = 0, g = 0, b = 128; reader.get("bkgd_red_top", r); reader.get("bkgd_green_top", g); reader.get("bkgd_blue_top", b); bkgd_top.red = static_cast<float> (r) / 255.0f; bkgd_top.green = static_cast<float> (g) / 255.0f; bkgd_top.blue = static_cast<float> (b) / 255.0f; reader.get("bkgd_red_bottom", r); reader.get("bkgd_green_bottom", g); reader.get("bkgd_blue_bottom", b); bkgd_bottom.red = static_cast<float> (r) / 255.0f; bkgd_bottom.green = static_cast<float> (g) / 255.0f; bkgd_bottom.blue = static_cast<float> (b) / 255.0f; if(backgroundimage != "") { auto background = std::make_shared<Background>(); background->set_image(backgroundimage, bgspeed); m_sector.add_object(background); } else { auto gradient = std::make_shared<Gradient>(); gradient->set_gradient(bkgd_top, bkgd_bottom); m_sector.add_object(gradient); } std::string particlesystem; reader.get("particle_system", particlesystem); if(particlesystem == "clouds") m_sector.add_object(std::make_shared<CloudParticleSystem>()); else if(particlesystem == "snow") m_sector.add_object(std::make_shared<SnowParticleSystem>()); else if(particlesystem == "rain") m_sector.add_object(std::make_shared<RainParticleSystem>()); Vector startpos(100, 170); reader.get("start_pos_x", startpos.x); reader.get("start_pos_y", startpos.y); auto spawn = std::make_shared<SpawnPoint>(); spawn->pos = startpos; spawn->name = "main"; m_sector.spawnpoints.push_back(spawn); m_sector.music = "chipdisko.ogg"; // skip reading music filename. It's all .ogg now, anyway /* reader.get("music", music); */ m_sector.music = "music/" + m_sector.music; int width = 30, height = 15; reader.get("width", width); reader.get("height", height); std::vector<unsigned int> tiles; if(reader.get("interactive-tm", tiles) || reader.get("tilemap", tiles)) { auto tileset = TileManager::current()->get_tileset(m_sector.level->get_tileset()); auto tilemap = std::make_shared<TileMap>(tileset); tilemap->set(width, height, tiles, LAYER_TILES, true); // replace tile id 112 (old invisible tile) with 1311 (new invisible tile) for(size_t x=0; x < tilemap->get_width(); ++x) { for(size_t y=0; y < tilemap->get_height(); ++y) { uint32_t id = tilemap->get_tile_id(x, y); if(id == 112) tilemap->change(x, y, 1311); } } if (height < 19) tilemap->resize(width, 19); m_sector.add_object(tilemap); } if(reader.get("background-tm", tiles)) { auto tileset = TileManager::current()->get_tileset(m_sector.level->get_tileset()); auto tilemap = std::make_shared<TileMap>(tileset); tilemap->set(width, height, tiles, LAYER_BACKGROUNDTILES, false); if (height < 19) tilemap->resize(width, 19); m_sector.add_object(tilemap); } if(reader.get("foreground-tm", tiles)) { auto tileset = TileManager::current()->get_tileset(m_sector.level->get_tileset()); auto tilemap = std::make_shared<TileMap>(tileset); tilemap->set(width, height, tiles, LAYER_FOREGROUNDTILES, false); // fill additional space in foreground with tiles of ID 2035 (lightmap/black) if (height < 19) tilemap->resize(width, 19, 2035); m_sector.add_object(tilemap); } // read reset-points (now spawn-points) ReaderMapping resetpoints; if(reader.get("reset-points", resetpoints)) { auto iter = resetpoints.get_iter(); while(iter.next()) { if(iter.get_key() == "point") { Vector sp_pos; if(reader.get("x", sp_pos.x) && reader.get("y", sp_pos.y)) { auto sp = std::make_shared<SpawnPoint>(); sp->name = "main"; sp->pos = sp_pos; m_sector.spawnpoints.push_back(sp); } } else { log_warning << "Unknown token '" << iter.get_key() << "' in reset-points." << std::endl; } } } // read objects ReaderCollection objects; if(reader.get("objects", objects)) { for(auto const& obj : objects.get_objects()) { auto object = parse_object(obj.get_name(), obj.get_mapping()); if(object) { m_sector.add_object(object); } else { log_warning << "Unknown object '" << obj.get_name() << "' in level." << std::endl; } } } // add a camera auto camera_ = std::make_shared<Camera>(&m_sector, "Camera"); m_sector.add_object(camera_); m_sector.update_game_objects(); if (m_sector.solid_tilemaps.empty()) { log_warning << "sector '" << m_sector.name << "' does not contain a solid tile layer." << std::endl; } fix_old_tiles(); m_sector.update_game_objects(); }
void SectorParser::parse(const ReaderMapping& sector) { bool has_background = false; auto iter = sector.get_iter(); while(iter.next()) { if(iter.get_key() == "name") { iter.get(m_sector.name); } else if(iter.get_key() == "gravity") { iter.get(m_sector.gravity); } else if(iter.get_key() == "music") { iter.get(m_sector.music); } else if(iter.get_key() == "spawnpoint") { auto sp = std::make_shared<SpawnPoint>(iter.as_mapping()); if (sp->name != "" && sp->pos.x >= 0 && sp->pos.y >= 0) { m_sector.spawnpoints.push_back(sp); } } else if(iter.get_key() == "init-script") { iter.get(m_sector.init_script); } else if(iter.get_key() == "ambient-light") { std::vector<float> vColor; sector.get( "ambient-light", vColor ); if(vColor.size() < 3) { log_warning << "(ambient-light) requires a color as argument" << std::endl; } else { m_sector.ambient_light = Color( vColor ); } } else { GameObjectPtr object = parse_object(iter.get_key(), iter.as_mapping()); if(object) { if(std::dynamic_pointer_cast<Background>(object)) { has_background = true; } else if(std::dynamic_pointer_cast<Gradient>(object)) { has_background = true; } m_sector.add_object(object); } } } if(!has_background) { auto gradient = std::make_shared<Gradient>(); gradient->set_gradient(Color(0.3, 0.4, 0.75), Color(1, 1, 1)); m_sector.add_object(gradient); } m_sector.update_game_objects(); if (m_sector.solid_tilemaps.empty()) { log_warning << "sector '" << m_sector.name << "' does not contain a solid tile layer." << std::endl; } fix_old_tiles(); if (!m_sector.camera) { log_warning << "sector '" << m_sector.name << "' does not contain a camera." << std::endl; m_sector.update_game_objects(); m_sector.add_object(std::make_shared<Camera>(&m_sector, "Camera")); } m_sector.update_game_objects(); m_sector.foremost_layer = m_sector.calculate_foremost_layer(); }
TextScroller::TextScroller(const std::string& filename) : defaultspeed(DEFAULT_SPEED), speed(defaultspeed), music(), background(), lines(), scroll(0), fading(false) { std::string text; std::string background_file; try { register_translation_directory(filename); auto doc = ReaderDocument::parse(filename); auto root = doc.get_root(); if(root.get_name() != "supertux-text") { throw std::runtime_error("File isn't a supertux-text file"); } else { auto text_lisp = root.get_mapping(); int version = 1; text_lisp.get("version", version); if (version == 1) { log_info << "[" << filename << "] Text uses old format: version 1" << std::endl; if(!text_lisp.get("text", text)) { throw std::runtime_error("File doesn't contain a text field"); } // Split text string lines into a vector lines = InfoBoxLine::split(text, static_cast<float>(SCREEN_WIDTH) - 2.0f * LEFT_BORDER); } else if (version == 2) { ReaderMapping content; if (!text_lisp.get("content", content)) { throw std::runtime_error("File doesn't contain content"); } else { auto iter = content.get_iter(); while (iter.next()) { if (iter.get_key() == "image") { std::string image_file; iter.get(image_file); lines.emplace_back(new InfoBoxLine('!', image_file)); } else if (iter.get_key() == "person") { bool simple; std::string name, info, image_file; if (!iter.as_mapping().get("simple", simple)) { simple = false; } if (simple) { if (!iter.as_mapping().get("name", name) || !iter.as_mapping().get("info", info)) { throw std::runtime_error("Simple entry requires both name and info specified"); } if (iter.as_mapping().get("image", image_file)) { log_warning << "[" << filename << "] Simple person entry shouldn't specify images" << std::endl; } lines.emplace_back(new InfoBoxLine(' ', name + " (" + info + ")")); } else { if (iter.as_mapping().get("name", name)) { lines.emplace_back(new InfoBoxLine('\t', name)); } if (iter.as_mapping().get("image", image_file) && !simple) { lines.emplace_back(new InfoBoxLine('!', image_file)); } if (iter.as_mapping().get("info", info)) { lines.emplace_back(new InfoBoxLine(' ', info)); } } } else if (iter.get_key() == "blank") { // Empty line lines.emplace_back(new InfoBoxLine('\t', "")); } else if (iter.get_key() == "text") { std::string type, string; if (!iter.as_mapping().get("type", type)) { type = "normal"; } if (!iter.as_mapping().get("string", string)) { throw std::runtime_error("Text entry requires a string"); } if (type == "normal") lines.emplace_back(new InfoBoxLine('\t', string)); else if (type == "normal-left") lines.emplace_back(new InfoBoxLine('#', string)); else if (type == "small") lines.emplace_back(new InfoBoxLine(' ', string)); else if (type == "heading") lines.emplace_back(new InfoBoxLine('-', string)); else if (type == "reference") lines.emplace_back(new InfoBoxLine('*', string)); else { log_warning << "[" << filename << "] Unknown text type '" << type << "'" << std::endl; lines.emplace_back(new InfoBoxLine('\t', string)); } } else { log_warning << "[" << filename << "] Unknown token '" << iter.get_key() << "'" << std::endl; } } } } else { throw std::runtime_error("File format version is not supported"); } if (!text_lisp.get("background", background_file)) { throw std::runtime_error("File doesn't contain a background file"); } text_lisp.get("speed", defaultspeed); text_lisp.get("music", music); } } catch (std::exception& e) { std::ostringstream msg; msg << "Couldn't load file '" << filename << "': " << e.what() << std::endl; throw std::runtime_error(msg.str()); } // load background image background = Surface::create("images/background/" + background_file); }