Skip to content

Instantly share code, notes, and snippets.

@cppxor2arr
Created August 26, 2017 05:25
Show Gist options
  • Save cppxor2arr/669ad35d83b696a37d665ddcaebeb23b to your computer and use it in GitHub Desktop.
Save cppxor2arr/669ad35d83b696a37d665ddcaebeb23b to your computer and use it in GitHub Desktop.
SFML gravity simulator
#include <SFML/Graphics.hpp>
#include <cmath>
class prog
{
public:
prog();
prog(const float&, const float&, const sf::String&);
void open(const float&, const float&, const sf::String&);
void loop();
private:
sf::RenderWindow window;
sf::Event event;
enum class state { null, exit, resize, move, clear, reset };
state current_state{state::null};
sf::View view;
sf::CircleShape object, gravity_object;
sf::Vector2f gravity, velocity, diff;
sf::VertexArray tracer{sf::LinesStrip};
float angle{0};
bool start{false};
sf::Clock timer;
state handle_events();
void refresh(const sf::Color& color = sf::Color::Black);
float radian(const float&);
float degree(const float&);
};
prog::prog() { }
prog::prog(const float& w, const float& h, const sf::String& window_title)
{
open(w, h, window_title);
}
void prog::open(const float& w, const float& h, const sf::String& window_title)
{
window.create(sf::VideoMode{static_cast<unsigned>(w), static_cast<unsigned>(h)}, window_title);
window.setFramerateLimit(0);
}
prog::state prog::handle_events()
{
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
return state::exit;
if (event.type == sf::Event::KeyPressed)
switch (event.key.code)
{
case sf::Keyboard::Return: return state::exit;
case sf::Keyboard::C: return state::clear;
case sf::Keyboard::R: return state::reset;
default: break;
}
if (event.type == sf::Event::Resized)
return state::resize;
if (event.type == sf::Event::MouseMoved)
return state::move;
}
return state::null;
}
void prog::refresh(const sf::Color& color)
{
window.clear(color);
window.setView(view);
window.draw(gravity_object);
window.draw(object);
window.draw(tracer);
window.display();
}
float prog::radian(const float& degree)
{
constexpr float pi{3.14159265358979323846};
return degree * pi / 180.0;
}
float prog::degree(const float& radian)
{
constexpr float pi{3.14159265358979323846};
return radian * 180 / pi;
}
void prog::loop()
{
view.setCenter(0, 0);
view.setSize(window.getSize().x, window.getSize().y);
object.setRadius(12);
object.setPosition(view.getCenter() - view.getSize() / 2.0f);
object.setFillColor(sf::Color::Green);
object.setPointCount(100);
gravity_object.setRadius(25);
gravity_object.setPosition(view.getCenter() - sf::Vector2f{gravity_object.getRadius(), gravity_object.getRadius()});
gravity_object.setFillColor(sf::Color::Blue);
gravity_object.setPointCount(100);
timer.restart();
while (window.isOpen())
{
current_state = handle_events();
if (current_state == state::exit)
window.close();
if (current_state == state::resize)
view.setSize(view.getSize().y * (window.getSize().x / window.getSize().y), view.getSize().y);
if (current_state == state::move)
{
gravity_object.setPosition(event.mouseMove.x - window.getSize().x / 2.0f - gravity_object.getRadius(),
event.mouseMove.y - window.getSize().y / 2.0f - gravity_object.getRadius());
start = true;
}
if (current_state == state::clear)
tracer.clear();
if (current_state == state::reset)
{
start = false;
object.setPosition(-(view.getSize() / 2.0f));
gravity_object.setPosition(-gravity_object.getRadius(), -gravity_object.getRadius());
tracer.clear();
}
diff = (gravity_object.getPosition() + sf::Vector2f{gravity_object.getRadius(),
gravity_object.getRadius()}) -
(object.getPosition() + sf::Vector2f{object.getRadius(), object.getRadius()});
if (diff.x > 0 && diff.y > 0) // quadrant I
angle = degree(std::atan(diff.y / diff.x));
else if (diff.x < 0 && diff.y > 0) // quadrant II
angle = degree(std::atan(diff.y / diff.x)) + 180;
else if (diff.x < 0 && diff.y < 0) // quadrant III
angle = degree(std::atan(diff.y / diff.x)) + 180;
else if (diff.x > 0 && diff.y < 0) // quadrant IV
angle = degree(std::atan(diff.y / diff.x)) + 360;
gravity = sf::Vector2f{10 * std::cos(radian(angle)), 10 * std::sin(radian(angle))} /
(std::sqrt(diff.x * diff.x + diff.y * diff.y) / 10);
if (start && timer.getElapsedTime().asMilliseconds() > 10)
{
velocity += gravity;
object.move(velocity);
tracer.append(object.getPosition() + sf::Vector2f{object.getRadius(), object.getRadius()});
timer.restart();
}
refresh();
}
}
int main()
{
prog app{1000, 500, "SFML"};
app.loop();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment