Merge branch 'oss' into develop

This commit is contained in:
NaiJi ✨ 2020-03-19 18:32:29 +03:00
commit 118d3de73b
7 changed files with 203 additions and 115 deletions

View File

@ -46,7 +46,7 @@ bool PassableCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return true; return true;
} }
CellPtr PassableCell::getDefaultInstance() const CellPtr PassableCell::clone() const
{ {
return std::make_unique<PassableCell>(); return std::make_unique<PassableCell>();
} }
@ -69,7 +69,7 @@ bool WaterCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return false; return false;
} }
CellPtr WaterCell::getDefaultInstance() const CellPtr WaterCell::clone() const
{ {
return std::make_unique<WaterCell>(); return std::make_unique<WaterCell>();
} }
@ -94,7 +94,7 @@ bool WallCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return false; return false;
} }
CellPtr WallCell::getDefaultInstance() const CellPtr WallCell::clone() const
{ {
return std::make_unique<WallCell>(); return std::make_unique<WallCell>();
} }
@ -120,7 +120,7 @@ bool ChargeCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return true; return true;
} }
CellPtr ChargeCell::getDefaultInstance() const CellPtr ChargeCell::clone() const
{ {
return std::make_unique<ChargeCell>(); return std::make_unique<ChargeCell>();
} }
@ -143,7 +143,7 @@ bool ExitCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return true; return true;
} }
CellPtr ExitCell::getDefaultInstance() const CellPtr ExitCell::clone() const
{ {
return std::make_unique<ExitCell>(); return std::make_unique<ExitCell>();
} }
@ -174,7 +174,7 @@ void TeleportCell::setDestination(coordinate new_cell_row, coordinate new_cell_c
new_col = new_cell_col; new_col = new_cell_col;
} }
CellPtr TeleportCell::getDefaultInstance() const CellPtr TeleportCell::clone() const
{ {
return std::make_unique<TeleportCell>(); return std::make_unique<TeleportCell>();
} }
@ -182,6 +182,8 @@ CellPtr TeleportCell::getDefaultInstance() const
/////////////////////////////////////// ///////////////////////////////////////
const std::vector<CELL_TYPE> TriggerCell::cells_to_cast { PASSABLE_CELL, WATER_CELL, WALL_CELL, EXIT_CELL };
TriggerCell::TriggerCell(/*std::vector<CellPtr> &&cells_to_change,*/ coordinate cell_row, coordinate cell_col, const sf::Color &color) : TriggerCell::TriggerCell(/*std::vector<CellPtr> &&cells_to_change,*/ coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Cell(cell_row, cell_col, color) Cell(cell_row, cell_col, color)
{ {
@ -194,27 +196,31 @@ TriggerCell::TriggerCell(/*std::vector<CellPtr> &&cells_to_change,*/ coordinate
TriggerCell::~TriggerCell() TriggerCell::~TriggerCell()
{} {}
void TriggerCell::addTarget(CellPtr &&cell)
{
UNUSED(cell);
//cells.emplace_back(cell);
}
bool TriggerCell::onMovingTo(HeroPtr &hero, LevelPtr &level) bool TriggerCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
{ {
UNUSED(hero); UNUSED(hero);
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 (CellPtr &cell : cells)
{ {
const coordinate &row = cell->row(); const coordinate &row = cell->row();
const coordinate &col = cell->col(); const coordinate &col = cell->col();
map[row][col].release(); level->getCellAt(row, col).release();
map[row][col] = std::move(cell); level->getCellAt(row, col) = std::move(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;
} }
CellPtr TriggerCell::getDefaultInstance() const CellPtr TriggerCell::clone() const
{ {
return std::make_unique<TriggerCell>(); return std::make_unique<TriggerCell>();
} }

View File

@ -21,14 +21,14 @@ const sf::Color Pink = sf::Color(255, 192, 203);
const sf::Color Black = sf::Color( 0, 0, 0); const sf::Color Black = sf::Color( 0, 0, 0);
} }
enum CELL_TYPES { enum CELL_TYPE {
PASSABLE_CELL = 0, PASSABLE_CELL = 0,
WATER_CELL, WATER_CELL = 1,
WALL_CELL, WALL_CELL = 2,
CHARGE_CELL, CHARGE_CELL = 3,
EXIT_CELL, EXIT_CELL = 4,
TELEPORT_CELL, TELEPORT_CELL = 5,
TRIGGER_CELL, TRIGGER_CELL = 6,
N_CELLS N_CELLS
}; };
@ -69,7 +69,7 @@ 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 CellPtr getDefaultInstance() const = 0; virtual CellPtr clone() const = 0;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -86,7 +86,7 @@ public:
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual CellPtr getDefaultInstance() const override; virtual CellPtr clone() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -103,7 +103,7 @@ public:
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual CellPtr getDefaultInstance() const override; virtual CellPtr clone() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -120,7 +120,7 @@ public:
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual CellPtr getDefaultInstance() const override; virtual CellPtr clone() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -141,7 +141,7 @@ public:
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual CellPtr getDefaultInstance() const override; virtual CellPtr clone() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -158,7 +158,7 @@ public:
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual CellPtr getDefaultInstance() const override; virtual CellPtr clone() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -182,7 +182,7 @@ public:
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual CellPtr getDefaultInstance() const override; virtual CellPtr clone() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
@ -191,10 +191,13 @@ public:
class TriggerCell final : public Cell class TriggerCell final : public Cell
{ {
private: private:
// Vector of cells to place on map // Vector of cells to place on map
std::vector<CellPtr> cells; std::vector<CellPtr> cells;
public: public:
// Vector of cell types you can cast in to
static const std::vector<CELL_TYPE> cells_to_cast;
TriggerCell(//std::vector<CellPtr> &&cells_to_change, TriggerCell(//std::vector<CellPtr> &&cells_to_change,
coordinate cell_row = 0, coordinate cell_row = 0,
coordinate cell_col = 0, coordinate cell_col = 0,
@ -202,9 +205,11 @@ public:
virtual ~TriggerCell() override; virtual ~TriggerCell() override;
void addTarget(CellPtr &&cell);
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual CellPtr getDefaultInstance() const override; virtual CellPtr clone() const override;
}; };
#endif // CELL_H #endif // CELL_H

View File

@ -100,6 +100,6 @@ void Game::onMoving(sf::Keyboard::Key &key)
////////////////////////// //////////////////////////
if (!level->mapArray()[attempt_row][attempt_col]->onMovingTo(hero, level)) if (!level->getCellAt(attempt_row, attempt_col)->onMovingTo(hero, level))
hero->setPosition(initial_row, initial_col); hero->setPosition(initial_row, initial_col);
} }

View File

@ -1,103 +1,146 @@
#include "level.h" #include "level.h"
#include <sstream>
#include <fstream> #include <fstream>
#include <cstring> #include <algorithm>
#include <iostream>
void Level::prepareCellInstances()
{
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::readMap(std::ifstream &file)
{
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);
}
}
}
template<typename D, typename B> // [D]erived - [B]ase template<typename D, typename B> // [D]erived - [B]ase
std::unique_ptr<D> static_unique_pointer_cast (std::unique_ptr<B>&& old) std::unique_ptr<D> static_unique_pointer_cast(std::unique_ptr<B>&& old)
{ {
return std::unique_ptr<D>{static_cast<D*>(old.release())}; return std::unique_ptr<D>{static_cast<D *>(old.release())};
} }
Level::Level(const std::string &map_file) void Level::Map::init(const std::string &map_file_name)
{ {
prepareCellInstances(); prepareDefaultCells();
std::ifstream file; std::ifstream file;
file.open(map_file); file.open(map_file_name);
std::string cur_line; std::string cur_line;
std::istringstream sstr;
SECTION cur_section = SECTION::NONE;
while (getline(file, cur_line)) while (getline(file, cur_line))
{ {
// need fix; see std::string.compare if (map_section.find(cur_line) != map_section.end())
if (strstr(cur_line.data(), "size") != NULL)
{ {
file >> level_width >> level_height; cur_section = map_section[cur_line];
map.resize(level_height); continue;
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; sstr.clear();
auto teleport_cell = static_unique_pointer_cast<TeleportCell>(std::move(map[src_row][src_col])); sstr.str(cur_line);
teleport_cell->setDestination(dest_row, dest_col); switch (cur_section)
map[src_row][src_col] = std::move(teleport_cell); {
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);
}
} }
Level::~Level() void Level::Map::readTeleport(std::istringstream &sstr)
{ {
for (Cell *cell : default_cells) coordinate src_row, src_col;
delete cell; 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);
} }
size_t Level::width() const void Level::Map::readTrigger(std::istringstream &sstr)
{ {
return level_width; 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]));
trigger_cell->addTarget(default_cells[cell_type]->clone());
data[src_row][src_col] = std::move(trigger_cell);
} }
size_t Level::height() const Level::Level(const std::string &map_file_name)
{ {
return level_height; map.init(map_file_name);
}
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) void Level::placeBridge(coordinate row, coordinate col)
{ {
map[row][col] = std::make_unique<PassableCell>(row, col, palette::Black); map.data[row][col] = std::make_unique<PassableCell>(row, col, palette::Black);
} }
void Level::removeCharge(coordinate row, coordinate col) void Level::removeCharge(coordinate row, coordinate col)
{ {
map[row][col] = std::make_unique<PassableCell>(row, col, color_ground); map.data[row][col] = std::make_unique<PassableCell>(row, col, color_ground);
}
Map& Level::mapArray()
{
return map;
} }
sf::Color Level::defaultGroundColor() sf::Color Level::defaultGroundColor()

View File

@ -2,38 +2,74 @@
#define LEVEL_H #define LEVEL_H
#include <array> #include <array>
#include <map>
#include "cell.h" #include "cell.h"
const std::string default_file_name = "test_map"; // Very desirable to create module for default values
const std::string default_map_file_name = "test_map";
using Row = std::vector<CellPtr>;
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
{ {
private: private:
struct Map
{
using Row = std::vector<CellPtr>;
using Matrix = std::vector<Row>;
enum class SECTION
{
SIZE,
MAP,
TELEPORT,
TRIGGER,
NONE
};
std::map<std::string, SECTION> map_section =
{
{ "size", SECTION::SIZE },
{ "map", SECTION::MAP },
{ "teleport", SECTION::TELEPORT },
{ "trigger", SECTION::TRIGGER },
{ "", SECTION::NONE }
};
Matrix data;
size_t rows, cols;
std::array<CellPtr, N_CELLS> default_cells;
void init(const std::string &map_file_name = default_map_file_name);
/// Prepare prototypes of default cells
void prepareDefaultCells();
/// Map file section readers
void readMapSize(std::istringstream &sstr);
void readMapRow(std::istringstream &sstr);
void readTeleport(std::istringstream &sstr);
void readTrigger(std::istringstream &sstr);
};
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(const std::string &map_file = default_file_name); Level(const std::string &map_file_name = default_map_file_name);
~Level();
size_t width() const; /// Number of map rows
size_t height() const; size_t rows() const;
/// Number of map columns
size_t cols() const;
/// Get cell at position row, col
CellPtr &getCellAt(coordinate row, coordinate col);
/// Place a bridge cell /// Place a bridge cell
void placeBridge(coordinate x, coordinate y); void placeBridge(coordinate x, coordinate y);
/// Get the 2D array of level map
Map& mapArray();
/// Replace a charge cell with a ground cell /// Replace a charge cell with a ground cell
void removeCharge(coordinate x, coordinate y); void removeCharge(coordinate x, coordinate y);

View File

@ -77,8 +77,6 @@ bool Renderer::render(const LevelPtr &level, const HeroPtr &hero, sf::RenderWind
if (!hero || !level) if (!hero || !level)
return false; return false;
const Map &map = level->mapArray();
painter_x = init_painter_x; painter_x = init_painter_x;
painter_y = init_painter_y; painter_y = init_painter_y;
horizontal_shift = 0; horizontal_shift = 0;
@ -94,15 +92,15 @@ bool Renderer::render(const LevelPtr &level, const HeroPtr &hero, sf::RenderWind
hero->position(hero_row, hero_col); hero->position(hero_row, hero_col);
// Draw map from 2D array // Draw map from 2D array
for (coordinate x = 0; x < level->width(); ++x) for (coordinate c = 0; c < level->cols(); ++c)
{ {
horizontal_shift = static_cast<float>(level->width()) * cell_deviation; horizontal_shift = static_cast<float>(level->cols()) * cell_deviation;
for (coordinate y = 0; y < level->height(); ++y) for (coordinate r = 0; r < level->rows(); ++r)
{ {
drawCell(map[y][x], main_window); drawCell(level->getCellAt(r, c), main_window);
if (hero_row == y && hero_col == x) if (hero_row == r && hero_col == c)
{ {
// Draw the hero sprite // Draw the hero sprite
brush_cell.setFillColor(palette::White); brush_cell.setFillColor(palette::White);

View File

@ -3,7 +3,7 @@ CONFIG += c++17
CONFIG -= console app_bundle CONFIG -= console app_bundle
CONFIG -= qt CONFIG -= qt
QMAKE_CXXFLAGS = -Wall -Werror -Wextra -Wpedantic -Wconversion -std=c++17 -O2 -g QMAKE_CXXFLAGS = -Wall -Werror -Wextra -Wpedantic -Wconversion -std=c++17 -O0 -g
SOURCES += \ SOURCES += \
cell.cpp \ cell.cpp \