Global refactoring; add level builder

master
oss 4 years ago
parent e8f06c3929
commit 6eac3c84f6

@ -3,10 +3,10 @@
#include "hero.h" #include "hero.h"
#include "level.h" #include "level.h"
#define UNUSED(expr) (void)(expr); #define UNUSED(expr) (void)(expr)
Cell::Cell(coordinate cell_x, coordinate cell_y, const sf::Color &color) : Cell::Cell(coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Entity(cell_x, cell_y), Entity(cell_row, cell_col),
cell_color(color) cell_color(color)
{} {}
@ -20,8 +20,8 @@ sf::Color Cell::color() const noexcept
/////////////////////////////////////// ///////////////////////////////////////
PassableCell::PassableCell(coordinate cell_x, coordinate cell_y, const sf::Color &color) : PassableCell::PassableCell(coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Cell(cell_x, cell_y, color) Cell(cell_row, cell_col, color)
{} {}
PassableCell::~PassableCell() PassableCell::~PassableCell()
@ -29,17 +29,21 @@ PassableCell::~PassableCell()
bool PassableCell::onMovingTo(HeroPtr &hero, LevelPtr &level) bool PassableCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
{ {
UNUSED(hero) UNUSED(hero), UNUSED(level);
UNUSED(level)
// Hero just moves on. // Hero just moves on.
return true; return true;
} }
Cell *PassableCell::getDefaultInstance()
{
return new PassableCell();
}
/////////////////////////////////////// ///////////////////////////////////////
WaterCell::WaterCell(coordinate cell_x, coordinate cell_y, const sf::Color &color) : WaterCell::WaterCell(coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Cell(cell_x, cell_y, color) Cell(cell_row, cell_col, color)
{} {}
WaterCell::~WaterCell() WaterCell::~WaterCell()
@ -48,19 +52,21 @@ WaterCell::~WaterCell()
bool WaterCell::onMovingTo(HeroPtr &hero, LevelPtr &level) bool WaterCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
{ {
// Try to use one charge to place a bridge // Try to use one charge to place a bridge
if (hero->useCharge()) { if (hero->useCharge())
level->placeBridge(pos_x, pos_y); level->placeBridge(entity_row, entity_col);
return true;
}
// If hero doesn't have enough charges, we move Hero back
return false; return false;
} }
Cell *WaterCell::getDefaultInstance()
{
return new WaterCell();
}
/////////////////////////////////////// ///////////////////////////////////////
WallCell::WallCell(coordinate cell_x, coordinate cell_y, const sf::Color &color) : WallCell::WallCell(coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Cell(cell_x, cell_y, color) Cell(cell_row, cell_col, color)
{} {}
WallCell::~WallCell() WallCell::~WallCell()
@ -68,17 +74,21 @@ WallCell::~WallCell()
bool WallCell::onMovingTo(HeroPtr &hero, LevelPtr &level) bool WallCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
{ {
UNUSED(hero) UNUSED(hero), UNUSED(level);
UNUSED(level)
// Hero never passes this cell. // Hero never passes this cell.
return false; return false;
} }
Cell *WallCell::getDefaultInstance()
{
return new WallCell();
}
/////////////////////////////////////// ///////////////////////////////////////
ChargeCell::ChargeCell(coordinate cell_x, coordinate cell_y, int has_charges, const sf::Color &color) : ChargeCell::ChargeCell(coordinate cell_row, coordinate cell_col, int has_charges, const sf::Color &color) :
Cell(cell_x, cell_y, color), Cell(cell_row, cell_col, color),
cell_charges(has_charges) cell_charges(has_charges)
{} {}
@ -89,15 +99,20 @@ bool ChargeCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
{ {
// Hero picks up the charge; remove it from the map // Hero picks up the charge; remove it from the map
hero->refillCharges(cell_charges); hero->refillCharges(cell_charges);
level->removeCharge(pos_x, pos_y); level->removeCharge(entity_row, entity_col);
return true; return true;
} }
Cell *ChargeCell::getDefaultInstance()
{
return new ChargeCell();
}
/////////////////////////////////////// ///////////////////////////////////////
ExitCell::ExitCell(coordinate cell_x, coordinate cell_y, const sf::Color &color) : ExitCell::ExitCell(coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Cell(cell_x, cell_y, color) Cell(cell_row, cell_col, color)
{} {}
ExitCell::~ExitCell() ExitCell::~ExitCell()
@ -105,19 +120,24 @@ ExitCell::~ExitCell()
bool ExitCell::onMovingTo(HeroPtr &hero, LevelPtr &level) bool ExitCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
{ {
UNUSED(level) UNUSED(level);
// Level is over. // Level is over.
hero->reachExit(); hero->reachExit();
return true; return true;
} }
Cell *ExitCell::getDefaultInstance()
{
return new ExitCell();
}
/////////////////////////////////////// ///////////////////////////////////////
TeleportCell::TeleportCell(coordinate cell_x, coordinate cell_y, coordinate new_cell_x, coordinate new_cell_y, const sf::Color &color) : TeleportCell::TeleportCell(coordinate cell_row, coordinate cell_col, coordinate new_cell_row, coordinate new_cell_col, const sf::Color &color) :
Cell(cell_x, cell_y, color), Cell(cell_row, cell_col, color),
new_x(new_cell_x), new_x(new_cell_row),
new_y(new_cell_y) new_y(new_cell_col)
{} {}
TeleportCell::~TeleportCell() TeleportCell::~TeleportCell()
@ -125,19 +145,24 @@ TeleportCell::~TeleportCell()
bool TeleportCell::onMovingTo(HeroPtr &hero, LevelPtr &level) bool TeleportCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
{ {
UNUSED(level) UNUSED(level);
// Hero jumps into teleport! // Hero jumps into teleport!
hero->setPosition(new_x, new_y); hero->setPosition(new_x, new_y);
return true; return true;
} }
Cell *TeleportCell::getDefaultInstance()
{
return new TeleportCell();
}
/////////////////////////////////////// ///////////////////////////////////////
TriggerCell::TriggerCell(std::vector<CellPtr> &&cells_to_change, coordinate cell_x, coordinate cell_y, const sf::Color &color) : TriggerCell::TriggerCell(/*std::vector<CellPtr> &&cells_to_change,*/ coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Cell(cell_x, cell_y, color) Cell(cell_row, cell_col, color)
{ {
cells = std::move(cells_to_change); //cells = std::move(cells_to_change);
} }
TriggerCell::~TriggerCell() TriggerCell::~TriggerCell()
@ -145,20 +170,25 @@ TriggerCell::~TriggerCell()
bool TriggerCell::onMovingTo(HeroPtr &hero, LevelPtr &level) bool TriggerCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
{ {
UNUSED(hero) UNUSED(hero);
Map &map = level->mapArray(); Map &map = level->mapArray();
// We replace needed cells with the ones that the trigger provides. // We replace needed cells with the ones that the trigger provides.
for (CellPtr &cell : cells) for (Cell *cell : cells)
{ {
const coordinate &y = cell->y(); const coordinate &row = cell->row();
const coordinate &x = cell->x(); const coordinate &col = cell->col();
map[x][y].release(); delete map[row][col];
map[x][y] = std::move(cell); map[row][col] = cell;
} }
// It's an impassable object, so player can't move to here. // It's an impassable object, so player can't move to here.
return false; return false;
} }
Cell *TriggerCell::getDefaultInstance()
{
return new TriggerCell();
}

@ -16,6 +16,18 @@ const sf::Color Blue = sf::Color(0, 255, 255);
const sf::Color Gray = sf::Color(125, 125, 125); const sf::Color Gray = sf::Color(125, 125, 125);
} }
enum CELL_TYPES {
PASSABLE_CELL = 0,
WATER_CELL,
WALL_CELL,
CHARGE_CELL,
EXIT_CELL,
TELEPORT_CELL,
TRIGGER_CELL,
N_CELLS
};
/////////////////////////////////////// ///////////////////////////////////////
class Hero; class Hero;
@ -24,7 +36,6 @@ class Cell;
using HeroPtr = std::unique_ptr<Hero>; using HeroPtr = std::unique_ptr<Hero>;
using LevelPtr = std::unique_ptr<Level>; using LevelPtr = std::unique_ptr<Level>;
using CellPtr = std::unique_ptr<Cell>;
/////////////////////////////////////// ///////////////////////////////////////
@ -35,8 +46,8 @@ protected:
sf::Color cell_color; sf::Color cell_color;
public: public:
Cell(coordinate cell_x = 0, Cell(coordinate cell_row = 0,
coordinate cell_y = 0, coordinate cell_col = 0,
const sf::Color &color = palette::White); const sf::Color &color = palette::White);
virtual ~Cell() override; virtual ~Cell() override;
@ -45,6 +56,8 @@ public:
/// Determine if Hero can move onto this cell or not /// Determine if Hero can move onto this cell or not
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) = 0; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) = 0;
virtual Cell *getDefaultInstance() = 0;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -53,13 +66,15 @@ public:
class PassableCell : public Cell class PassableCell : public Cell
{ {
public: public:
PassableCell(coordinate cell_x = 0, PassableCell(coordinate cell_row = 0,
coordinate cell_y = 0, // Brown coordinate cell_col = 0, // Brown
const sf::Color &color = palette::Brown); const sf::Color &color = palette::Brown);
virtual ~PassableCell() override; virtual ~PassableCell() override;
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -68,13 +83,15 @@ public:
class WaterCell : public Cell class WaterCell : public Cell
{ {
public: public:
WaterCell(coordinate cell_x = 0, WaterCell(coordinate cell_row = 0,
coordinate cell_y = 0, coordinate cell_col = 0,
const sf::Color &color = palette::Blue); const sf::Color &color = palette::Blue);
virtual ~WaterCell() override; virtual ~WaterCell() override;
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -83,13 +100,15 @@ public:
class WallCell : public Cell class WallCell : public Cell
{ {
public: public:
WallCell(coordinate cell_x = 0, WallCell(coordinate cell_row = 0,
coordinate cell_y = 0, // Gray coordinate cell_col = 0, // Gray
const sf::Color &color = ); const sf::Color &color = palette::Gray);
virtual ~WallCell() override; virtual ~WallCell() override;
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -101,14 +120,16 @@ private:
int cell_charges; int cell_charges;
public: public:
ChargeCell(coordinate cell_x = 0, ChargeCell(coordinate cell_row = 0,
coordinate cell_y = 0, coordinate cell_col = 0,
int has_charges = 1, int has_charges = 1,
const sf::Color &color = sf::Color::Green); const sf::Color &color = sf::Color::Green);
virtual ~ChargeCell() override; virtual ~ChargeCell() override;
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -117,13 +138,15 @@ public:
class ExitCell : public Cell class ExitCell : public Cell
{ {
public: public:
ExitCell(coordinate cell_x = 0, ExitCell(coordinate cell_row = 0,
coordinate cell_y = 0, coordinate cell_col = 0,
const sf::Color &color = sf::Color::Red); const sf::Color &color = sf::Color::Red);
virtual ~ExitCell() override; virtual ~ExitCell() override;
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -135,15 +158,17 @@ private:
coordinate new_x, new_y; coordinate new_x, new_y;
public: public:
TeleportCell(coordinate cell_x = 0, TeleportCell(coordinate cell_row = 0,
coordinate cell_y = 0, coordinate cell_col = 0,
coordinate new_cell_x = 0, coordinate new_cell_row = 0,
coordinate new_cell_y = 0, // Purple coordinate new_cell_col = 0, // Purple
const sf::Color &color = sf::Color(128, 0, 128)); const sf::Color &color = sf::Color(128, 0, 128));
virtual ~TeleportCell() override; virtual ~TeleportCell() override;
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -153,17 +178,19 @@ class TriggerCell : public Cell
{ {
private: private:
// Vector of cells to place on map // Vector of cells to place on map
std::vector<CellPtr> cells; std::vector<Cell *> cells;
public: public:
TriggerCell(std::vector<CellPtr> &&cells_to_change, TriggerCell(//std::vector<CellPtr> &&cells_to_change,
coordinate cell_x = 0, coordinate cell_row = 0,
coordinate cell_y = 0, // Pink coordinate cell_col = 0, // Pink
const sf::Color &color = sf::Color(255, 192, 203)); const sf::Color &color = sf::Color(255, 192, 203));
virtual ~TriggerCell() override; virtual ~TriggerCell() override;
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override;
}; };
#endif // CELL_H #endif // CELL_H

@ -1,31 +1,31 @@
#include "entity.h" #include "entity.h"
Entity::Entity(coordinate _x, coordinate _y) : Entity::Entity(coordinate _row, coordinate _col) :
pos_x(_x), pos_y(_y) entity_row(_row), entity_col(_col)
{} {}
Entity::~Entity() Entity::~Entity()
{} {}
/// Get current Entity position /// Get current Entity position
void Entity::position(coordinate &x, coordinate &y) const noexcept void Entity::position(coordinate &row, coordinate &col) const noexcept
{ {
x = pos_x; row = entity_row;
y = pos_y; col = entity_col;
} }
void Entity::setPosition(coordinate x, coordinate y) void Entity::setPosition(coordinate row, coordinate col)
{ {
pos_x = x; entity_row = row;
pos_y = y; entity_col = col;
} }
coordinate Entity::x() const noexcept coordinate Entity::row() const noexcept
{ {
return pos_x; return entity_row;
} }
coordinate Entity::y() const noexcept coordinate Entity::col() const noexcept
{ {
return pos_y; return entity_col;
} }

@ -1,30 +1,30 @@
#ifndef ENTITY_H #ifndef ENTITY_H
#define ENTITY_H #define ENTITY_H
using coordinate = unsigned int; using coordinate = unsigned long;
/// Interface representing entity which can be placed on the map /// Interface representing entity which can be placed on the map
class Entity class Entity
{ {
protected: protected:
coordinate pos_x, pos_y; coordinate entity_row, entity_col;
public: public:
Entity(coordinate _x = 0, coordinate _y = 0); Entity(coordinate _row = 0, coordinate _col = 0);
virtual ~Entity() = 0; virtual ~Entity() = 0;
/// Get current Entity position /// Get current Entity position
void position(coordinate &x, coordinate &y) const noexcept; void position(coordinate &row, coordinate &col) const noexcept;
/// Set Entity position explicitly /// Set Entity position explicitly
void setPosition(coordinate x, coordinate y); void setPosition(coordinate row, coordinate col);
/// Get current x of the Entity position /// Get current x of the Entity position
coordinate x() const noexcept; coordinate row() const noexcept;
/// Get current y of the Entity position /// Get current y of the Entity position
coordinate y() const noexcept; coordinate col() const noexcept;
}; };
#endif // ENTITY_H #endif // ENTITY_H

@ -8,7 +8,7 @@ constexpr int cell_width = 60;
constexpr int cell_height = 35; constexpr int cell_height = 35;
constexpr int cell_deviation = 25; constexpr int cell_deviation = 25;
constexpr int window_side = cell_width * side; constexpr int window_side = cell_width * 4;
Game::Game() Game::Game()
{ {
@ -18,11 +18,11 @@ Game::Game()
// Generate level // Generate level
level = std::make_unique<Level>(); level = std::make_unique<Level>();
main_window.create(sf::VideoMode(window_side, window_side), "SFML-Test Application", sf::Style::Default); main_window.create(sf::VideoMode(window_side * 2, window_side * 2), "SFML-Test Application", sf::Style::Default);
main_window.setActive(); main_window.setActive();
current_level = 1; current_level = 1;
loadLevel(current_level); //loadLevel(current_level);
} }
int Game::run() int Game::run()
@ -54,7 +54,6 @@ int Game::run()
} }
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
Direction Game::getDirection(sf::Keyboard::Key &key) const Direction Game::getDirection(sf::Keyboard::Key &key) const
{ {
switch (key) switch (key)
@ -93,24 +92,20 @@ void Game::onMoving(sf::Keyboard::Key &key)
return; return;
// Save the initial coordinates // Save the initial coordinates
coordinate initial_x, initial_y; coordinate initial_row, initial_col;
hero->position(initial_x, initial_y); hero->position(initial_row, initial_col);
// Try to move hero // Try to move hero
hero->move(direction); hero->move(direction);
// Save the new coordinates after moving // Save the new coordinates after moving
coordinate attempt_x, attempt_y; coordinate attempt_row, attempt_col;
hero->position(attempt_x, attempt_y); hero->position(attempt_row, attempt_col);
////////////////////////// //////////////////////////
if (!level->mapArray()[attempt_x][attempt_y]->onMovingTo(hero, level)) if (!level->mapArray()[attempt_row][attempt_col]->onMovingTo(hero, level))
hero->setPosition(initial_x, initial_y); hero->setPosition(initial_row, initial_col);
if (hero->onExit())
loadLevel(++current_level);
} }
void Game::renderMap() void Game::renderMap()
@ -142,22 +137,22 @@ void Game::renderMap()
text.setString("Available bridge cells: " + std::to_string(hero->charges())); text.setString("Available bridge cells: " + std::to_string(hero->charges()));
// Where is hero // Where is hero
coordinate hero_x, hero_y; coordinate hero_row, hero_col;
hero->position(hero_x, hero_y); hero->position(hero_row, hero_col);
// Draw map from 2D array // Draw map from 2D array
for (coordinate x = 0; x < side; ++x) for (coordinate x = 0; x < level->width(); ++x)
{ {
shift = side * cell_deviation; shift = static_cast<float>(level->width()) * cell_deviation;
for (coordinate y = 0; y < side; ++y) for (coordinate y = 0; y < level->height(); ++y)
{ {
convex_brush.setPosition(shift + painter_x, painter_y); convex_brush.setPosition(shift + painter_x, painter_y);
convex_brush.setFillColor(map[x][y]->color()); convex_brush.setFillColor(map[y][x]->color());
main_window.draw(convex_brush); main_window.draw(convex_brush);
if (hero_x == x && hero_y == y) if (hero_row == y && hero_col == x)
{ {
// Place the hero sprite // Place the hero sprite
convex_brush.setFillColor(sf::Color::White); convex_brush.setFillColor(sf::Color::White);
@ -176,52 +171,3 @@ void Game::renderMap()
main_window.draw(text); main_window.draw(text);
} }
void Game::loadLevel(int level_index)
{
Map &map = level->mapArray();
// Fill the level with water
for (coordinate x = 0; x < side; ++x)
for (coordinate y = 0; y < side; ++y)
map[x][y] = std::make_unique<WaterCell>(x, y);
std::vector<CellPtr> trigger_cells;
trigger_cells.emplace_back(std::make_unique<PassableCell>(0, 0));
trigger_cells.emplace_back(std::make_unique<PassableCell>(1, 0));
trigger_cells.emplace_back(std::make_unique<PassableCell>(0, 1));
switch (level_index)
{
case 1:
// Hardcoding is temporary!
hero->setPosition(1, 1);
hero->setCharges(2);
level->setDefaultGroundColor(sf::Color(165, 42, 42));
map[0][0] = std::make_unique<WallCell>(0, 0);
map[0][1] = std::make_unique<WallCell>(0, 1);
map[1][0] = std::make_unique<WallCell>(1, 0);
map[1][1] = std::make_unique<PassableCell>(1, 1);
map[1][2] = std::make_unique<PassableCell>(1, 2);
map[1][3] = std::make_unique<PassableCell>(1, 3);
map[1][4] = std::make_unique<PassableCell>(1, 4);
map[2][1] = std::make_unique<TeleportCell>(2, 1, 6, 6);
map[2][2] = std::make_unique<PassableCell>(2, 2);
map[3][2] = std::make_unique<PassableCell>(3, 2);
map[3][3] = std::make_unique<PassableCell>(3, 3);
map[6][3] = std::make_unique<PassableCell>(6, 3);
map[6][4] = std::make_unique<PassableCell>(6, 4);
map[6][5] = std::make_unique<PassableCell>(6, 5);
map[6][6] = std::make_unique<PassableCell>(6, 6);
map[7][6] = std::make_unique<PassableCell>(7, 6);
map[9][6] = std::make_unique<PassableCell>(9, 6);
map[8][7] = std::make_unique<ExitCell>(8, 7);
map[2][3] = std::make_unique<ChargeCell>(2, 3, 5);
map[3][3] = std::make_unique<TriggerCell>(std::move(trigger_cells), 3, 3);
break;
default:
main_window.close();
}
}

@ -33,7 +33,7 @@ private:
void renderMap(); void renderMap();
/// Prepare map and hero for a game level /// Prepare map and hero for a game level
void loadLevel(int level_index = 1); //void loadLevel(int level_index = 1);
public: public:
explicit Game(); explicit Game();

@ -1,7 +1,7 @@
#include "hero.h" #include "hero.h"
Hero::Hero(coordinate position_x, coordinate position_y, int initial_charges) : Hero::Hero(coordinate row, coordinate col, int initial_charges) :
Entity(position_x, position_y), Entity(row, col),
hero_charges(initial_charges), hero_charges(initial_charges),
on_exit(false) on_exit(false)
{} {}
@ -37,13 +37,13 @@ void Hero::move(const Direction &direction)
switch (direction) switch (direction)
{ {
case Direction::Up: case Direction::Up:
--pos_y; break; --entity_row; break;
case Direction::Down: case Direction::Down:
++pos_y; break; ++entity_row; break;
case Direction::Left: case Direction::Left:
--pos_x; break; --entity_col; break;
case Direction::Right: case Direction::Right:
++pos_x; break; ++entity_col; break;
case Direction::None: case Direction::None:
break; break;
} }

@ -20,7 +20,7 @@ private:
bool on_exit; bool on_exit;
public: public:
explicit Hero(coordinate position_x = 0, coordinate position_y = 0, int initial_charges = 0); explicit Hero(coordinate row = 0, coordinate col = 0, int initial_charges = 0);
/// Add more charges for hero to use /// Add more charges for hero to use
void refillCharges(int append_charges); void refillCharges(int append_charges);

@ -1,16 +1,98 @@
#include "level.h" #include "level.h"
Level::Level() #include <fstream>
{} #include <cstring>
void Level::placeBridge(coordinate x, coordinate y) void Level::prepareCellInstances()
{ {
map[x][y] = std::make_unique<PassableCell>(x, y, sf::Color::Black); default_cells[PASSABLE_CELL] = new PassableCell();
default_cells[WATER_CELL] = new WaterCell();
default_cells[WALL_CELL] = new WallCell();
default_cells[CHARGE_CELL] = new ChargeCell();
default_cells[EXIT_CELL] = new ExitCell();
default_cells[TELEPORT_CELL] = new TeleportCell();
default_cells[TRIGGER_CELL] = new TriggerCell();
} }
void Level::removeCharge(coordinate x, coordinate y) void Level::readMap(std::ifstream &file)
{ {
map[x][y] = std::make_unique<PassableCell>(x, y, color_ground); int i;
for (coordinate j = 0; j < map.size(); ++j)
{
for (coordinate k = 0; k < map[j].size(); ++k)
{
file >> i;
map[j][k] = default_cells[i]->getDefaultInstance();
map[j][k]->setPosition(j, k);
}
}
}
Level::Level(const std::string &map_file)
{
prepareCellInstances();
std::ifstream file;
file.open(map_file);
std::string cur_line;
while (getline(file, cur_line))
{
// need fix; see std::string.compare
if (strstr(cur_line.data(), "size") != NULL)
{
file >> level_width >> level_height;
map.resize(level_height);
for (Row &row : map)
row.resize(level_width);
}
else if (strstr(cur_line.data(), "map") != NULL)
{
readMap(file);
}
else if (strstr(cur_line.data(), "teleport") != NULL)
{
coordinate src_row, src_col;
coordinate dest_row, dest_col;
file >> src_row >> src_col >> dest_row >> dest_col;
// reinterpret_cast<TeleportCell *>(map[src_row][src_col])->setDestination(dest_row, dest_col);
}
}
}
Level::~Level()
{
for (Cell *cell : default_cells)
delete cell;
for (Row &row : map)
for (Cell *cell : row)
delete cell;
}
size_t Level::width() const
{
return level_width;
}
size_t Level::height() const
{
return level_height;
}
void Level::placeBridge(coordinate row, coordinate col)
{
Cell *buf = map[row][col];
map[row][col] = new PassableCell(row, col, sf::Color::Black);
delete buf;
}
void Level::removeCharge(coordinate row, coordinate col)
{
Cell *buf = map[row][col];
map[row][col] = new PassableCell(row, col, color_ground);
delete buf;
} }
Map& Level::mapArray() Map& Level::mapArray()

@ -4,10 +4,10 @@
#include <array> #include <array>
#include "cell.h" #include "cell.h"
constexpr coordinate side = 32; const std::string default_file_name = "test_map";
using Row = std::array<CellPtr, side>; using Row = std::vector<Cell *>;
using Map = std::array<Row, side>; using Map = std::vector<Row>;
/// Abstraction over 2D array to quickly get access to level cells /// Abstraction over 2D array to quickly get access to level cells
class Level class Level
@ -15,9 +15,18 @@ class Level
private: private:
Map map; Map map;
sf::Color color_ground; sf::Color color_ground;
size_t level_width, level_height;
std::array<Cell *, N_CELLS> default_cells;
void prepareCellInstances();
void readMap(std::ifstream &file);
public: public:
Level(); Level(const std::string &map_file = default_file_name);
~Level();
size_t width() const;
size_t height() const;
/// Place a bridge cell /// Place a bridge cell
void placeBridge(coordinate x, coordinate y); void placeBridge(coordinate x, coordinate y);

Loading…
Cancel
Save