You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
5.5 KiB
C++

#include "game.h"
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/Text.hpp>
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<Hero>(1, 1, 2);
// Generate level
level = std::make_unique<Level>();
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);
//////////////////////////
if (!level->mapArray()[attempt_x][attempt_y]->onMovingTo(hero, level))
hero->setPosition(initial_x, initial_y);
if (hero->onExit())
loadLevel(++current_level);
}
void Game::renderMap()
{
const Map &map = level->mapArray();
float 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 std::unique_ptr<Cell> &cell : row)
{
rectangle_brush.setPosition(painter_y, painter_x);
rectangle_brush.setFillColor(cell->color());
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(static_cast<float>(hero_x) * cell_length, static_cast<float>(hero_y) * cell_length);
main_window.draw(rectangle_brush);
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);
switch (level_index)
{
case 1:
// Hardcoding is temporary!
hero->setPosition(1, 1);
hero->setCharges(2);
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);
break;
default:
main_window.close();
}
}