Separate scene rendering from Game class

This commit is contained in:
NaiJi ✨ 2020-03-18 20:45:01 +03:00
parent b0cb76d419
commit 0a226fa083
7 changed files with 187 additions and 118 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,15 +1,5 @@
#include "game.h" #include "game.h"
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/ConvexShape.hpp>
#include <SFML/Graphics/Text.hpp>
constexpr int cell_width = 60;
constexpr int cell_height = 35;
constexpr int cell_deviation = 25;
constexpr int window_side = cell_width * 4;
Game::Game() Game::Game()
{ {
// Place the player with 10 initial charges onto x: 1, y: 1 // Place the player with 10 initial charges onto x: 1, y: 1
@ -18,7 +8,10 @@ Game::Game()
// Generate level // Generate level
level = std::make_unique<Level>(); level = std::make_unique<Level>();
main_window.create(sf::VideoMode(window_side * 3, window_side * 3), "SFML-Test Application", sf::Style::Default); // Prepare level renderer
renderer = std::make_unique<Renderer>();
main_window.create(sf::VideoMode(renderer->windowSize() * 5, renderer->windowSize() * 5), "SFML-Test Application", sf::Style::Default);
main_window.setActive(); main_window.setActive();
main_window.setFramerateLimit(60); main_window.setFramerateLimit(60);
@ -28,7 +21,7 @@ Game::Game()
int Game::run() int Game::run()
{ {
// Initial level rendering // Initial level rendering
renderMap(); renderer->render(level, hero, main_window);
// On the game loop // On the game loop
while (main_window.isOpen()) while (main_window.isOpen())
@ -46,7 +39,7 @@ int Game::run()
onMoving(event.key.code); onMoving(event.key.code);
// Probably something changed! Re-render // Probably something changed! Re-render
renderMap(); renderer->render(level, hero, main_window);
} }
} }
@ -110,101 +103,3 @@ void Game::onMoving(sf::Keyboard::Key &key)
if (!level->mapArray()[attempt_row][attempt_col]->onMovingTo(hero, level)) if (!level->mapArray()[attempt_row][attempt_col]->onMovingTo(hero, level))
hero->setPosition(initial_row, initial_col); hero->setPosition(initial_row, initial_col);
} }
void Game::renderMap()
{
const Map &map = level->mapArray();
float painter_x = 60, painter_y = 60;
float horizontal_shift = 0, vertical_shift = 0;
sf::RectangleShape background_brush({static_cast<float>(main_window.getSize().x), static_cast<float>(main_window.getSize().y)});
background_brush.setFillColor(palette::Black);
background_brush.setPosition(0.f, 0.f);
main_window.draw(background_brush);
// Brush for cell sprites
sf::ConvexShape convex_brush;
convex_brush.setPointCount(4);
convex_brush.setPoint(0, sf::Vector2f(cell_deviation, 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(3, sf::Vector2f(0.f, cell_height));
convex_brush.setFillColor(palette::Blue);
convex_brush.setOutlineThickness(0);
convex_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(palette::White);
text.setCharacterSize(25);
text.setPosition(50, 350);
text.setString("Available bridge cells: " + std::to_string(hero->charges()));
// Where is hero
coordinate hero_row, hero_col;
hero->position(hero_row, hero_col);
// Draw map from 2D array
for (coordinate x = 0; x < level->width(); ++x)
{
horizontal_shift = static_cast<float>(level->width()) * cell_deviation;
for (coordinate y = 0; y < level->height(); ++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());
main_window.draw(convex_brush);
if (hero_row == y && hero_col == x)
{
// Draw the hero sprite
convex_brush.setFillColor(palette::White);
main_window.draw(convex_brush);
}
// Move painter to next cell of current column
painter_y += cell_height;
horizontal_shift -= cell_deviation;
}
// Move painter to next column
painter_y = 60;
painter_x += cell_width;
}
main_window.draw(text);
}

View File

@ -3,12 +3,11 @@
#include <memory> #include <memory>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Time.hpp> #include <SFML/System/Time.hpp>
#include <SFML/Window.hpp>
#include "hero.h" #include "hero.h"
#include "level.h" #include "level.h"
#include "renderer.h"
/// The main class where all the process happens /// The main class where all the process happens
class Game class Game
@ -17,6 +16,7 @@ private:
// Game entities // Game entities
HeroPtr hero; HeroPtr hero;
LevelPtr level; LevelPtr level;
std::unique_ptr<Renderer> renderer;
int current_level; int current_level;
@ -29,9 +29,6 @@ private:
/// Move player by pressed key /// Move player by pressed key
void onMoving(sf::Keyboard::Key &key); void onMoving(sf::Keyboard::Key &key);
/// Render game state
void renderMap();
/// Prepare map and hero for a game level /// Prepare map and hero for a game level
//void loadLevel(int level_index = 1); //void loadLevel(int level_index = 1);

132
src/renderer.cpp Normal file
View File

@ -0,0 +1,132 @@
#include "renderer.h"
#include "level.h"
#include "hero.h"
constexpr unsigned int DEFAULT_CELL_WIDTH = 60;
constexpr unsigned int DEFAULT_CELL_HEIGHT = 35;
constexpr unsigned int DEFAULT_CELL_DEVIATION = 25;
constexpr unsigned int DEFAULT_WINDOW_SIDE = DEFAULT_CELL_WIDTH * 4;
Renderer::Renderer() :
cell_width(DEFAULT_CELL_WIDTH),
cell_height(DEFAULT_CELL_HEIGHT),
cell_deviation(DEFAULT_CELL_DEVIATION),
window_size(DEFAULT_WINDOW_SIDE),
init_painter_x(60),
init_painter_y(60),
vertical_shift(0),
horizontal_shift(0)
{
font.loadFromFile("font/VeraMono.ttf");
text_charges.setFont(font);
text_charges.setFillColor(palette::White);
text_charges.setCharacterSize(25);
brush_background.setFillColor(palette::Black);
brush_background.setPosition(0.f, 0.f);
brush_cell.setPointCount(4);
brush_cell.setPoint(0, sf::Vector2f(cell_deviation, 0.f));
brush_cell.setPoint(1, sf::Vector2f(cell_deviation + cell_width, 0.f));
brush_cell.setPoint(2, sf::Vector2f(cell_width, cell_height));
brush_cell.setPoint(3, sf::Vector2f(0.f, cell_height));
brush_cell.setFillColor(palette::Blue);
brush_cell.setOutlineThickness(0);
brush_wall.setPointCount(6); // Points 0 and 4 should be calculated each iteration of rendering
brush_wall.setPoint(1, sf::Vector2f(cell_deviation + cell_width, 0.f));
brush_wall.setPoint(2, sf::Vector2f(cell_width, cell_height));
brush_wall.setPoint(3, sf::Vector2f(0.f, cell_height));
brush_wall.setPoint(5, sf::Vector2f(cell_width, cell_height));
brush_wall.setOutlineThickness(0);
}
bool Renderer::drawCell(const CellPtr &cell, sf::RenderWindow &main_window)
{
vertical_shift = static_cast<float>(cell->heightShift());
// If cell has any height value, we should draw walls for it
if (vertical_shift > 0)
{
brush_wall.setPoint(0, sf::Vector2f(cell_deviation + cell_width, -vertical_shift));
brush_wall.setPoint(4, sf::Vector2f(0.f, cell_height - vertical_shift));
sf::Color wall_color(sf::Uint8(cell->color().r - 40), sf::Uint8(cell->color().g - 40), sf::Uint8(cell->color().b - 40));
brush_wall.setFillColor(wall_color);
brush_wall.setPosition(painter_x + horizontal_shift, painter_y);
main_window.draw(brush_wall);
}
// Draw the top surface of the cell itself
float final_x = painter_x + horizontal_shift;
float final_y = painter_y - vertical_shift;
brush_cell.setPosition(final_x, final_y);
brush_cell.setFillColor(cell->color());
main_window.draw(brush_cell);
return true;
}
bool Renderer::render(const LevelPtr &level, const HeroPtr &hero, sf::RenderWindow &main_window)
{
if (!hero || !level)
return false;
const Map &map = level->mapArray();
painter_x = init_painter_x;
painter_y = init_painter_y;
horizontal_shift = 0;
vertical_shift = 0;
brush_background.setSize({static_cast<float>(main_window.getSize().x), static_cast<float>(main_window.getSize().y)});
main_window.draw(brush_background);
brush_cell.setPosition(painter_x, painter_y);
// Where is hero
coordinate hero_row, hero_col;
hero->position(hero_row, hero_col);
// Draw map from 2D array
for (coordinate x = 0; x < level->width(); ++x)
{
horizontal_shift = static_cast<float>(level->width()) * cell_deviation;
for (coordinate y = 0; y < level->height(); ++y)
{
drawCell(map[y][x], main_window);
if (hero_row == y && hero_col == x)
{
// Draw the hero sprite
brush_cell.setFillColor(palette::White);
main_window.draw(brush_cell);
}
// Move painter to next cell of current column
painter_y += cell_height;
horizontal_shift -= cell_deviation;
}
// Move painter to next column
painter_y = init_painter_y;
painter_x += cell_width;
}
text_charges.setPosition(50, 350);
text_charges.setString("Available charges left: " + std::to_string(hero->charges()));
main_window.draw(text_charges);
return true;
}
unsigned int Renderer::windowSize() const
{
return window_size;
}

43
src/renderer.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef RENDERER_H
#define RENDERER_H
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/ConvexShape.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Window.hpp>
class Level;
class Cell;
class Hero;
/// Represents functionality to draw game level onto window
class Renderer
{
private:
float cell_width, cell_height, cell_deviation;
unsigned int window_size;
float init_painter_x, init_painter_y;
float painter_x, painter_y;
float vertical_shift, horizontal_shift;
sf::Text text_charges;
sf::Font font;
sf::RectangleShape brush_background;
sf::ConvexShape brush_cell;
sf::ConvexShape brush_wall;
bool drawCell(const std::unique_ptr<Cell> &cell, sf::RenderWindow &main_window);
public:
explicit Renderer();
bool render(const std::unique_ptr<Level> &level, const std::unique_ptr<Hero> &hero, sf::RenderWindow &main_window);
unsigned int windowSize() const;
};
#endif // RENDERER_H

View File

@ -11,14 +11,16 @@ SOURCES += \
game.cpp \ game.cpp \
hero.cpp \ hero.cpp \
level.cpp \ level.cpp \
main.cpp main.cpp \
renderer.cpp
HEADERS += \ HEADERS += \
cell.h \ cell.h \
entity.h \ entity.h \
game.h \ game.h \
hero.h \ hero.h \
level.h level.h \
renderer.h
# Only to highlight syntax when I am on Windows # Only to highlight syntax when I am on Windows
win32:INCLUDEPATH += d:\SFML-2.5.1\include win32:INCLUDEPATH += d:\SFML-2.5.1\include