You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
3.8 KiB
C++

#include "level.h"
#include <sstream>
#include <fstream>
#include <algorithm>
#include <iostream>
template<typename D, typename B> // [D]erived - [B]ase
std::unique_ptr<D> static_unique_pointer_cast(std::unique_ptr<B>&& old)
{
return std::unique_ptr<D>{static_cast<D *>(old.release())};
}
void Level::Map::init(const std::string &path)
{
prepareDefaultCells();
std::ifstream file;
file.open(path);
std::string cur_line;
std::istringstream sstr;
SECTION cur_section = SECTION::NONE;
while (getline(file, cur_line))
{
if (map_section.find(cur_line) != map_section.end())
{
cur_section = map_section[cur_line];
continue;
}
sstr.clear();
sstr.str(cur_line);
switch (cur_section)
{
case SECTION::SIZE:
readMapSize(sstr);
break;
case SECTION::MAP:
readMapRow(sstr);
break;
case SECTION::TELEPORT:
readTeleport(sstr);
break;
case SECTION::TRIGGER:
readTrigger(sstr);
break;
default:
break;
}
}
file.close();
}
void Level::Map::prepareDefaultCells()
{
default_cells[PASSABLE_CELL] = std::make_unique<PassableCell>();
default_cells[WATER_CELL] = std::make_unique<WaterCell>();
default_cells[WALL_CELL] = std::make_unique<WallCell>();
default_cells[CHARGE_CELL] = std::make_unique<ChargeCell>();
default_cells[EXIT_CELL] = std::make_unique<ExitCell>();
default_cells[TELEPORT_CELL] = std::make_unique<TeleportCell>();
default_cells[TRIGGER_CELL] = std::make_unique<TriggerCell>();
}
void Level::Map::readMapSize(std::istringstream &sstr)
{
sstr >> rows >> cols;
data.reserve(rows * cols);
}
void Level::Map::readMapRow(std::istringstream &sstr)
{
data.emplace_back(Row());
int cell_type;
while (sstr >> cell_type)
{
data.back().emplace_back(default_cells[cell_type]->clone());
data.back().back()->setPosition(data.size()-1, data.back().size()-1);
}
}
void Level::Map::readTeleport(std::istringstream &sstr)
{
coordinate src_row, src_col;
coordinate dest_row, dest_col;
sstr >> src_row >> src_col >> dest_row >> dest_col;
auto teleport_cell = static_unique_pointer_cast<TeleportCell>(std::move(data[src_row][src_col]));
teleport_cell->setDestination(dest_row, dest_col);
data[src_row][src_col] = std::move(teleport_cell);
}
void Level::Map::readTrigger(std::istringstream &sstr)
{
coordinate src_row, src_col;
coordinate dest_row, dest_col;
int cell_type;
sstr >> src_row >> src_col >> dest_row >> dest_col >> cell_type;
if (std::find(TriggerCell::cells_to_cast.begin(), TriggerCell::cells_to_cast.end(), cell_type) ==
TriggerCell::cells_to_cast.end())
return ;
auto trigger_cell = static_unique_pointer_cast<TriggerCell>(std::move(data[src_row][src_col]));
auto dest_cell = default_cells[cell_type]->clone();
dest_cell->setPosition(dest_row, dest_col);
trigger_cell->addTarget(std::move(dest_cell));
data[src_row][src_col] = std::move(trigger_cell);
}
Level::Level(const std::string &path)
{
map.init(path);
}
size_t Level::rows() const
{
return map.rows;
}
size_t Level::cols() const
{
return map.cols;
}
CellPtr &Level::getCellAt(coordinate row, coordinate col)
{
return map.data[row][col];
}
void Level::placeBridge(coordinate row, coordinate col)
{
map.data[row][col] = std::make_unique<PassableCell>(row, col, palette::Black);
}
void Level::removeCharge(coordinate row, coordinate col)
{
map.data[row][col] = std::make_unique<PassableCell>(row, col, color_ground);
}
sf::Color Level::defaultGroundColor()
{
return color_ground;
}
void Level::setDefaultGroundColor(const sf::Color &color)
{
color_ground = color;
}