Resolve conflicts

This commit is contained in:
oss 2020-03-18 00:35:03 +03:00
commit 6b6dc6671c
11 changed files with 173 additions and 81 deletions

View File

@ -7,6 +7,6 @@ Just playing around with [sfml](https://www.sfml-dev.org/), since I have nothing
- Run `./sfml-test` command from your build destination. - Run `./sfml-test` command from your build destination.
### How to build: ### ### How to build: ###
- Except any C++ compiler which supports C++14 and higher, you also need to have SFML installed and accessible. - Except any C++ compiler which supports C++17 and higher, you also need to have SFML installed and accessible.
- Build the project (my sources work with qmake) - Build the project (my sources work with qmake)
- Move the `/src/font` folder into the folder of your build destination. - Move the `/src/font` folder into the folder of your build destination.

Binary file not shown.

10
build-debug/test_map Normal file
View File

@ -0,0 +1,10 @@
size
7 7
map
2 2 2 2 2 2 2
2 0 0 0 0 0 2
2 0 0 1 0 0 2
2 0 0 1 1 0 2
2 1 1 2 2 2 2
2 0 0 0 0 0 2
2 2 2 2 2 2 2

Binary file not shown.

10
build-release/test_map Normal file
View File

@ -0,0 +1,10 @@
size
7 7
map
2 2 2 2 2 2 2
2 0 0 0 0 0 2
2 0 0 1 0 0 2
2 0 0 1 1 0 2
2 1 1 2 2 2 2
2 0 0 0 0 0 2
2 2 2 2 2 2 2

View File

@ -7,7 +7,8 @@
Cell::Cell(coordinate cell_row, coordinate cell_col, const sf::Color &color) : Cell::Cell(coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Entity(cell_row, cell_col), Entity(cell_row, cell_col),
cell_color(color) cell_color(color),
height_shift(0) // ground by default
{} {}
Cell::~Cell() Cell::~Cell()
@ -18,6 +19,16 @@ sf::Color Cell::color() const noexcept
return cell_color; return cell_color;
} }
void Cell::setHeightShift(coordinate shift_by_y)
{
height_shift = shift_by_y;
}
coordinate Cell::heightShift() const
{
return height_shift;
}
/////////////////////////////////////// ///////////////////////////////////////
PassableCell::PassableCell(coordinate cell_row, coordinate cell_col, const sf::Color &color) : PassableCell::PassableCell(coordinate cell_row, coordinate cell_col, const sf::Color &color) :
@ -35,9 +46,9 @@ bool PassableCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return true; return true;
} }
Cell *PassableCell::getDefaultInstance() CellPtr PassableCell::getDefaultInstance() const
{ {
return new PassableCell(); return std::make_unique<PassableCell>();
} }
/////////////////////////////////////// ///////////////////////////////////////
@ -58,16 +69,19 @@ bool WaterCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return false; return false;
} }
Cell *WaterCell::getDefaultInstance() CellPtr WaterCell::getDefaultInstance() const
{ {
return new WaterCell(); return std::make_unique<WaterCell>();
} }
/////////////////////////////////////// ///////////////////////////////////////
WallCell::WallCell(coordinate cell_row, coordinate cell_col, const sf::Color &color) : WallCell::WallCell(coordinate cell_row, coordinate cell_col, const sf::Color &color) :
Cell(cell_row, cell_col, color) Cell(cell_row, cell_col, color)
{} {
// walls are a bit higher than ground and water
height_shift = 10;
}
WallCell::~WallCell() WallCell::~WallCell()
{} {}
@ -80,9 +94,9 @@ bool WallCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return false; return false;
} }
Cell *WallCell::getDefaultInstance() CellPtr WallCell::getDefaultInstance() const
{ {
return new WallCell(); return std::make_unique<WallCell>();
} }
/////////////////////////////////////// ///////////////////////////////////////
@ -90,7 +104,9 @@ Cell *WallCell::getDefaultInstance()
ChargeCell::ChargeCell(coordinate cell_row, coordinate cell_col, int has_charges, const sf::Color &color) : ChargeCell::ChargeCell(coordinate cell_row, coordinate cell_col, int has_charges, const sf::Color &color) :
Cell(cell_row, cell_col, color), Cell(cell_row, cell_col, color),
cell_charges(has_charges) cell_charges(has_charges)
{} {
height_shift = 5; // charges are a bit higher than ground and water, but lower than walls
}
ChargeCell::~ChargeCell() ChargeCell::~ChargeCell()
{} {}
@ -104,9 +120,9 @@ bool ChargeCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return true; return true;
} }
Cell *ChargeCell::getDefaultInstance() CellPtr ChargeCell::getDefaultInstance() const
{ {
return new ChargeCell(); return std::make_unique<ChargeCell>();
} }
/////////////////////////////////////// ///////////////////////////////////////
@ -127,17 +143,17 @@ bool ExitCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
return true; return true;
} }
Cell *ExitCell::getDefaultInstance() CellPtr ExitCell::getDefaultInstance() const
{ {
return new ExitCell(); return std::make_unique<ExitCell>();
} }
/////////////////////////////////////// ///////////////////////////////////////
TeleportCell::TeleportCell(coordinate cell_row, coordinate cell_col, coordinate new_cell_row, coordinate new_cell_col, 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_row, cell_col, color), Cell(cell_row, cell_col, color),
new_x(new_cell_row), new_row(new_cell_row),
new_y(new_cell_col) new_col(new_cell_col)
{} {}
TeleportCell::~TeleportCell() TeleportCell::~TeleportCell()
@ -148,21 +164,31 @@ 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_row, new_col);
return true; return true;
} }
Cell *TeleportCell::getDefaultInstance() void TeleportCell::setDestination(coordinate new_cell_row, coordinate new_cell_col)
{ {
return new TeleportCell(); new_row = new_cell_row;
new_col = new_cell_col;
} }
CellPtr TeleportCell::getDefaultInstance() const
{
return std::make_unique<TeleportCell>();
}
/////////////////////////////////////// ///////////////////////////////////////
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)
{ {
//cells = std::move(cells_to_change); //cells = std::move(cells_to_change);
// triggers are a bit higher than ground and water, but lower than walls
height_shift = 5;
} }
TriggerCell::~TriggerCell() TriggerCell::~TriggerCell()
@ -175,20 +201,20 @@ bool TriggerCell::onMovingTo(HeroPtr &hero, LevelPtr &level)
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 (Cell *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();
delete map[row][col]; map[row][col].release();
map[row][col] = cell; map[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;
} }
Cell *TriggerCell::getDefaultInstance() CellPtr TriggerCell::getDefaultInstance() const
{ {
return new TriggerCell(); return std::make_unique<TriggerCell>();
} }

View File

@ -10,10 +10,15 @@
namespace palette namespace palette
{ {
const sf::Color Brown = sf::Color(165, 42, 42); const sf::Color Brown = sf::Color(165, 42, 42);
const sf::Color White = sf::Color(255, 255, 255); const sf::Color White = sf::Color(255, 255, 255);
const sf::Color Blue = sf::Color(0, 255, 255); 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);
const sf::Color Green = sf::Color( 0, 255, 0);
const sf::Color Red = sf::Color(250, 0, 0);
const sf::Color Purple = sf::Color(128, 0, 128);
const sf::Color Pink = sf::Color(255, 192, 203);
const sf::Color Black = sf::Color( 0, 0, 0);
} }
enum CELL_TYPES { enum CELL_TYPES {
@ -36,6 +41,7 @@ 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>;
/////////////////////////////////////// ///////////////////////////////////////
@ -44,6 +50,7 @@ class Cell : public Entity
{ {
protected: protected:
sf::Color cell_color; sf::Color cell_color;
coordinate height_shift;
public: public:
Cell(coordinate cell_row = 0, Cell(coordinate cell_row = 0,
@ -53,34 +60,39 @@ public:
virtual ~Cell() override; virtual ~Cell() override;
sf::Color color() const noexcept; sf::Color color() const noexcept;
/// "shift_by_y" indicates the height of current cell
/// Height is a shift of y coordinate on the scene, relatively to the ground (which is 0)
void setHeightShift(coordinate shift_by_y);
coordinate heightShift() const;
/// 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; virtual CellPtr getDefaultInstance() const = 0;
}; };
/////////////////////////////////////// ///////////////////////////////////////
/// Any cell where Hero is free to move /// Any cell where Hero is free to move
class PassableCell : public Cell class PassableCell final : public Cell
{ {
public: public:
PassableCell(coordinate cell_row = 0, PassableCell(coordinate cell_row = 0,
coordinate cell_col = 0, // Brown coordinate cell_col = 0,
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; virtual CellPtr getDefaultInstance() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
/// A cell which requires Hero to spend a charge for bridge to move on /// A cell which requires Hero to spend a charge for bridge to move on
class WaterCell : public Cell class WaterCell final : public Cell
{ {
public: public:
WaterCell(coordinate cell_row = 0, WaterCell(coordinate cell_row = 0,
@ -91,30 +103,30 @@ public:
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override; virtual CellPtr getDefaultInstance() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
/// A cell which is impossible to move on /// A cell which is impossible to move on
class WallCell : public Cell class WallCell final : public Cell
{ {
public: public:
WallCell(coordinate cell_row = 0, WallCell(coordinate cell_row = 0,
coordinate cell_col = 0, // Gray coordinate cell_col = 0,
const sf::Color &color = palette::Gray); 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; virtual CellPtr getDefaultInstance() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
/// A cell which gives hero a charge /// A cell which gives hero a charge
class ChargeCell : public Cell class ChargeCell final : public Cell
{ {
private: private:
int cell_charges; int cell_charges;
@ -123,74 +135,76 @@ public:
ChargeCell(coordinate cell_row = 0, ChargeCell(coordinate cell_row = 0,
coordinate cell_col = 0, coordinate cell_col = 0,
int has_charges = 1, int has_charges = 1,
const sf::Color &color = sf::Color::Green); const sf::Color &color = palette::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; virtual CellPtr getDefaultInstance() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
/// A cell which moves hero to next level /// A cell which moves hero to next level
class ExitCell : public Cell class ExitCell final : public Cell
{ {
public: public:
ExitCell(coordinate cell_row = 0, ExitCell(coordinate cell_row = 0,
coordinate cell_col = 0, coordinate cell_col = 0,
const sf::Color &color = sf::Color::Red); const sf::Color &color = palette::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; virtual CellPtr getDefaultInstance() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
/// A cell which teleports hero to following coordinates /// A cell which teleports hero to following coordinates
class TeleportCell : public Cell class TeleportCell final : public Cell
{ {
private: private:
coordinate new_x, new_y; coordinate new_row, new_col;
public: public:
TeleportCell(coordinate cell_row = 0, TeleportCell(coordinate cell_row = 0,
coordinate cell_col = 0, coordinate cell_col = 0,
coordinate new_cell_row = 0, coordinate new_cell_row = 0,
coordinate new_cell_col = 0, // Purple coordinate new_cell_col = 0,
const sf::Color &color = sf::Color(128, 0, 128)); const sf::Color &color = palette::Purple);
virtual ~TeleportCell() override; virtual ~TeleportCell() override;
void setDestination(coordinate new_cell_row, coordinate new_cell_col);
virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override; virtual bool onMovingTo(HeroPtr &hero, LevelPtr &level) override;
virtual Cell *getDefaultInstance() override; virtual CellPtr getDefaultInstance() const override;
}; };
/////////////////////////////////////// ///////////////////////////////////////
/// A cell which replaces and changes other map cells when activated /// A cell which replaces and changes other map cells when activated
class TriggerCell : 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<Cell *> cells; std::vector<CellPtr> cells;
public: public:
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, // Pink coordinate cell_col = 0,
const sf::Color &color = sf::Color(255, 192, 203)); const sf::Color &color = palette::Pink);
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; virtual CellPtr getDefaultInstance() const override;
}; };
#endif // CELL_H #endif // CELL_H

View File

@ -18,9 +18,12 @@ Game::Game()
// Generate level // Generate level
level = std::make_unique<Level>(); level = std::make_unique<Level>();
main_window.create(sf::VideoMode(window_side * 2, window_side * 2), "SFML-Test Application", sf::Style::Default); main_window.create(sf::VideoMode(window_side * 3, window_side * 3), "SFML-Test Application", sf::Style::Default);
main_window.setActive(); main_window.setActive();
level->mapArray()[0][0]->setHeightShift(15);
level->mapArray()[0][1]->setHeightShift(10);
current_level = 1; current_level = 1;
//loadLevel(current_level); //loadLevel(current_level);
} }
@ -112,8 +115,8 @@ void Game::renderMap()
{ {
const Map &map = level->mapArray(); const Map &map = level->mapArray();
float painter_x = 0, painter_y = 0; float painter_x = 60, painter_y = 60;
float shift = 0; float horizontal_shift = 0, vertical_shift = 0;
// Brush for cell sprites // Brush for cell sprites
sf::ConvexShape convex_brush; sf::ConvexShape convex_brush;
@ -122,7 +125,7 @@ void Game::renderMap()
convex_brush.setPoint(1, sf::Vector2f(cell_deviation + cell_width, 0.f)); convex_brush.setPoint(1, sf::Vector2f(cell_deviation + cell_width, 0.f));
convex_brush.setPoint(2, sf::Vector2f(cell_width, cell_height)); convex_brush.setPoint(2, sf::Vector2f(cell_width, cell_height));
convex_brush.setPoint(3, sf::Vector2f(0.f, cell_height)); convex_brush.setPoint(3, sf::Vector2f(0.f, cell_height));
convex_brush.setFillColor(sf::Color::Blue); convex_brush.setFillColor(palette::Blue);
convex_brush.setOutlineThickness(0); convex_brush.setOutlineThickness(0);
convex_brush.setPosition(painter_x, painter_y); convex_brush.setPosition(painter_x, painter_y);
@ -131,7 +134,7 @@ void Game::renderMap()
sf::Font font; sf::Font font;
font.loadFromFile("font/VeraMono.ttf"); font.loadFromFile("font/VeraMono.ttf");
text.setFont(font); text.setFont(font);
text.setFillColor(sf::Color::White); text.setFillColor(palette::White);
text.setCharacterSize(25); text.setCharacterSize(25);
text.setPosition(50, 350); text.setPosition(50, 350);
text.setString("Available bridge cells: " + std::to_string(hero->charges())); text.setString("Available bridge cells: " + std::to_string(hero->charges()));
@ -143,29 +146,58 @@ void Game::renderMap()
// Draw map from 2D array // Draw map from 2D array
for (coordinate x = 0; x < level->cols(); ++x) for (coordinate x = 0; x < level->cols(); ++x)
{ {
shift = static_cast<float>(level->cols()) * cell_deviation; horizontal_shift = static_cast<float>(level->cols()) * cell_deviation;
for (coordinate y = 0; y < level->rows(); ++y) for (coordinate y = 0; y < level->rows(); ++y)
{ {
convex_brush.setPosition(shift + painter_x, painter_y); vertical_shift = static_cast<float>(map[y][x]->heightShift());
// If cell has any height value, we should draw walls for it
if (vertical_shift > 0)
{
// Brush for vertical walls
sf::ConvexShape convex_wall_brush;
convex_wall_brush.setPointCount(6);
convex_wall_brush.setPoint(0, sf::Vector2f(cell_deviation + cell_width, -vertical_shift));
convex_wall_brush.setPoint(1, sf::Vector2f(cell_deviation + cell_width, 0.f));
convex_wall_brush.setPoint(2, sf::Vector2f(cell_width, cell_height));
convex_wall_brush.setPoint(3, sf::Vector2f(0.f, cell_height));
convex_wall_brush.setPoint(4, sf::Vector2f(0.f, cell_height - vertical_shift));
convex_wall_brush.setPoint(5, sf::Vector2f(cell_width, cell_height));
convex_wall_brush.setOutlineThickness(0);
sf::Color wall_color(sf::Uint8(map[y][x]->color().r - 40), sf::Uint8(map[y][x]->color().g - 40), sf::Uint8(map[y][x]->color().b - 40));
convex_wall_brush.setFillColor(wall_color);
convex_wall_brush.setPosition(painter_x + horizontal_shift, painter_y);
main_window.draw(convex_wall_brush);
}
// Draw the top surface of the cell itself
float final_x = painter_x + horizontal_shift;
float final_y = painter_y - vertical_shift;
convex_brush.setPosition(final_x, final_y);
convex_brush.setFillColor(map[y][x]->color()); convex_brush.setFillColor(map[y][x]->color());
main_window.draw(convex_brush); main_window.draw(convex_brush);
if (hero_row == y && hero_col == x) if (hero_row == y && hero_col == x)
{ {
// Place the hero sprite // Draw the hero sprite
convex_brush.setFillColor(sf::Color::White); convex_brush.setFillColor(palette::White);
main_window.draw(convex_brush); main_window.draw(convex_brush);
} }
// Move painter to next cell of row // Move painter to next cell of current column
painter_y += cell_height; painter_y += cell_height;
shift -= cell_deviation; horizontal_shift -= cell_deviation;
} }
// Move painter to next row of the map // Move painter to next column
painter_y = 0; painter_y = 60;
painter_x += cell_width; painter_x += cell_width;
} }

View File

@ -15,8 +15,8 @@ class Game
{ {
private: private:
// Game entities // Game entities
std::unique_ptr<Hero> hero; HeroPtr hero;
std::unique_ptr<Level> level; LevelPtr level;
int current_level; int current_level;

View File

@ -28,6 +28,12 @@ void Level::readMap(std::ifstream &file)
} }
} }
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())};
}
Level::Level(const std::string &map_file) Level::Level(const std::string &map_file)
{ {
prepareCellInstances(); prepareCellInstances();
@ -56,7 +62,9 @@ Level::Level(const std::string &map_file)
coordinate dest_row, dest_col; coordinate dest_row, dest_col;
file >> src_row >> src_col >> 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); auto teleport_cell = static_unique_pointer_cast<TeleportCell>(std::move(map[src_row][src_col]));
teleport_cell->setDestination(dest_row, dest_col);
map[src_row][src_col] = std::move(teleport_cell);
} }
} }
} }
@ -65,10 +73,6 @@ Level::~Level()
{ {
for (Cell *cell : default_cells) for (Cell *cell : default_cells)
delete cell; delete cell;
for (Row &row : map)
for (Cell *cell : row)
delete cell;
} }
size_t Level::rows() const size_t Level::rows() const
@ -83,16 +87,12 @@ size_t Level::cols() const
void Level::placeBridge(coordinate row, coordinate col) void Level::placeBridge(coordinate row, coordinate col)
{ {
Cell *buf = map[row][col]; map[row][col] = std::make_unique<PassableCell>(row, col, palette::Black);
map[row][col] = new PassableCell(row, col, sf::Color::Black);
delete buf;
} }
void Level::removeCharge(coordinate row, coordinate col) void Level::removeCharge(coordinate row, coordinate col)
{ {
Cell *buf = map[row][col]; map[row][col] = std::make_unique<PassableCell>(row, col, color_ground);
map[row][col] = new PassableCell(row, col, color_ground);
delete buf;
} }
Map& Level::mapArray() Map& Level::mapArray()

View File

@ -6,7 +6,7 @@
const std::string default_file_name = "test_map"; const std::string default_file_name = "test_map";
using Row = std::vector<Cell *>; using Row = std::vector<CellPtr>;
using Map = std::vector<Row>; 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