Created
August 26, 2017 05:25
-
-
Save cppxor2arr/669ad35d83b696a37d665ddcaebeb23b to your computer and use it in GitHub Desktop.
SFML gravity simulator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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