#include "game.h" #include #include constexpr int cell_length = 30; constexpr int window_side = cell_length * side; Game::Game() { // Place the player with 10 initial charges onto x: 1, y: 1 hero = std::make_unique(1, 1, 2); // Generate level level = std::make_unique(); main_window.create(sf::VideoMode(window_side, window_side), "SFML-Test Application", sf::Style::Default); main_window.setActive(); current_level = 1; loadLevel(current_level); } int Game::run() { // On the game loop while (main_window.isOpen()) { sf::Event event; while (main_window.pollEvent(event)) { if (event.type == sf::Event::Closed) main_window.close(); // Handling keyboard activity if (event.type == sf::Event::KeyPressed) { // Move onMoving(event.key.code); } } // Draw level renderMap(); main_window.display(); } return EXIT_SUCCESS; } //////////////////////////////////////////////////// Direction Game::getDirection(sf::Keyboard::Key &key) const { switch (key) { case sf::Keyboard::A: case sf::Keyboard::Left: case sf::Keyboard::Num4: return Direction::Left; case sf::Keyboard::W: case sf::Keyboard::Up: case sf::Keyboard::Num8: return Direction::Up; case sf::Keyboard::D: case sf::Keyboard::Right: case sf::Keyboard::Num6: return Direction::Right; case sf::Keyboard::S: case sf::Keyboard::Down: case sf::Keyboard::Num2: return Direction::Down; default: return Direction::None; } } void Game::onMoving(sf::Keyboard::Key &key) { // Determine where to move const Direction direction = getDirection(key); if (direction == Direction::None) return; // Save the initial coordinates coordinate initial_x, initial_y; hero->position(initial_x, initial_y); // Try to move hero hero->move(direction); // Save the new coordinates after moving coordinate attempt_x, attempt_y; hero->position(attempt_x, attempt_y); ////////////////////////// switch (level->cellOfType(attempt_x, attempt_y)) { case CellType::Water: // Try to use one charge to place a bridge if (hero->useCharge()) level->placeBridge(attempt_x, attempt_y); // If hero doesn't have enough charges, we move Hero back else hero->setPosition(initial_x, initial_y); break; case CellType::Charge: // Hero picks up the charge; remove it from the map hero->refillCharges(1); level->removeCharge(attempt_x, attempt_y); break; case CellType::Exit: // Hero exists the level! loadLevel(++current_level); break; case CellType::Wall: // You can't pass through wall. Hero goes back to inital coordinates hero->setPosition(initial_x, initial_y); break; } } void Game::renderMap() { const Map &map = level->mapArray(); coordinate painter_x = 0, painter_y = 0; // Brush for cell sprites sf::RectangleShape rectangle_brush; rectangle_brush.setSize({cell_length, cell_length}); rectangle_brush.setFillColor(sf::Color::Blue); rectangle_brush.setOutlineThickness(0); rectangle_brush.setPosition(painter_x, painter_y); // Counter for available charges sf::Text text; sf::Font font; font.loadFromFile("font/VeraMono.ttf"); text.setFont(font); text.setFillColor(sf::Color::White); text.setCharacterSize(25); text.setPosition(50, 350); text.setString("Available bridge cells: " + std::to_string(hero->charges())); // Draw map from 2D array for (const Row &row : map) { for (const CellType &cell : row) { rectangle_brush.setPosition(painter_y, painter_x); switch (cell) { case CellType::Ground: rectangle_brush.setFillColor(sf::Color(165, 42, 42)); // Brown break; case CellType::Charge: rectangle_brush.setFillColor(sf::Color::Green); break; case CellType::Bridge: rectangle_brush.setFillColor(sf::Color::Black); break; case CellType::Exit: rectangle_brush.setFillColor(sf::Color::Red); break; case CellType::Wall: rectangle_brush.setFillColor(sf::Color(60, 60, 60)); // Gray break; case CellType::Water: default: rectangle_brush.setFillColor(sf::Color::Blue); } main_window.draw(rectangle_brush); // Move painter to next cell of row painter_x += cell_length; } // Move painter to next row of the map painter_x = 0; painter_y += cell_length; } // Where is hero coordinate hero_x, hero_y; hero->position(hero_x, hero_y); // Place the hero sprite rectangle_brush.setFillColor(sf::Color::White); rectangle_brush.setPosition(hero_x * cell_length, hero_y * cell_length); main_window.draw(rectangle_brush); main_window.draw(text); } void Game::loadLevel(int level_index) { Map map; // Fill the level with water for (Row &row : map) { for (CellType &cell : row) cell = CellType::Water; } switch (level_index) { case 1: // Hardcoding is temporary! hero->setPosition(1, 1); hero->setCharges(2); map[0][0] = CellType::Wall; map[0][1] = CellType::Wall; map[1][0] = CellType::Wall; map[1][1] = CellType::Ground; map[1][2] = CellType::Ground; map[1][3] = CellType::Ground; map[1][4] = CellType::Ground; map[2][2] = CellType::Ground; map[3][2] = CellType::Ground; map[3][3] = CellType::Ground; map[3][3] = CellType::Ground; map[6][3] = CellType::Ground; map[6][4] = CellType::Ground; map[6][5] = CellType::Ground; map[6][6] = CellType::Ground; map[7][6] = CellType::Ground; map[9][6] = CellType::Ground; map[8][7] = CellType::Exit; map[2][3] = CellType::Charge; level->setMap(map); break; case 2: // Hardcoding is temporary! hero->setPosition(5, 5); hero->setCharges(10); map[5][6] = CellType::Ground; map[5][5] = CellType::Ground; map[5][4] = CellType::Ground; map[4][5] = CellType::Ground; map[4][6] = CellType::Ground; map[4][4] = CellType::Ground; map[6][6] = CellType::Ground; map[6][5] = CellType::Ground; map[6][4] = CellType::Ground; map[6][7] = CellType::Ground; map[6][8] = CellType::Ground; map[5][8] = CellType::Ground; map[8][8] = CellType::Ground; map[8][9] = CellType::Ground; map[8][10] = CellType::Exit; map[8][11] = CellType::Wall; map[7][11] = CellType::Wall; map[4][3] = CellType::Wall; map[4][7] = CellType::Charge; level->setMap(map); break; default: main_window.close(); } }