Example #1
0
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);
}
Example #2
0
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));
          }
        }
      }
    }
  }
}
Example #3
0
void
LevelParser::load(const std::string& filepath)
{
  try {
    m_level.m_filename = filepath;
    register_translation_directory(filepath);
    auto doc = ReaderDocument::from_file(filepath);
    auto root = doc.get_root();

    if(root.get_name() != "supertux-level")
      throw std::runtime_error("file is not a supertux-level file.");

    auto level = root.get_mapping();

    int version = 1;
    level.get("version", version);
    if(version == 1) {
      log_info << "[" <<  filepath << "] level uses old format: version 1" << std::endl;
      load_old_format(level);
    } else if (version == 2) {
      level.get("tileset", m_level.m_tileset);

      level.get("name", m_level.m_name);
      level.get("author", m_level.m_author);
      level.get("contact", m_level.m_contact);
      level.get("license", m_level.m_license);
      level.get("target-time", m_level.m_target_time);

      auto iter = level.get_iter();
      while(iter.next()) {
        if (iter.get_key() == "sector") {
          auto sector = SectorParser::from_reader(m_level, iter.as_mapping());
          m_level.add_sector(std::move(sector));
        }
      }

      if (m_level.m_license.empty()) {
        log_warning << "[" <<  filepath << "] The level author \"" << m_level.m_author
                    << "\" did not specify a license for this level \""
                    << m_level.m_name << "\". You might not be allowed to share it."
                    << std::endl;
      }
    } else {
      log_warning << "[" <<  filepath << "] level format version " << version << " is not supported" << std::endl;
    }
  } catch(std::exception& e) {
    std::stringstream msg;
    msg << "Problem when reading level '" << filepath << "': " << e.what();
    throw std::runtime_error(msg.str());
  }

  m_level.m_stats.init(m_level);
}
Example #4
0
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");
}
Example #5
0
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() ) );
    }
  }
}
Example #7
0
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();
}
Example #8
0
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);
}
Example #9
0
void
WorldMapParser::load_worldmap(const std::string& filename)
{
  m_worldmap.m_map_filename = physfsutil::realpath(filename);
  m_worldmap.m_levels_path = FileSystem::dirname(m_worldmap.m_map_filename);

  try {
    register_translation_directory(m_worldmap.m_map_filename);
    auto doc = ReaderDocument::from_file(m_worldmap.m_map_filename);
    auto root = doc.get_root();

    if (root.get_name() != "supertux-level")
      throw std::runtime_error("file isn't a supertux-level file.");

    auto level_ = root.get_mapping();

    level_.get("name", m_worldmap.m_name);

    std::string tileset_name;
    if (level_.get("tileset", tileset_name)) {
      if (m_worldmap.m_tileset != nullptr) {
        log_warning << "multiple tilesets specified in level_" << std::endl;
      } else {
        m_worldmap.m_tileset = TileManager::current()->get_tileset(tileset_name);
      }
    }
    /* load default tileset */
    if (m_worldmap.m_tileset == nullptr) {
      m_worldmap.m_tileset = TileManager::current()->get_tileset("images/worldmap.strf");
    }

    boost::optional<ReaderMapping> sector;
    if (!level_.get("sector", sector)) {
      throw std::runtime_error("No sector specified in worldmap file.");
    } else {
      auto iter = sector->get_iter();
      while (iter.next()) {
        if (iter.get_key() == "tilemap") {
          m_worldmap.add<TileMap>(m_worldmap.m_tileset, iter.as_mapping());
        } else if (iter.get_key() == "background") {
          m_worldmap.add<Background>(iter.as_mapping());
        } else if (iter.get_key() == "music") {
          const auto& sx = iter.get_sexp();
          if (sx.is_array() && sx.as_array().size() == 2 && sx.as_array()[1].is_string()) {
            std::string value;
            iter.get(value);
            m_worldmap.add<MusicObject>().set_music(value);
          } else {
            m_worldmap.add<MusicObject>(iter.as_mapping());
          }
        } else if (iter.get_key() == "init-script") {
          iter.get(m_worldmap.m_init_script);
        } else if (iter.get_key() == "worldmap-spawnpoint") {
          auto sp = std::make_unique<SpawnPoint>(iter.as_mapping());
          m_worldmap.m_spawn_points.push_back(std::move(sp));
        } else if (iter.get_key() == "level") {
          auto& level = m_worldmap.add<LevelTile>(m_worldmap.m_levels_path, iter.as_mapping());
          load_level_information(level);
        } else if (iter.get_key() == "special-tile") {
          m_worldmap.add<SpecialTile>(iter.as_mapping());
        } else if (iter.get_key() == "sprite-change") {
          m_worldmap.add<SpriteChange>(iter.as_mapping());
        } else if (iter.get_key() == "teleporter") {
          m_worldmap.add<Teleporter>(iter.as_mapping());
        } else if (iter.get_key() == "decal") {
          m_worldmap.add<Decal>(iter.as_mapping());
        } else if (iter.get_key() == "path") {
          m_worldmap.add<PathGameObject>(iter.as_mapping());
        } else if (iter.get_key() == "ambient-light") {
          const auto& sx = iter.get_sexp();
          if (sx.is_array() && sx.as_array().size() >= 3 &&
              sx.as_array()[1].is_real() && sx.as_array()[2].is_real() && sx.as_array()[3].is_real())
          {
            // for backward compatibilty
            std::vector<float> vColor;
            bool hasColor = sector->get("ambient-light", vColor);
            if (vColor.size() < 3 || !hasColor) {
              log_warning << "(ambient-light) requires a color as argument" << std::endl;
            } else {
              m_worldmap.add<AmbientLight>(Color(vColor));
            }
          } else {
            // modern format
            m_worldmap.add<AmbientLight>(iter.as_mapping());
          }
        } else if (iter.get_key() == "name") {
          // skip
        } else {
          log_warning << "Unknown token '" << iter.get_key() << "' in worldmap" << std::endl;
        }
      }
    }

    m_worldmap.flush_game_objects();

    if (m_worldmap.get_solid_tilemaps().empty())
      throw std::runtime_error("No solid tilemap specified");

    m_worldmap.move_to_spawnpoint("main");

  } catch(std::exception& e) {
    std::stringstream msg;
    msg << "Problem when parsing worldmap '" << m_worldmap.m_map_filename << "': " <<
      e.what();
    throw std::runtime_error(msg.str());
  }

  m_worldmap.finish_construction();
}