Skip to content

Instantly share code, notes, and snippets.

@dev001hajipro
Created June 18, 2017 22:29
Show Gist options
  • Save dev001hajipro/aa82cd98bbb3fc7e24f05bc30afdef6c to your computer and use it in GitHub Desktop.
Save dev001hajipro/aa82cd98bbb3fc7e24f05bc30afdef6c to your computer and use it in GitHub Desktop.
Attractor and Repeller with OpenSiv3D library.
# 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