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.

196 lines
4.8 KiB
C++

#include "level.h"
#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:
case SECTION::CHARGE:
case SECTION::TRIGGER:
readCellSection(sstr, cur_section);
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::readCellSection(std::istringstream &sstr, const SECTION &section)
{
coordinate src_row, src_col;
sstr >> src_row >> src_col;
switch (section) {
case SECTION::TELEPORT:
data[src_row][src_col] = readTeleport(sstr, static_unique_pointer_cast<TeleportCell>(std::move(data[src_row][src_col])));
break;
case SECTION::CHARGE:
data[src_row][src_col] = readCharge(sstr, static_unique_pointer_cast<ChargeCell>(std::move(data[src_row][src_col])));
break;
case SECTION::TRIGGER:
data[src_row][src_col] = readTrigger(sstr, static_unique_pointer_cast<TriggerCell>(std::move(data[src_row][src_col])));
break;
default:
break;
}
}
std::unique_ptr<TeleportCell> &&Level::Map::readTeleport(std::istringstream &sstr, std::unique_ptr<TeleportCell> &&cell)
{
coordinate dest_row, dest_col;
sstr >> dest_row >> dest_col;
cell->setDestination(dest_row, dest_col);
return std::move(cell);
}
std::unique_ptr<ChargeCell> &&Level::Map::readCharge(std::istringstream &sstr, std::unique_ptr<ChargeCell> &&cell)
{
int num_charges;
sstr >> num_charges;
cell->setCharges(num_charges);
return std::move(cell);
}
std::unique_ptr<TriggerCell> &&Level::Map::readTrigger(std::istringstream &sstr, std::unique_ptr<TriggerCell> &&cell)
{
coordinate dest_row, dest_col;
int cell_type;
sstr >> dest_row >> dest_col >> cell_type;
auto dest_cell = default_cells[cell_type]->clone();
dest_cell->setPosition(dest_row, dest_col);
switch (cell_type) {
case TELEPORT_CELL:
dest_cell = readTeleport(sstr, static_unique_pointer_cast<TeleportCell>(std::move(dest_cell)));
break;
case CHARGE_CELL:
dest_cell = readCharge(sstr, static_unique_pointer_cast<ChargeCell>(std::move(dest_cell)));
break;
case TRIGGER_CELL:
dest_cell = readTrigger(sstr, static_unique_pointer_cast<TriggerCell>(std::move(dest_cell)));
break;
default:
break;
}
cell->addTarget(std::move(dest_cell));
return std::move(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;
}
std::unique_ptr<Cell> &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;
}