diff --git a/application.cpp b/application.cpp index f5fbbf1..bc27fbc 100644 --- a/application.cpp +++ b/application.cpp @@ -1,6 +1,7 @@ #include #include "application.h" +// Hardcoded for now constexpr int SCREEN_WIDTH = 1280; constexpr int SCREEN_HEIGHT = 720; const sf::Time TIME_PER_SECOND = sf::seconds(1.f / 60.f); @@ -14,6 +15,7 @@ void Application::run() render_window.setFramerateLimit(60); render_window.display(); + // Main game cycle while (render_window.isOpen()) { processInput(); @@ -29,7 +31,7 @@ void Application::draw() render_window.display(); } -bool Application::processInput() +void Application::processInput() { sf::Event event; while (render_window.pollEvent(event)) @@ -41,11 +43,13 @@ bool Application::processInput() break; case sf::Event::KeyPressed: + // If already won, do nothing if (board.isWinCondition()) - return true; + return; + // Go to selection mode if (event.key.code == sf::Keyboard::Z) board.onSelectionMode(); - else + else // or just move cursor to next tile board.moveSelection(getDirection(event.key.code)); break; @@ -53,8 +57,6 @@ bool Application::processInput() break; } } - - return true; } DIRECTION Application::getDirection(sf::Keyboard::Key &key) const diff --git a/application.h b/application.h index 275c2c8..fc51fdb 100644 --- a/application.h +++ b/application.h @@ -8,11 +8,17 @@ class Application public: explicit Application(); + // Launch game void run(); + + // Refresh render_window to actual state void draw(); - bool processInput(); + + // Handle keyboard commands + void processInput(); private: + // Convert keyboard keys into moving direction DIRECTION getDirection(sf::Keyboard::Key &key) const; Board board; diff --git a/board.cpp b/board.cpp index 909fb32..14205ba 100644 --- a/board.cpp +++ b/board.cpp @@ -13,15 +13,21 @@ Board::Board(int splitting) : if (!global_texture.loadFromFile(picture_dest) ) return; - const float width = global_texture.getSize().x; - const float height = global_texture.getSize().y; + if (splitting <= 1) // If it's 1, the game is already over + { + sf::Sprite* sp = new sf::Sprite(global_texture); + vec_field.push_back(new Cell{0, 0, sp}); + return; + } + + const int width = global_texture.getSize().x; + const int height = global_texture.getSize().y; Cell::side_length = (width < height) ? width / splitting : height / splitting; cells_on_height = height / Cell::side_length; cells_on_width = width / Cell::side_length; vec_field.reserve(cells_on_height * cells_on_width); - vec_ref.reserve(vec_field.size()); /* Iterating board cells' screen positions. * The initial image after this would look exactly like the loaded picture, not shuffled yet. */ @@ -35,10 +41,9 @@ Board::Board(int splitting) : if ((width - y) >= Cell::side_length) { sf::Sprite* sp = new sf::Sprite(global_texture, sf::IntRect(y, x, Cell::side_length, Cell::side_length)); - sp->setPosition(y, x); + sp->setPosition(static_cast(y), static_cast(x)); - vec_field.push_back({index, index, sp}); - vec_ref.push_back(index); + vec_field.push_back(new Cell({index, index, sp})); ++index; } } @@ -48,18 +53,15 @@ Board::Board(int splitting) : // SHUFFLING // srand(static_cast(time(nullptr))); - for (Cells::iterator curr_it = vec_field.begin(); curr_it != vec_field.end(); ++curr_it) + for (Cells::size_type curr_i = 0; curr_i < vec_field.size(); ++curr_i) { - bool success = false; - while (!success) - { - Cells::iterator swap_it = cellByCurrentIndex(rand() & (vec_field.size() - 1)); - if (curr_it->current_index == swap_it->current_index) - continue; + Cells::size_type swap_i; + do + { // find two different tiles + swap_i = rand() & (vec_field.size() - 1); + } while (curr_i == swap_i); - swapCells(curr_it, swap_it); - success = true; - } + swapCells(curr_i, swap_i); } setSelectionVertex(selection_index); @@ -67,14 +69,17 @@ Board::Board(int splitting) : Board::~Board() { - for (Cell& cell : vec_field) - delete cell.sprite; + for (Cell *cell : vec_field) + { + delete cell->sprite; + delete cell; + } } void Board::draw(sf::RenderWindow& window) { - for (const Cell& cell : vec_field) - window.draw(*cell.sprite); + for (const Cell *cell : vec_field) + window.draw(*cell->sprite); window.draw(rect_selection); } @@ -125,7 +130,7 @@ bool Board::moveSelection(const DIRECTION &direction) case DIRECTION::UP: if (selection_index < cells_on_width) // if upper row return false; - swapCells(cellByCurrentIndex(selection_index), cellByCurrentIndex(selection_index - cells_on_width)); + swapCells(selection_index, selection_index - cells_on_width); selection_index -= cells_on_width; setSelectionVertex(selection_index); break; @@ -133,7 +138,7 @@ bool Board::moveSelection(const DIRECTION &direction) case DIRECTION::DOWN: if (selection_index > (cells_on_width * (cells_on_height - 1))) // if bottom row return false; - swapCells(cellByCurrentIndex(selection_index), cellByCurrentIndex(selection_index + cells_on_width)); + swapCells(selection_index, selection_index + cells_on_width); selection_index += cells_on_width; setSelectionVertex(selection_index); break; @@ -141,7 +146,7 @@ bool Board::moveSelection(const DIRECTION &direction) case DIRECTION::RIGHT: if ((selection_index + 1) % cells_on_width == 0) return false; - swapCells(cellByCurrentIndex(selection_index), cellByCurrentIndex(selection_index + 1)); + swapCells(selection_index, selection_index + 1); ++selection_index; setSelectionVertex(selection_index); break; @@ -149,7 +154,7 @@ bool Board::moveSelection(const DIRECTION &direction) case DIRECTION::LEFT: if (((selection_index % cells_on_width == 0) && (selection_index > cells_on_width)) || selection_index == 0) return false; - swapCells(cellByCurrentIndex(selection_index), cellByCurrentIndex(selection_index - 1)); + swapCells(selection_index, selection_index - 1); --selection_index; setSelectionVertex(selection_index); break; @@ -170,7 +175,7 @@ void Board::onSelectionMode() void Board::setSelectionVertex(Cells::size_type index) { - const auto& cell = cellByCurrentIndex(index); + const auto& cell = vec_field[index]; const auto& pos = cell->sprite->getPosition(); const auto& x = pos.x; const auto& y = pos.y; @@ -189,28 +194,27 @@ void Board::setSelectionVertex(Cells::size_type index) rect_selection[4].color = sf::Color::Red; } -void Board::swapCells(Cells::size_type curr_cell_ind, Cells::size_type swap_cell_ind) +void Board::swapCells(Cells::size_type curr_index, Cells::size_type swap_index) { - auto& curr_cell = vec_field[curr_cell_ind]; - auto& swap_cell = vec_field[swap_cell_ind]; - const sf::Vector2f temp_pos = curr_cell.sprite->getPosition(); - const Cells::size_type temp_cell_index = curr_cell.current_index; + Cell *curr_cell = vec_field[curr_index]; + Cell *swap_cell = vec_field[swap_index]; + const sf::Vector2f temp_pos = curr_cell->sprite->getPosition(); + const Cells::size_type temp_cell_index = curr_cell->current_index; - curr_cell.sprite->setPosition(vec_field[swap_cell_ind].sprite->getPosition()); - curr_cell.current_index = vec_field[swap_cell_ind].current_index; + curr_cell->sprite->setPosition(swap_cell->sprite->getPosition()); + curr_cell->current_index = swap_cell->current_index; - swap_cell.sprite->setPosition(temp_pos); - swap_cell.current_index = temp_cell_index; -} + swap_cell->sprite->setPosition(temp_pos); + swap_cell->current_index = temp_cell_index; -Board::Cells::iterator Board::cellByCurrentIndex(Cells::size_type index) -{ - return std::find_if(vec_field.begin(), vec_field.end(), [&](const Cell& cell) { return cell.current_index == index; }); + Cell* temp = vec_field[curr_index]; + vec_field[curr_index] = vec_field[swap_index]; + vec_field[swap_index] = temp; } bool Board::isWinCondition() const { - return std::all_of(vec_field.begin(), vec_field.end(), [](const Cell& cell){ return cell.current_index == cell.inital_index; }); + return std::all_of(vec_field.begin(), vec_field.end(), [](const Cell *cell){ return cell->current_index == cell->inital_index; }); } int Board::Cell::side_length = 0; diff --git a/board.h b/board.h index c74dc32..bef8dde 100644 --- a/board.h +++ b/board.h @@ -18,28 +18,38 @@ enum class DIRECTION NONE }; +////////////////////////////////// + class Board { public: - explicit Board(int splitting = 6); + explicit Board(int splitting = 1); ~Board(); + // Output current graphical state on application window void draw(sf::RenderWindow& window); + + // Move cursor to next tile by given direction bool moveSelection(const DIRECTION& direction); + + // Go to or leave from selection mode void onSelectionMode(); + + // Did player win the game bool isWinCondition() const; private: + // Game tile struct Cell { std::vector::size_type inital_index; std::vector::size_type current_index; sf::Sprite *sprite; - static float side_length; + static int side_length; }; - using Cells = std::vector; + using Cells = std::vector; using RefCells = std::vector; sf::VertexArray rect_selection; @@ -48,11 +58,11 @@ private: Cells::size_type cells_on_width; // amount of cells on horizontal side of board Cells::size_type cells_on_height; // amount of cells on vertical side of board Cells vec_field; - RefCells vec_ref; // map to actual index sf::Texture global_texture; bool on_selection; + void swapCells(Cells::size_type curr_index, Cells::size_type swap_index); + + // Draw selection cursor on given tile void setSelectionVertex(Cells::size_type index); - void swapCells(Cells::size_type curr_cell_ind, Cells::size_type swap_cell_ind); - Cells::iterator cellByCurrentIndex(Cells::size_type index); }; diff --git a/main.cpp b/main.cpp index 0ca2175..20ccd15 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,7 @@ -#include "gamestate.h" +#include "application.h" int main() { - GameState game; + Application game; game.run(); }