maze-cpp/main.cpp

160 lines
5.2 KiB
C++

#include <SFML/Graphics.hpp>
#include <cmath>
#include "Grid.h"
#include "algorithms/Sidewinder.h"
#include "algorithms/AldousBroder.h"
#include "algorithms/Wilsons.h"
#include "algorithms/HuntAndKill.h"
#include "algorithms/RecursiveBacktracker.h"
#include "algorithms/BinaryTree.h"
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};
}
//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;
};
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 drawGridToTexture(sf::RenderTexture& render_texture, const DistanceGrid& grid, int cell_size) {
auto width = grid.getCols() * cell_size;
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;
auto wall = sf::Color::Black;
auto start = sf::Color::Blue;
auto goal = sf::Color::Red;
render_texture.clear(background);
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);
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);
}
}
render_texture.display();
}
const int CELL_SIZE = 20;
const int WIDTH = 25;
const int HEIGHT = 25;
int main() {
DistanceGrid grid(HEIGHT, WIDTH);
Sidewinder::on(grid);
grid.setStart(grid.randomCell());
sf::RenderWindow window(sf::VideoMode(WIDTH * CELL_SIZE, HEIGHT * CELL_SIZE), "Hello, SFML!");
while ( window.isOpen() &&
!sf::Keyboard::isKeyPressed(sf::Keyboard::Escape) &&
!sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
grid = DistanceGrid(HEIGHT, WIDTH);
Sidewinder::on(grid);
grid.setStart(grid.randomCell());
} else if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
grid = DistanceGrid(HEIGHT, WIDTH);
AldousBroder::on(grid);
grid.setStart(grid.randomCell());
} else if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
grid = DistanceGrid(HEIGHT, WIDTH);
Wilsons::on(grid);
grid.setStart(grid.randomCell());
} else if (sf::Keyboard::isKeyPressed(sf::Keyboard::H)) {
grid = DistanceGrid(HEIGHT, WIDTH);
HuntAndKill::on(grid);
grid.setStart(grid.randomCell());
} else if (sf::Keyboard::isKeyPressed(sf::Keyboard::R)) {
grid = DistanceGrid(HEIGHT, WIDTH);
RecursiveBacktracker::on(grid);
grid.setStart(grid.randomCell());
} else if (sf::Keyboard::isKeyPressed(sf::Keyboard::B)) {
grid = DistanceGrid(HEIGHT, WIDTH);
BinaryTree::on(grid);
grid.setStart(grid.randomCell());
}
window.clear(sf::Color::Blue);
sf::RenderTexture render_texture;
drawGridToTexture(render_texture, grid, CELL_SIZE);
const sf::Texture& texture = render_texture.getTexture();
sf::Sprite sprite(texture);
window.draw(sprite);
window.display();
}
return 0;
}