Skip to content

Instantly share code, notes, and snippets.

@MORTAL2000
Last active July 16, 2016 02:21
Show Gist options
  • Save MORTAL2000/896ea24c907923f9a578fa2fa9296a8c to your computer and use it in GitHub Desktop.
Save MORTAL2000/896ea24c907923f9a578fa2fa9296a8c to your computer and use it in GitHub Desktop.
#include <SFML/Graphics.hpp>
#include <iostream>
#include <iomanip>
#include <array>
#include <vector>
#include <utility>
#include <queue>
#include <tuple>
#include <set>
#include <algorithm>
#include <random>
#include <cassert>
namespace sf
{
template <typename T>
inline bool operator < (const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x < right.x) || ((left.x == right.x) && (left.y < right.y));
}
template <typename T>
inline bool operator > (const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x > right.x) || ((left.x == right.x) && (left.y > right.y));
}
template <typename T>
inline Vector2<T> operator / (const Vector2<T>& left, const Vector2<T>& right)
{
if (right.x == 0 || right.y == 0 ) return left;
T x = left.x / right.x;
T y = left.y / right.y;
return {x, y};
}
template <typename T, typename U>
inline Vector2<T>& operator +=(Vector2<T>& left, const Vector2<U>& right)
{
left.x += right.x;
left.y += right.y;
return left;
}
template <typename T, typename U>
inline Vector2<T>& operator -=(Vector2<T>& left, const Vector2<U>& right)
{
left.x -= right.x;
left.y -= right.y;
return left;
}
template <typename T, typename U>
inline Vector2<T> operator +(const Vector2<T>& left, const Vector2<U>& right)
{
return Vector2<T>(left.x + right.x, left.y + right.y);
}
template <typename T, typename U>
inline Vector2<T> operator +(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x + right, left.y + right);
}
template <typename T, typename U>
inline Vector2<T> operator -(const Vector2<T>& left, const Vector2<U>& right)
{
return Vector2<T>(left.x - right.x, left.y - right.y);
}
template <typename T, typename U>
inline Vector2<T> operator -(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x - right, left.y - right);
}
template <typename T, typename U>
inline Vector2<T> operator *(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x * right, left.y * right);
}
template <typename T, typename U>
inline Vector2<T> operator *(T left, const Vector2<U>& right)
{
return Vector2<T>(right.x * left, right.y * left);
}
template <typename T, typename U>
inline Vector2<T>& operator *=(Vector2<T>& left, U right)
{
left.x *= right;
left.y *= right;
return left;
}
template <typename T, typename U>
inline Vector2<T> operator /(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x / right, left.y / right);
}
template <typename T, typename U>
inline Vector2<T>& operator /=(Vector2<T>& left, U right)
{
left.x /= right;
left.y /= right;
return left;
}
}
template <typename T>
std::ostream& operator<<(std::ostream& out, sf::Vector2<T> v)
{
out << '(' << v.x << ',' << v.y <<')';
return out;
}
std::ostream& operator<<(std::ostream& out, sf::Color c)
{
out << '(' << (int)c.r << ',' << (int)c.b << ',' << (int)c.g<< ')';
return out;
}
std::vector<sf::Vertex>
make_outLines(unsigned width, unsigned height, float size,
const sf::Color& color=sf::Color{139,137,137})
{
std::vector<sf::Vertex> vertices((width + height + 2) * 2);
static const auto e = 0.001f;
// make vertical lines
for (unsigned i = 0; i <= width; ++i) {
const auto& line = &vertices[i * 2];
line[0].position = {((i==0) ? i+e : i) * size, 0};
line[1].position = {((i==0) ? i+e : i) * size, height * size};
line[0].color = line[1].color = color;
}
// make horizontal lines
for (unsigned i = 0; i <= height; ++i) {
const auto& line = &vertices[(i + width + 1) * 2];
line[0].position = {0, ((i==height) ? i-e : i) * size};
line[1].position = {width * size, ((i==height) ? i-e : i) * size};
line[0].color = line[1].color = color;
}
return vertices;
}
//std::vector<int> make_grid(unsigned cols, unsigned rows)
//{
//
// unsigned RCvertices=2*cols*(rows-1);
// unsigned TSvertices=2*cols*(rows-1)+2*(rows-2);
// unsigned numVertices=TSvertices;
// std::vector<int> trianglestrip(numVertices);
// unsigned j=0;
// for(unsigned i = 1; i <= RCvertices; i += 2)
// {
// trianglestrip[ j ] = (1 +i)/2;
// trianglestrip[ j +1 ] = (cols*2 + i + 1) / 2;
// if( trianglestrip[ j +1 ] % cols == 0)
// {
// if( trianglestrip[ j +1 ] != cols && trianglestrip[ j +1 ] != cols*rows )
// {
// trianglestrip[ j +2 ] = trianglestrip[ j +1 ];
// trianglestrip[ j +3 ] = (1 + i + 2) / 2;
// j += 2;
// }
// }
// j += 2;
// }
// return trianglestrip;
//}
class Grid final : public sf::Drawable, public sf::Transformable
{
class Cell
{
public:
explicit Cell(const sf::Vector2i& offset,float size, const sf::Color& color)
{
// quad[0].position = { coord.x * size, coord.y * size};
//
// quad[1].position = { coord.x * size, (coord.y + 1) * size};
// quad[2].position = {(coord.x + 1) * size, coord.y * size};
//
//// quad[3].position = { coord.x * size, (coord.y + 1) * size};
//// quad[4].position = {(coord.x + 1) * size, coord.y * size};
//
//// quad[3].position = { (coord.x + 1) * size, (coord.y ) * size};
//// quad[4].position = {(coord.x ) * size, (coord.y + 1) * size};
//
// quad[3].position = {(coord.x + 1) * size, (coord.y + 1) * size};
//
// //for (auto& v : quad) { v.color = color;}
// quad[0].color = quad[3].color = sf::Color::Blue;
// quad[1].color = sf::Color::Green;
// quad[2].color = sf::Color::Red;
// Stip
// quad[0] = {{ coord.x * size, coord.y * size}, sf::Color::Blue};
//
// quad[1] = {{ coord.x * size, (coord.y + 1) * size}, sf::Color::Green};
// quad[2] = {{(coord.x + 1) * size, coord.y * size}, sf::Color::Red};
//
//// quad[3] = {{ coord.x * size, (coord.y + 1) * size}, sf::Color::Green};
//// quad[4] = {{(coord.x + 1) * size, coord.y * size}, sf::Color::Red};
// quad[3] = {{(coord.x + 1) * size, (coord.y + 1) * size}, sf::Color::Blue};
// // fan
// quad[0] = {sf::Vector2f{(offset.x + 1) * 0.5f, (offset.y + 1) * 0.5f} * size, sf::Color::Black}; // center for all
//
// quad[1] = {sf::Vector2f{ offset.x, offset.y } * size, sf::Color::Green};
// quad[2] = {sf::Vector2f{(offset.x + 1), offset.y } * size, sf::Color::Red};
//
// quad[3] = {sf::Vector2f{(offset.x + 1), offset.y } * size, sf::Color::Green};
// quad[4] = {sf::Vector2f{(offset.x + 1), (offset.y + 1) } * size, sf::Color::Red};
//
// quad[5] = {sf::Vector2f{(offset.x + 1), (offset.y + 1) } * size, sf::Color::Green};
// quad[6] = {sf::Vector2f{ offset.x, (offset.y + 1) } * size, sf::Color::Red};
//
// quad[7] = {sf::Vector2f{ offset.x, offset.y } * size, sf::Color::Green};
// quad[8] = {sf::Vector2f{ offset.x, (offset.y + 1) } * size, sf::Color::Red};
// Triangles
quad[0] = {sf::Vector2f( offset.x, offset.y ) * size, sf::Color::Blue};
quad[1] = {sf::Vector2f((offset.x + 1), offset.y ) * size, sf::Color::Green};
quad[2] = {sf::Vector2f( offset.x, (offset.y + 1)) * size, sf::Color::Red};
quad[3] = {sf::Vector2f((offset.x + 1), offset.y ) * size, sf::Color::Blue};
quad[4] = {sf::Vector2f((offset.x + 1), (offset.y + 1)) * size, sf::Color::Green};
quad[5] = {sf::Vector2f( offset.x, (offset.y + 1)) * size, sf::Color::Red};
}
void setFillColor(const sf::Color& color) const
{
for (auto& v : quad) { v.color = color;}
}
const sf::Color& getFillColor() const
{
return quad[0].color;
}
sf::Vector2i getPosition() const
{
return static_cast<const sf::Vector2i>(quad[0].position);
}
const sf::Vertex* data() const
{
return quad.data();
}
unsigned size() const
{
return quad.size();
}
friend std::ostream& operator<<(std::ostream& out, Cell c)
{
out << " "
<< c.quad[0].position << "\n " << c.quad[1].position << " "
<< c.quad[2].position << "\n "
// << c.quad[3].position << ' '
// << c.quad[4].position << "\n"
<< c.quad[3].position << "\n "
<< c.quad[0].color << ' ' << c.quad[1].color << "\n "
<< c.quad[3].color << ' ' << c.quad[2].color << "\n";
return out;
}
private:
mutable std::array<sf::Vertex, 6> quad;
};
public:
explicit Grid(int width, int height, float tile_size, const sf::Color& color)
: grid{}
, outlines{make_outLines((int)std::floor(width/tile_size), (int)std::floor(height/tile_size), tile_size)}
{
const auto numOfCellPerRow = (int)std::floor(width/tile_size);
const auto numberOfCelles = numOfCellPerRow * (int)std::floor(height/tile_size);
grid.reserve(numberOfCelles);
for (int i = 0; i < numberOfCelles; ++i)
{
sf::Vector2i offset((int)std::floor(i % numOfCellPerRow), (int)std::floor(i / numOfCellPerRow));
grid.emplace_back(offset, tile_size, color);
}
}
Cell& operator[](unsigned index) {return grid[index];}
const Cell& operator[](unsigned index) const {return grid[index];}
std::vector<Cell>::iterator begin() {return grid.begin();}
std::vector<Cell>::iterator end() {return grid.end();}
private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
// const auto& transform = getTransform();
// states.transform *= transform;
static const auto grid_size = grid[0].size()*grid.size();
static const auto outlines_size = outlines.size();
static const auto& outlines_cache = outlines.data();
target.draw(grid[0].data(), grid_size, sf::Triangles, states);
target.draw(outlines_cache, outlines_size, sf::Lines, states);
}
private:
std::vector<Cell> grid;
std::vector<sf::Vertex> outlines;
};
void pollEvent(sf::RenderWindow& window)
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
}
int main()
{
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
int numOfCellPerRow = 6;
int tile_size = window.getSize().x/numOfCellPerRow;
//sf::View view = window.getDefaultView();
//view.zoom(2.f);
//window.setView(view);
//int tile_size = window.getSize().x/4;
// Quads
std::vector<sf::Vertex> quad{
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Yellow}},
};
// Triangles
std::vector<sf::Vertex> triangles{
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Red}},
};
// Triangles Fan
std::vector<sf::Vertex> triangles_fan{
{sf::Vector2f{0.5f, 0.5f} * tile_size, {sf::Color::Black}}, // center for all
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Red}},
};
//Triangles Strip
std::vector<sf::Vertex> triangles_strip{
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Green}}, // shared vertices
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
// {sf::Vector2f{0, 1} * tile_size, {sf::Color::Green}},
// {sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Blue}},
};
std::vector<sf::Vertex> triangles_strip_full{
// top-left
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Blue}},
// bottom-left
{sf::Vector2f{0, 0+1} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0, 1+1} * tile_size, {sf::Color::Green}}, // shared vertices
{sf::Vector2f{1, 0+1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0, 1+1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 0+1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 1+1} * tile_size, {sf::Color::Blue}},
// top-right
{sf::Vector2f{0+1, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0+1, 1} * tile_size, {sf::Color::Green}}, // shared vertices
{sf::Vector2f{1+1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0+1, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1+1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1+1, 1} * tile_size, {sf::Color::Blue}},
// bottom-right
{sf::Vector2f{0+1, 0+1} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0+1, 1+1} * tile_size, {sf::Color::Green}}, // shared vertices
{sf::Vector2f{1+1, 0+1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0+1, 1+1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1+1, 0+1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1+1, 1+1} * tile_size, {sf::Color::Blue}},
};
Grid grid(window.getSize().x, window.getSize().y, tile_size, sf::Color::Blue);
for(auto i : grid) std::cout << i << '\n';
sf::Vector2f coord{1,1};
grid[coord.y + (window.getSize().y/tile_size) * coord.x].setFillColor(sf::Color::Yellow);
while (window.isOpen())
{
pollEvent(window);
window.clear();
// window.draw(quad.data(), quad.size(), sf::Quads);
// window.draw(triangles.data(), triangles.size(), sf::Triangles);
// window.draw(triangles_fan.data(), triangles_fan.size(), sf::TrianglesFan);
//window.draw(triangles_strip.data(), triangles_strip.size(), sf::TrianglesStrip);
//window.draw(triangles_strip_full.data(), triangles_strip_full.size(), sf::TrianglesStrip);
window.draw(grid);
window.display();
}
try{
// MapEditor editor;
// editor.run();
} catch (std::runtime_error& e)
{
std::cout << "Exception: " << e.what() << '\n';
return 1;
} catch (std::out_of_range& e)
{
std::cout << "Exception: " << e.what() << '\n';
return 1;
} catch (...)
{
std::cout << "Unknown Exception!\n";
return 1;
}
}
#include <SFML/Graphics.hpp>
#include <iostream>
#include <iomanip>
#include <array>
#include <vector>
#include <utility>
#include <queue>
#include <tuple>
#include <set>
#include <algorithm>
#include <random>
#include <cassert>
namespace sf
{
template <typename T>
inline bool operator < (const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x < right.x) || ((left.x == right.x) && (left.y < right.y));
}
template <typename T>
inline bool operator > (const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x > right.x) || ((left.x == right.x) && (left.y > right.y));
}
template <typename T>
inline Vector2<T> operator / (const Vector2<T>& left, const Vector2<T>& right)
{
if (right.x == 0 || right.y == 0 ) return left;
T x = left.x / right.x;
T y = left.y / right.y;
return {x, y};
}
template <typename T, typename U>
inline Vector2<T>& operator +=(Vector2<T>& left, const Vector2<U>& right)
{
left.x += right.x;
left.y += right.y;
return left;
}
template <typename T, typename U>
inline Vector2<T>& operator -=(Vector2<T>& left, const Vector2<U>& right)
{
left.x -= right.x;
left.y -= right.y;
return left;
}
template <typename T, typename U>
inline Vector2<T> operator +(const Vector2<T>& left, const Vector2<U>& right)
{
return Vector2<T>(left.x + right.x, left.y + right.y);
}
template <typename T, typename U>
inline Vector2<T> operator -(const Vector2<T>& left, const Vector2<U>& right)
{
return Vector2<T>(left.x - right.x, left.y - right.y);
}
template <typename T, typename U>
inline Vector2<T> operator +(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x + right, left.y + right);
}
template <typename T, typename U>
inline Vector2<T> operator -(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x - right, left.y - right);
}
template <typename T, typename U>
inline Vector2<T> operator *(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x * right, left.y * right);
}
template <typename T, typename U>
inline Vector2<T>& operator *=(Vector2<T>& left, U right)
{
left.x *= right;
left.y *= right;
return left;
}
template <typename T, typename U>
inline Vector2<T> operator /(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x / right, left.y / right);
}
template <typename T, typename U>
inline Vector2<T>& operator /=(Vector2<T>& left, U right)
{
left.x /= right;
left.y /= right;
return left;
}
}
template <typename T>
std::ostream& operator<<(std::ostream& out, sf::Vector2<T> v)
{
out << '(' << v.x << ',' << v.y <<')';
return out;
}
std::ostream& operator<<(std::ostream& out, sf::Color c)
{
out << '(' << (int)c.r << ',' << (int)c.b << ',' << (int)c.g<< ')';
return out;
}
std::vector<sf::Vertex>
make_outLines(unsigned width, unsigned height, float size,
const sf::Color& color=sf::Color{139,137,137})
{
std::vector<sf::Vertex> vertices((width + height + 2) * 2);
static const auto e = 0.001f;
// make vertical lines
for (unsigned i = 0; i <= width; ++i) {
const auto& line = &vertices[i * 2];
line[0].position = {((i==0) ? i+e : i) * size, 0};
line[1].position = {((i==0) ? i+e : i) * size, height * size};
line[0].color = line[1].color = color;
}
// make horizontal lines
for (unsigned i = 0; i <= height; ++i) {
const auto& line = &vertices[(i + width + 1) * 2];
line[0].position = {0, ((i==height) ? i-e : i) * size};
line[1].position = {width * size, ((i==height) ? i-e : i) * size};
line[0].color = line[1].color = color;
}
return vertices;
}
//std::vector<int> make_grid(unsigned cols, unsigned rows)
//{
//
// unsigned RCvertices=2*cols*(rows-1);
// unsigned TSvertices=2*cols*(rows-1)+2*(rows-2);
// unsigned numVertices=TSvertices;
// std::vector<int> trianglestrip(numVertices);
// unsigned j=0;
// for(unsigned i = 1; i <= RCvertices; i += 2)
// {
// trianglestrip[ j ] = (1 +i)/2;
// trianglestrip[ j +1 ] = (cols*2 + i + 1) / 2;
// if( trianglestrip[ j +1 ] % cols == 0)
// {
// if( trianglestrip[ j +1 ] != cols && trianglestrip[ j +1 ] != cols*rows )
// {
// trianglestrip[ j +2 ] = trianglestrip[ j +1 ];
// trianglestrip[ j +3 ] = (1 + i + 2) / 2;
// j += 2;
// }
// }
// j += 2;
// }
// return trianglestrip;
//}
class Grid final : public sf::Drawable
{
class Cell
{
public:
explicit Cell(const sf::Vector2i& offset, float size, const sf::Color& color)
{
quad[0] = {sf::Vector2f( offset.x, offset.y ) * size, color};
quad[1] = {sf::Vector2f((offset.x + 1), offset.y ) * size, color};
quad[2] = {sf::Vector2f( offset.x, (offset.y + 1)) * size, color};
quad[3] = {sf::Vector2f((offset.x + 1), offset.y ) * size, color};
quad[4] = {sf::Vector2f((offset.x + 1), (offset.y + 1)) * size, color};
quad[5] = {sf::Vector2f( offset.x, (offset.y + 1)) * size, color};
}
void setFillColor(const sf::Color& color) const
{
for (auto& v : quad) { v.color = color;}
}
const sf::Color& getFillColor() const
{
return quad[0].color;
}
sf::Vector2i getPosition() const
{
return static_cast<const sf::Vector2i>(quad[0].position);
}
const sf::Vertex* data() const
{
return quad.data();
}
unsigned size() const
{
return quad.size();
}
friend std::ostream& operator<<(std::ostream& out, Cell c)
{
out << " "
<< c.quad[0].position << " " << c.quad[1].position << " "
<< c.quad[3].position << "\n "
<< c.quad[2].position << " " << c.quad[4].position << " "
<< c.quad[3].position << "\n "
<< "\n "
<< c.quad[0].color << " " << c.quad[1].color << " "
<< c.quad[3].color << "\n "
<< c.quad[2].color << " " << c.quad[4].color << " "
<< c.quad[3].color << "\n";
return out;
}
private:
mutable std::array<sf::Vertex, 6> quad;
};
public:
explicit Grid(int width, int height, float tile_size, const sf::Color& color)
: grid{}
, outlines{make_outLines(width, height, tile_size)}
{
const auto numberOfCelles = width * height;
grid.reserve(numberOfCelles);
for (int i = 0; i < numberOfCelles; ++i)
{
sf::Vector2i offset(i % width, i / width);
grid.emplace_back(offset, tile_size, color);
}
}
Cell& operator[](unsigned index) {return grid[index];}
const Cell& operator[](unsigned index) const {return grid[index];}
std::vector<Cell>::iterator begin() {return grid.begin();}
std::vector<Cell>::iterator end() {return grid.end();}
private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
static const auto grid_size = grid[0].size()*grid.size();
static const auto outlines_size = outlines.size();
static const auto& outlines_cache = outlines.data();
target.draw(grid[0].data(), grid_size, sf::Triangles, states);
target.draw(outlines_cache, outlines_size, sf::Lines, states);
}
private:
std::vector<Cell> grid;
std::vector<sf::Vertex> outlines;
};
void pollEvent(sf::RenderWindow& window)
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
}
Grid make_grid(sf::Vector2u windowSize, float numOfCellPerRow)
{
float tileSize = windowSize.x/numOfCellPerRow;
Grid grid(numOfCellPerRow, numOfCellPerRow, tileSize, sf::Color::Blue);
return grid;
}
int main()
{
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
float numOfCellPerRow = 6;
float tile_size = window.getSize().x/numOfCellPerRow;
//sf::View view = window.getDefaultView();
//view.zoom(2.f);
//window.setView(view);
//int tile_size = window.getSize().x/4;
// Quads
std::vector<sf::Vertex> quad{
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Yellow}},
};
// Triangles
std::vector<sf::Vertex> triangles{
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Red}},
};
// Triangles Fan
std::vector<sf::Vertex> triangles_fan{
{sf::Vector2f{0.5f, 0.5f} * tile_size, {sf::Color::Black}}, // center for all
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Green}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Red}},
};
//Triangles Strip
std::vector<sf::Vertex> triangles_strip{
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Green}}, // shared vertices
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
// {sf::Vector2f{0, 1} * tile_size, {sf::Color::Green}},
// {sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Blue}},
};
std::vector<sf::Vertex> triangles_strip_full{
// top-left
{sf::Vector2f{0, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 1} * tile_size, {sf::Color::Blue}},
// bottom-left
{sf::Vector2f{0, 0+1} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0, 1+1} * tile_size, {sf::Color::Green}}, // shared vertices
{sf::Vector2f{1, 0+1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0, 1+1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1, 0+1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1, 1+1} * tile_size, {sf::Color::Blue}},
// top-right
{sf::Vector2f{0+1, 0} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0+1, 1} * tile_size, {sf::Color::Green}}, // shared vertices
{sf::Vector2f{1+1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0+1, 1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1+1, 0} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1+1, 1} * tile_size, {sf::Color::Blue}},
// bottom-right
{sf::Vector2f{0+1, 0+1} * tile_size, {sf::Color::Blue}},
{sf::Vector2f{0+1, 1+1} * tile_size, {sf::Color::Green}}, // shared vertices
{sf::Vector2f{1+1, 0+1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{0+1, 1+1} * tile_size, {sf::Color::Green}},
{sf::Vector2f{1+1, 0+1} * tile_size, {sf::Color::Red}},
{sf::Vector2f{1+1, 1+1} * tile_size, {sf::Color::Blue}},
};
Grid grid = make_grid(window.getSize(),6);
sf::Vector2i coord{1, 1};
std::cout << grid[coord.x + 5 * coord.y] ;
grid[coord.x + 6 * coord.y].setFillColor(sf::Color::Yellow);
while (window.isOpen())
{
pollEvent(window);
window.clear();
// window.draw(quad.data(), quad.size(), sf::Quads);
// window.draw(triangles.data(), triangles.size(), sf::Triangles);
// window.draw(triangles_fan.data(), triangles_fan.size(), sf::TrianglesFan);
//window.draw(triangles_strip.data(), triangles_strip.size(), sf::TrianglesStrip);
//window.draw(triangles_strip_full.data(), triangles_strip_full.size(), sf::TrianglesStrip);
window.draw(grid);
window.display();
}
try{
// MapEditor editor;
// editor.run();
} catch (std::runtime_error& e)
{
std::cout << "Exception: " << e.what() << '\n';
return 1;
} catch (std::out_of_range& e)
{
std::cout << "Exception: " << e.what() << '\n';
return 1;
} catch (...)
{
std::cout << "Unknown Exception!\n";
return 1;
}
}
// hex
#include <iostream>
#include <vector>
#include <SFML/Graphics.hpp>
bool isMouseContainsHexagaon(sf::CircleShape& cell, sf::Vector2f passed_mousePos, std::vector<sf::Vector2f>& points)
{
points.clear();
bool is_contain = false;
const auto& transform = cell.getTransform();
for (unsigned i = 0; i < cell.getPointCount(); ++i){
points.emplace_back(transform.transformPoint(cell.getPoint(i)));
}
for (unsigned i = 0; i < points.size(); i++)
{
unsigned j = ((i + points.size() - 1)%points.size());
//std::cout << i << ' ' << j << ' ' << ((i + points.size() -1)%points.size())<< '\n';//getchar();
bool b1 = (points[i].y > passed_mousePos.y);
bool b2 = (points[j].y > passed_mousePos.y);
float vX = (points[j].x - points[i].x);
float vY = (points[j].y - points[i].y);
float ratio = (vX / vY);
float vmx = (passed_mousePos.x - points[i].x);
float vmy =(passed_mousePos.y - points[i].y) * ratio;
if (b1 != b2 && (vmx > vmy)) {
is_contain = !is_contain;
}
}
return is_contain;
}
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "Hexgrid Example");
sf::CircleShape hexagon;
hexagon.setRadius(window.getSize().x / 16.f);
hexagon.setPointCount(6);
hexagon.setFillColor(sf::Color(150, 50, 250));
hexagon.setOutlineThickness(2);
hexagon.setOutlineColor(sf::Color(250, 150, 100));
hexagon.setOrigin(hexagon.getGlobalBounds().width / 2.f, hexagon.getGlobalBounds().height / 2.f);
std::vector<sf::CircleShape> grid;
std::vector<sf::Vector2f> points;
points.reserve(6);
float xpos = 0, ypos = 0;
for (int y = 0; y < 12; y++)
{
if (y == 0)
{
ypos = y * hexagon.getGlobalBounds().height;
}
else
{
ypos = ypos + (hexagon.getGlobalBounds().height - (hexagon.getGlobalBounds().height * 0.25f));
}
for (int x = 0; x < 12; x++)
{
if (y % 2 == 0)
{
xpos = x * hexagon.getGlobalBounds().width;
}
else
{
xpos = (x * hexagon.getGlobalBounds().width) + (hexagon.getGlobalBounds().width * 0.5f);
}
hexagon.setPosition(xpos, ypos);
grid.push_back(hexagon);
}
}
while (window.isOpen())
{
sf::Event e;
while (window.pollEvent(e))
{
if (e.type == sf::Event::Closed)
{
window.close();
}
if (e.type == sf::Event::MouseMoved)
{
std::cout << e.mouseMove.x << ' ' << e.mouseMove.y << '\n';
for (auto& c : grid)
{
if (isMouseContainsHexagaon(c, sf::Vector2f(e.mouseMove.x, e.mouseMove.y), points))
{
c.setFillColor(sf::Color(255, 255, 255));
}
else
{
c.setFillColor(sf::Color(150, 50, 250));
}
}
}
}
// const auto& position = sf::Mouse::getPosition(window);
// const auto& cov = window.mapPixelToCoords(position);
// grid.chkHexGridWithMousePos(sf::Vector2f(position));
//
// for (auto& c : grid)
// {
// if (isMouseContainsHexagaon(c, sf::Vector2f(e.mouseMove.x, e.mouseMove.y), points))
// {
// c.setFillColor(sf::Color(255, 255, 255));
// }
// else
// {
// c.setFillColor(sf::Color(150, 50, 250));
// }
// }
window.clear();
for (auto c : grid)
{
window.draw(c);
}
window.display();
}
}
#include <SFML/Graphics.hpp>
#include <iostream>
#include <array>
#include <vector>
#include <utility>
#include <queue>
#include <tuple>
#include <set>
#include <algorithm>
#include <random>
namespace sf
{
template <typename T>
inline bool operator < (const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x < right.x) || ((left.x == right.x) && (left.y < right.y));
}
template <typename T>
inline bool operator > (const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x > right.x) || ((left.x == right.x) && (left.y > right.y));
}
template <typename T, typename U>
inline Vector2<T> operator /(const Vector2<T>& left, U right)
{
return Vector2<T>(left.x / right, left.y / right);
}
}
template <typename T>
inline double manhattan(const T& a, const T& b)
{
const auto dx = std::abs(a.x - b.x);
const auto dy = std::abs(a.y - b.y);
return (dx + dy);
}
template <typename T>
inline double euclidean(const T& a, const T& b)
{
const auto dx = std::abs(a.x - b.x);
const auto dy = std::abs(a.y - b.y);
return std::sqrt(dx * dx + dy * dy);
}
template <typename T>
inline double chebyshev(const T& a, const T& b)
{
const auto dx = std::abs(a.x - b.x);
const auto dy = std::abs(a.y - b.y);
return std::max(dx, dy);
}
template <typename N>
class Graph
{
class Node;
using NodeHolder = std::set<Node>;
public:
using NodeVal = N;
using NodeRef = typename NodeHolder::iterator;
using Edges = std::vector<std::tuple<NodeRef, double, double>>;
public:
void addNode(const N& data) const
{
nodes.emplace(data);
}
const NodeRef getRef(const N& data) const
{
const auto& found = nodes.find(data);
if (found == nodes.end())
throw std::runtime_error("Graph::getRef: Key not found!\n");
return found;
}
void addEdge(const NodeRef src, const NodeRef dst, double cost) const
{
if (src != nodes.end() && dst != nodes.end())
src->addEdge(dst, cost);
}
void clear()
{
nodes.clear();
}
private:
class Node
{
using EdgesRef = typename Edges::iterator;
N data;
mutable Edges edges;
public:
Node(const N& data) : data{data}, edges{} {}
void addEdge(const NodeRef e, double f, double g=0.0) const
{
edges.emplace_back(e, f, g);
edges.shrink_to_fit();
}
const NodeVal& value() const
{
return data;
}
const EdgesRef begin() const {return edges.begin();}
const EdgesRef end() const {return edges.end();}
friend bool operator < (const Node& lhs, const Node& rhs)
{
return lhs.data < rhs.data;
}
};
private:
mutable NodeHolder nodes;
};
sf::Vector2f twoDToIso(const sf::Vector2f& coord)
{
return {coord.x - coord.y, (coord.x + coord.y) / 2};
}
sf::Vector2i isoTo2D(const sf::Vector2f& coord)
{
return sf::Vector2i((2 * coord.y + coord.x) / 2, (2 * coord.y - coord.x) / 2);
}
std::vector<sf::Vertex>
make_outLines(unsigned width, unsigned height, float size,
const sf::Color& color=sf::Color{139,137,137})
{
std::vector<sf::Vertex> vertices((width + height + 2) * 2);
static const auto e = 0.001f;
// make vertical lines
for (unsigned i = 0; i <= width; ++i)
{
const auto& line = &vertices[i * 2];
line[0] = {twoDToIso(sf::Vector2f(((i==0) ? i+e : i), 0 ) * size), color};
line[1] = {twoDToIso(sf::Vector2f(((i==0) ? i+e : i), height) * size), color};
}
// make horizontal lines
for (unsigned i = 0; i <= height; ++i)
{
const auto& line = &vertices[(i + width + 1) * 2];
line[0] = {twoDToIso(sf::Vector2f(0, ((i==height) ? i-e : i)) * size), color};
line[1] = {twoDToIso(sf::Vector2f(width, ((i==height) ? i-e : i)) * size), color};
}
return vertices;
}
class Grid final : public sf::Drawable
{
class Cell
{
public:
explicit Cell(const sf::Vector2i& offset, float size, const sf::Color& color)
{
vertices[0] = {twoDToIso(sf::Vector2f( offset.x, offset.y ) * size), color};
vertices[1] = {twoDToIso(sf::Vector2f((offset.x + 1), offset.y ) * size), color};
vertices[2] = {twoDToIso(sf::Vector2f( offset.x, (offset.y + 1)) * size), color};
vertices[3] = {twoDToIso(sf::Vector2f((offset.x + 1), offset.y ) * size), color};
vertices[4] = {twoDToIso(sf::Vector2f((offset.x + 1), (offset.y + 1)) * size), color};
vertices[5] = {twoDToIso(sf::Vector2f( offset.x, (offset.y + 1)) * size), color};
}
void setFillColor(const sf::Color& color) const
{
for (auto& v : vertices) { v.color = color;}
}
const sf::Color& getFillColor() const
{
return vertices[0].color;
}
sf::Vector2f getPosition() const
{
return vertices[0].position;
}
const sf::Vertex* data() const
{
return vertices.data();
}
unsigned size() const
{
return vertices.size();
}
private:
mutable std::array<sf::Vertex, 6> vertices;
};
using CellHolder = std::vector<Cell>;
using CellRef = CellHolder::iterator;
using OutLineHolder = std::vector<sf::Vertex>;
public:
explicit Grid(int width,
int height,
float tile_size,
const sf::Color& color=sf::Color::White)
: grid{}
, outlines{make_outLines(width, height, tile_size)}
{
const auto numberOfCells = width * height;
grid.reserve(numberOfCells);
for (int i = 0; i < numberOfCells; ++i)
{
sf::Vector2i offset(i % width, i / width);
grid.emplace_back(offset, tile_size, color);
}
}
const Cell& operator[](unsigned index) const {return grid[index];}
CellRef begin() {return grid.begin();}
CellRef end() {return grid.end();}
private:
void draw(sf::RenderTarget& target, sf::RenderStates) const
{
static const auto grid_size = grid[0].size()*grid.size();
static const auto outlines_size = outlines.size();
static const auto& outlines_cache = outlines.data();
target.draw(grid[0].data(), grid_size, sf::Triangles);
target.draw(outlines_cache, outlines_size, sf::Lines);
}
private:
CellHolder grid;
OutLineHolder outlines;
};
template <typename Graph>
class PathFinder
{
using NodeRef = typename Graph::NodeRef;
using NodeVal = typename Graph::NodeVal;
using QueBase = std::tuple<NodeRef, double, double, std::vector<NodeRef>>;
struct QueueHelper final : public QueBase
{
QueueHelper(const QueueHelper&) = default;
explicit QueueHelper(const NodeRef& data,
double f,
double g,
const std::vector<NodeRef>& route)
: QueBase(data, f, g, route)
{
std::get<3>(*this).emplace_back(data);
std::get<3>(*this).shrink_to_fit();
}
friend bool operator < (const QueueHelper& lhs, const QueueHelper& rhs)
{
return std::get<1>(lhs) > std::get<1>(rhs);
}
};
public:
explicit PathFinder(sf::RenderWindow& window, Grid& grid, int width)
: window{window}
, grid{grid}
, width{width}
, light{sf::Color{102,205,170}}
, dark{sf::Color{127,255,212}}
{}
std::vector<NodeRef> routeAstar(const NodeRef& src, const NodeRef& dst) const
{
std::set<NodeVal> found;
std::priority_queue<QueueHelper> frontier;
frontier.emplace(src, 0,0, std::vector<NodeRef>{});
const auto& start = src->value();
const auto& goal = dst->value();
static const double scale = 0.001;
while (!frontier.empty())
{
const auto next = frontier.top(); frontier.pop();
const auto& nextRef = std::get<0>(next);
const auto& nextVal = nextRef->value();
if (found.find(nextVal) != found.end()) continue;
const auto& result = std::get<3>(next);
if (nextRef == dst) return result;
if (nextRef != src && nextRef != dst){
const auto index = nextVal.x + width * nextVal.y;
grid[index].setFillColor(light);
}
found.emplace(nextVal);
const auto nextg = std::get<2>(next);
const auto& d1 = nextVal - goal;
const auto& d2 = start - goal;
const auto cross = std::abs(d1.x*d2.y - d2.x*d1.y) * scale;
for (const auto& edge : *nextRef)
{
const auto& edgeRef = std::get<0>(edge);
const auto& edgeVal = edgeRef->value();
if (found.find(edgeVal) != found.end()) continue;
const auto h = manhattan(edgeVal, goal) + cross;
const auto f = nextg + h;
const auto g = nextg + std::get<1>(edge);
if (edgeRef != src && edgeRef != dst){
const auto index = edgeVal.x + width * edgeVal.y;
grid[index].setFillColor(dark);
}
frontier.emplace(edgeRef, f, g, result);
}
draw();
}
return {};
}
std::vector<NodeRef> routeDijkstra(const NodeRef& src, const NodeRef& dst) const
{
std::set<NodeVal> found;
std::priority_queue<QueueHelper> frontier;
frontier.emplace(src, 0,0, std::vector<NodeRef>{});
while (!frontier.empty())
{
const auto next = frontier.top(); frontier.pop();
const auto& nextRef = std::get<0>(next);
const auto& nextVal = nextRef->value();
if (found.find(nextVal) != found.end()) continue;
const auto& result = std::get<3>(next);
if (nextRef == dst) return result;
if (nextRef != src && nextRef != dst){
const auto index = nextVal.x + width * nextVal.y;
grid[index].setFillColor(light);
}
found.emplace(nextVal);
const auto& cost = std::get<1>(next);
for (const auto& edge : *nextRef)
{
const auto& edgeRef = std::get<0>(edge);
const auto& edgeVal = edgeRef->value();
if (found.find(edgeVal) != found.end()) continue;
if (edgeRef != src && edgeRef != dst){
const auto index = edgeVal.x + width * edgeVal.y;
grid[index].setFillColor(dark);
}
frontier.emplace(edgeRef, cost + std::get<1>(edge), 0, result);
}
draw();
}
return {};
}
private:
void draw() const
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed
|| (event.type == sf::Event::KeyPressed
&& event.key.code == sf::Keyboard::Escape))
window.close();
}
window.clear();
window.draw(grid);
window.display();
}
private:
sf::RenderWindow& window;
Grid& grid;
const int width;
const sf::Color light;
const sf::Color dark;
};
class MapEditor : public sf::Transformable
{
using PathHolder = std::vector<sf::Vector2i>;
using PathRef = PathHolder::iterator;
using Graph = Graph<sf::Vector2i>;
using PathFinder = PathFinder<Graph>;
enum Input
{
None = 0,
AddWall = 1 << 0,
RemoveWall = 1 << 1,
MoveStart = 1 << 2,
MoveGoal = 1 << 3,
};
enum Algorithm
{
Dijkstra = 1 << 0,
Astar = 1 << 1,
};
public:
MapEditor()
: width{30}
, height{30}
, tile_size{20}
, window{
sf::VideoMode(width*tile_size, height*tile_size),
"Path Finders - Algorithms"}
, view{window.getDefaultView()}
, grid{width, height, tile_size}
, input{None}
, start{}
, goal{}
, needUpdate{false}
, algorithm{Dijkstra}
, graph{}
, pathFinder{window, grid, width}
{
view.move(-width*tile_size/2, 0);
view.zoom(2.f);
window.setView(view);
std::random_device rd;
std::mt19937 gen(rd());
auto distH = std::uniform_int_distribution<>(1,height/2);
auto distW = std::uniform_int_distribution<>(width/4,width*2);
start.x = distW(gen)%width; start.y = distH(gen)%height;
goal.x = distW(gen)%width; goal.y = distH(gen)%height;
grid[start.x + width * start.y].setFillColor(sf::Color::Green);
grid[goal.x + width * goal.y].setFillColor(sf::Color::Red);
begin = path.end();
}
void run()
{
while (window.isOpen())
{
processEvents();
update();
render();
}
}
private:
void processEvents()
{
static const unsigned toggle = (Dijkstra ^ Astar);
sf::Event event;
float factor = 0.f;
while (window.pollEvent(event))
{
const auto& pos = sf::Mouse::getPosition(window);
const auto& mappedPos = window.mapPixelToCoords(pos, view);
const auto& coord = isoTo2D(mappedPos) / tile_size;
switch (event.type)
{
case sf::Event::Closed:window.close(); break;
case sf::Event::KeyPressed:
if (event.key.code == sf::Keyboard::Escape){
window.close();
}
else if (event.key.code == sf::Keyboard::P){
clearPath();
}
else if (event.key.code == sf::Keyboard::R){
setAlgorithmType(algorithm);
}
else if (event.key.code == sf::Keyboard::S){
setAlgorithmType(algorithm);
}
else if (event.key.code == sf::Keyboard::W){
clearWall();
}
else if (event.key.code == sf::Keyboard::T){
algorithm ^= toggle;
}
// debug
else if (event.key.code == sf::Keyboard::Right){
view.rotate(factor -= 1.f);
window.setView(view);
}
else if (event.key.code == sf::Keyboard::Left){
view.rotate(factor += 1.f);
window.setView(view);
}
break;
case sf::Event::MouseButtonPressed:
if (event.mouseButton.button == sf::Mouse::Left)
{
if (addWall(coord)){
input = AddWall;
}
if (moveStart(coord)){
input = MoveStart;
}
if (moveGoal(coord)){
input = MoveGoal;
}
}
if (event.mouseButton.button == sf::Mouse::Right)
{
input = RemoveWall;
removeWall(coord);
}
break;
case sf::Event::MouseButtonReleased:
{
input &= ~(AddWall | RemoveWall | MoveStart | MoveGoal);
}
break;
case sf::Event::MouseMoved:
if (input & AddWall){
addWall(coord);
}
else if (input & RemoveWall){
removeWall(coord);
}
else if (input & MoveStart){
moveStart(coord);
}
else if (input & MoveGoal){
moveGoal(coord);
}
break;
default:break;
};
}
}
void render()
{
window.clear();
window.draw(grid);
window.display();
}
void setAlgorithmType(unsigned a)
{
algorithm = a;
reset();
std::vector<Graph::NodeRef> result;
if (algorithm & Dijkstra)
result = pathFinder.routeDijkstra(graph.getRef(start), graph.getRef(goal));
else
result = pathFinder.routeAstar(graph.getRef(start), graph.getRef(goal));
for (const auto& c : result){
path.emplace_back(c->value());
}
path.shrink_to_fit();
begin = path.begin();
}
void update()
{
if(needUpdate){
clearPath();
needUpdate = false;
}
if (begin == path.end()) return;
const auto& coord = *begin;
if (coord != start && coord != goal){
grid[coord.x + width * coord.y].setFillColor(sf::Color::Yellow);
}
begin++;
}
// mouse input
bool moveStart(const sf::Vector2i& position)
{
if(!in_bounds(position) || !passable(position)|| position == goal) return false;
start = position;
needUpdate = true;
return needUpdate;
}
bool moveGoal(const sf::Vector2i& position)
{
if(!in_bounds(position) || !passable(position) || position == start) return false;
goal = position;
needUpdate = true;
return needUpdate;
}
bool addWall(const sf::Vector2i& position)
{
if(position == start || position == goal || !in_bounds(position)) return false;
grid[position.x + width * position.y].setFillColor(Gray);
return true;
}
void removeWall(const sf::Vector2i& position)
{
if(position == start || position == goal || !in_bounds(position)) return;
grid[position.x + width * position.y].setFillColor(sf::Color::White);
needUpdate = true;
}
// keyboards input
void clearPath()
{
for (const auto& tile : grid) // keep wall
{
if (tile.getFillColor() == Gray) continue;
tile.setFillColor(sf::Color::White);
}
grid[start.x + width * start.y].setFillColor(sf::Color::Green);
grid[goal.x + width * goal.y].setFillColor(sf::Color::Red);
}
void clearWall()
{
for (const auto& tile : grid)
{
if (tile.getFillColor() == Gray)
tile.setFillColor(sf::Color::White);
}
needUpdate = true;
}
void reset()
{
clearPath();
path.clear();
begin = path.end();
graph.clear();
for (const auto& tile : grid)
{
const auto& p = isoTo2D(tile.getPosition()) / tile_size;
if (!passable(p)) continue;
graph.addNode(p);
}
for (const auto& tile : grid)
{
const auto& p = isoTo2D(tile.getPosition()) / tile_size;
if (!passable(p)) continue;
for (const auto& next : neighbors(p)){
graph.addEdge(graph.getRef(p), graph.getRef(next), 1.0);
}
}
}
inline bool in_bounds(const sf::Vector2i& id) const
{
return 0 <= id.x && id.x < width && 0 <= id.y && id.y < height;
}
inline bool passable(const sf::Vector2i& position) const
{
const auto& tile = grid[position.x + width * position.y];
return tile.getFillColor() != Gray;
}
std::vector<sf::Vector2i> neighbors(const sf::Vector2i& id) const
{
static const std::array<sf::Vector2i, 4> Directions{{
{ 1, 0},
{ 0, -1},
{-1, 0},
{ 0, 1},
}};
std::vector<sf::Vector2i> result;
result.reserve(Directions.size());
for (const auto& direction : Directions)
{
const auto& next(id + direction);
if (!in_bounds(next) || !passable(next)) continue;
result.emplace_back(next);
}
return result;
}
private:
static const sf::Color Gray;
const int width;
const int height;
const float tile_size;
sf::RenderWindow window;
sf::View view;
Grid grid;
PathHolder path;
PathRef begin;
unsigned input;
sf::Vector2i start;
sf::Vector2i goal;
bool needUpdate;
// Algorithm's engine
unsigned algorithm;
Graph graph;
PathFinder pathFinder;
};
const sf::Color MapEditor::Gray = sf::Color{139,137,137};
int main()
{
try{
MapEditor editor;
editor.run();
} catch (std::runtime_error& e)
{
std::cout << "Exception: " << e.what() << '\n';
return 1;
} catch (std::out_of_range& e)
{
std::cout << "Exception: " << e.what() << '\n';
return 1;
} catch (...)
{
std::cout << "Unknown Exception!\n";
return 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment