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
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 #4
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 #6
0
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();
}
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);
}