Created
June 18, 2017 22:29
-
-
Save dev001hajipro/aa82cd98bbb3fc7e24f05bc30afdef6c to your computer and use it in GitHub Desktop.
Attractor and Repeller with OpenSiv3D library.
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 <Siv3D.hpp> | |
#include <iostream> | |
#include <string> | |
#include <random> | |
using namespace std; | |
inline double myrand(double min, double max) | |
{ | |
// 以下2行は一回だけでよいのでは? | |
std::random_device rnd; | |
std::mt19937 mt(rnd()); | |
std::uniform_real_distribution<> dist(min, max); | |
return dist(mt); | |
} | |
inline double constrain(double n, double low, double high) { | |
return std::max(std::min(n, high), low); | |
} | |
class Mover { | |
public: | |
Mover() | |
: m_position(Vec2::Zero()), | |
m_velocity(Vec2::Zero()), | |
m_acceleration (Vec2::Zero()), | |
m_lifespan(255), | |
m_mass(1), | |
m_r(5) | |
{ | |
double offx = myrand(-50.0, 50.0); | |
double offy = myrand(-50.0, 50.0); | |
//m_position = Vec2(Window::Center().x + offx, Window::Center().y + offy); | |
m_position = Vec2(Window::Center().x, 100); | |
m_velocity = Vec2(myrand(-1.0,1.0), myrand(-1.0,1.0)); | |
std::cout << "Mover constructor" << std::endl; | |
} | |
void ApplyForce(Vec2 f) | |
{ | |
Vec2 a = f / this->m_mass; // F=MA, A=F/M | |
m_acceleration += a; | |
} | |
void Update() | |
{ | |
m_velocity += m_acceleration; | |
m_position += m_velocity; | |
m_acceleration *= 0; | |
this->m_lifespan += -1; | |
} | |
void Display() | |
{ | |
//Print << m_position; | |
double r = m_r; | |
Circle(m_position, r) | |
.draw(Color(175,175,175, this->m_lifespan)) | |
.drawFrame(1, 0, Color(0, 0, 0, this->m_lifespan)); | |
} | |
void Run() | |
{ | |
Update(); | |
Display(); | |
} | |
bool IsDead() { | |
return (m_lifespan <= 0); | |
} | |
Vec2 m_position; | |
private: | |
Vec2 m_velocity; | |
Vec2 m_acceleration; | |
int32_t m_lifespan; | |
int32_t m_mass; | |
int32_t m_r; | |
}; | |
class Attractor { | |
public: | |
Attractor() | |
: | |
m_position(Vec2::Zero()) | |
{ | |
} | |
Attractor(const Vec2 pos) | |
: | |
m_position(pos) | |
{ | |
} | |
Vec2 Attract(Mover &m) | |
{ | |
Vec2 dir = m_position - m.m_position; | |
double len = dir.length(); | |
len = constrain(len, 20, 110); | |
// limit | |
dir.normalize(); | |
double force = 1.0 * 100.0 / (len*len); | |
dir *= force; | |
return dir; | |
} | |
void Display() { | |
double r = 10; | |
Circle(m_position, r) | |
.draw(Color(175, 125, 125, 200)) | |
.drawFrame(1, 0, Color(0, 0, 0, 200)); | |
} | |
private: | |
Vec2 m_position; | |
}; | |
class Repeller { | |
public: | |
Repeller() | |
: | |
m_position(Vec2::Zero()) | |
{ | |
} | |
Repeller(const Vec2 pos) | |
: | |
m_position(pos) | |
{ | |
} | |
Vec2 Repel(Mover &m) | |
{ | |
Vec2 dir = m_position - m.m_position; | |
double len = dir.length(); | |
len = constrain(len, 10, 110); | |
// limit | |
dir.normalize(); | |
double force = -1.0 * 100.0 / (len*len); | |
dir *= force; | |
return dir; | |
} | |
void Display() { | |
double r = 10; | |
Circle(m_position, r) | |
.draw(Color(175, 175, 175, 200)) | |
.drawFrame(1, 0, Color(0, 0, 0, 200)); | |
} | |
private: | |
Vec2 m_position; | |
}; | |
class ParticleSystem { | |
public: | |
ParticleSystem() { | |
} | |
void AddParticle() { | |
//if (Random() < 0.5) {} | |
m_data.emplace_back(); // 引数なしMoverコンストラクター呼び出し | |
} | |
void ApplyForce(Vec2 force) { | |
for (Mover &e : m_data) { | |
e.ApplyForce(force); | |
} | |
} | |
void ApplyRepeller(Repeller & repeller) | |
{ | |
for (Mover &m : m_data) { | |
Vec2 force = repeller.Repel(m); | |
m.ApplyForce(force); | |
} | |
} | |
void ApplyAttract(Attractor & attractor) | |
{ | |
for (Mover &m : m_data) { | |
Vec2 force = attractor.Attract(m); | |
m.ApplyForce(force); | |
} | |
} | |
void Run() { | |
for (Mover &e : m_data) { | |
e.Run(); | |
} | |
} | |
void Remove() { | |
auto n = std::remove_if(m_data.begin(), m_data.end(), | |
[](Mover &m)->bool { return m.IsDead(); }); | |
m_data.erase(n, m_data.end()); | |
} | |
size_t Size() { | |
return m_data.size(); | |
} | |
private: | |
vector<Mover> m_data; | |
}; | |
void Main() | |
{ | |
Graphics::SetBackground(Color(240, 240, 240, 255)); | |
const Font font(30); | |
const Vec2 gravity(0.00, 0.03); | |
//vector<Mover> movers(100); | |
ParticleSystem ps; | |
const Vec2 pos(Window::Center().x - 120, Window::Center().y); | |
Repeller repeller1(pos); | |
const Vec2 pos2(Window::Center().x + 90, Window::Center().y+130); | |
Repeller repeller2(pos2); | |
const Vec2 pos3(Window::Center().x + 150, Window::Center().y + 0); | |
Attractor attractor1(pos3); | |
double t = 0.0; | |
while (System::Update()) | |
{ | |
font(L"Attractor Repeller(りぺらー)🐣").drawAt(Window::Center().x, 30, Palette::Black); | |
for (int i = 0; i < 10; i++) ps.AddParticle(); | |
ps.ApplyForce(gravity); | |
ps.ApplyRepeller(repeller1); | |
ps.ApplyRepeller(repeller2); | |
ps.ApplyAttract(attractor1); | |
ps.Run(); | |
ps.Remove(); | |
repeller1.Display(); | |
repeller2.Display(); | |
attractor1.Display(); | |
font(ps.Size()).draw(20, 200, Palette::Black); | |
t += System::DeltaTime(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment