196 lines
4.8 KiB
C++
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 §ion)
|
|
{
|
|
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;
|
|
}
|