maze-cpp/demos/SfmlUtils.h
2023-05-03 23:52:33 -04:00

152 lines
5.0 KiB
C++

//Utils to make easy SFML based demos with Maze library
#pragma once
#include "Grid.h"
#include <SFML/Graphics.hpp>
#include <cmath>
namespace utils {
namespace sfml {
//From: https://github.com/SFML/SFML/wiki/Source:-Line-segment-with-thickness
class sfLine : public sf::Drawable
{
public:
sfLine(const sf::Vector2f& point1, const sf::Vector2f& point2, const sf::Color& color = sf::Color::Yellow):
color(color), thickness(5.f)
{
sf::Vector2f direction = point2 - point1;
sf::Vector2f unitDirection = direction/std::sqrt(direction.x*direction.x+direction.y*direction.y);
sf::Vector2f unitPerpendicular(-unitDirection.y,unitDirection.x);
sf::Vector2f offset = (thickness/2.f)*unitPerpendicular;
vertices[0].position = point1 + offset;
vertices[1].position = point2 + offset;
vertices[2].position = point2 - offset;
vertices[3].position = point1 - offset;
for (int i=0; i<4; ++i)
vertices[i].color = color;
}
void draw(sf::RenderTarget &target, sf::RenderStates states) const
{
target.draw(vertices,4,sf::Quads);
}
private:
sf::Vertex vertices[4];
float thickness;
sf::Color color;
};
sf::Color interpolateColors(const sf::Color& c1, const sf::Color& c2, float t) {
auto r = static_cast<sf::Uint8>((1 - t) * c1.r + t * c2.r);
auto g = static_cast<sf::Uint8>((1 - t) * c1.g + t * c2.g);
auto b = static_cast<sf::Uint8>((1 - t) * c1.b + t * c2.b);
return {r, g, b};
}
void lineTo(sf::RenderTexture& render_texture, int x1, int y1, int x2, int y2, const sf::Color& color) {
sfLine line(sf::Vector2f(x1, y1), sf::Vector2f(x2, y2), color);
render_texture.draw(line);
}
void drawGridLinesToTexture(sf::RenderTexture& render_texture, const Grid& grid, int cell_size) {
const auto wall = sf::Color::Black;
for (auto& cell : grid) {
auto x1 = cell.getCol() * cell_size;
auto y1 = cell.getRow() * cell_size;
auto x2 = (cell.getCol() + 1) * cell_size;
auto y2 = (cell.getRow() + 1) * cell_size;
if (!cell.hasNorth()) {
lineTo(render_texture, x1, y1, x2, y1, wall);
}
if (!cell.hasWest()) {
lineTo(render_texture, x1, y1, x1, y2, wall);
}
if (!cell.isLinked(cell.east)) {
lineTo(render_texture, x2, y1, x2, y2, wall);
}
if (!cell.isLinked(cell.south)) {
lineTo(render_texture, x1, y2, x2, y2, wall);
}
}
}
void drawDistanceGridBackgroundsToTexture(sf::RenderTexture& render_texture, const DistanceGrid& grid, int cell_size) {
const auto start = sf::Color::Blue;
const auto goal = sf::Color::Red;
for (auto& cell : grid) {
auto x1 = cell.getCol() * cell_size;
auto y1 = cell.getRow() * cell_size;
auto x2 = (cell.getCol() + 1) * cell_size;
auto y2 = (cell.getRow() + 1) * cell_size;
sf::Color color = interpolateColors(start, goal, grid.intensityAt(cell));
sf::RectangleShape rectangle(sf::Vector2f(cell_size, cell_size));
rectangle.setPosition(x1, y1);
rectangle.setFillColor(color);
render_texture.draw(rectangle);
}
}
void drawMaskedGridBackgroundsToTexture(sf::RenderTexture& render_texture, const MaskedGrid& grid, int cell_size) {
const auto disabled = sf::Color::Black;
for (auto& cell : grid) {
if (!grid.isCellEnabled(cell)) {
auto x1 = cell.getCol() * cell_size;
auto y1 = cell.getRow() * cell_size;
sf::RectangleShape rectangle(sf::Vector2f(cell_size, cell_size));
rectangle.setPosition(x1, y1);
rectangle.setFillColor(disabled);
render_texture.draw(rectangle);
}
}
}
void drawGridToTexture(sf::RenderTexture& render_texture, const MaskedGrid& grid, int cell_size) {
const auto width = grid.getCols() * cell_size;
const auto height = grid.getRows() * cell_size;
if (!render_texture.create(width, height)) {
throw std::runtime_error("Failed to create render texture");
}
auto background = sf::Color::White;
render_texture.clear(background);
drawGridLinesToTexture(render_texture, grid, cell_size);
drawMaskedGridBackgroundsToTexture(render_texture, grid, cell_size);
render_texture.display();
}
void drawGridToTexture(sf::RenderTexture& render_texture, const DistanceGrid& grid, int cell_size) {
const auto width = grid.getCols() * cell_size;
const auto height = grid.getRows() * cell_size;
if (!render_texture.create(width, height)) {
throw std::runtime_error("Failed to create render texture");
}
auto background = sf::Color::White;
render_texture.clear(background);
drawDistanceGridBackgroundsToTexture(render_texture, grid, cell_size);
drawGridLinesToTexture(render_texture, grid, cell_size);
render_texture.display();
}
void drawGridToTexture(sf::RenderTexture& render_texture, const Grid& grid, int cell_size) {
const auto width = grid.getCols() * cell_size;
const auto height = grid.getRows() * cell_size;
if (!render_texture.create(width, height)) {
throw std::runtime_error("Failed to create render texture");
}
auto background = sf::Color::White;
render_texture.clear(background);
drawGridLinesToTexture(render_texture, grid, cell_size);
render_texture.display();
}
}
}