Created
July 9, 2017 14:13
-
-
Save sknjpn/5e9d7053c171b3bae673c71f0cdfbdf4 to your computer and use it in GitHub Desktop.
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 <HamFramework.hpp> | |
struct Compass | |
{ | |
Compass(const Vec2& _pos) : pos(_pos), ang(Vec2::Up), v(0.0) {} | |
Vec2 pos; | |
Vec2 ang; | |
double v; | |
}; | |
struct Monopole | |
{ | |
Monopole(const Vec2& _pos, const bool& _isNPole) : pos(_pos), isNPole(_isNPole), strength(1.0) {} | |
bool isNPole; //true:N極 false:S極 | |
Vec2 pos; | |
double strength; | |
}; | |
void Main() | |
{ | |
Camera2D camera; | |
Window::SetTitle(L"CompassSimulator"); | |
Window::Resize(1280, 720); | |
Array<Compass> compass; | |
Array<Monopole> monopole; | |
Monopole* selectedMonopole = NULL; | |
monopole.push_back(Monopole(Vec2(160, 240), true)); | |
monopole.push_back(Monopole(Vec2(480, 240), false)); | |
bool f = false; | |
for (double x = -2000.0; x < 2000; x += 32 * 1.73) | |
{ | |
for (double y = -2000.0; y < 2000.0; y += 64) | |
{ | |
if (f) compass.push_back(Compass(Vec2(x, y))); | |
else compass.push_back(Compass(Vec2(x, y + 32))); | |
} | |
f = !f; | |
} | |
const Font mFont(32, Typeface::Black); | |
Window::SetStyle(WindowStyle::Sizeable); | |
while (System::Update()) | |
{ | |
Window::SetBaseSize(Window::Size()); | |
for (auto& c : compass) | |
{ | |
double force = 0.0; //力のモーメント | |
for (auto& m : monopole) | |
{ | |
double len = (m.pos - c.pos).length(); | |
if (len == 0.0) continue; | |
if (m.isNPole) | |
force -= c.ang.cross(m.pos - c.pos) / len / (len*len + 32.0*32.0)*1000.0; | |
else | |
force += c.ang.cross(m.pos - c.pos) / len / (len*len + 32.0*32.0)*1000.0; | |
} | |
c.v += force; | |
c.v *= 0.98; | |
c.ang.rotate(c.v); | |
} | |
camera.update(); | |
{ | |
auto t1 = camera.createTransformer(); | |
for (auto& c : compass) | |
{ | |
const double theta = Atan2(c.ang.y, c.ang.x); | |
//Circle(c.pos, 28).draw(Palette::Lightsteelblue).drawFrame(1.0, 1.0, Palette::Gray); | |
Triangle(0, -4, 24, 0, 0, 4).rotatedAt(Vec2::Zero, theta).movedBy(c.pos).draw(Palette::Red); | |
Triangle(0, -4, -24, 0, 0, 4).rotatedAt(Vec2::Zero, theta).movedBy(c.pos).draw(Palette::White); | |
Circle(c.pos, 3).draw(Palette::Gray); | |
} | |
for (auto& m : monopole) | |
{ | |
double accuracy = 4.0; | |
for (int i = 0; i < 32; i++) | |
{ | |
Vec2 p = m.pos.movedBy(Vec2::Right.rotated(i*Pi / 16.0)); | |
for (int j = 0; j < 500; j++) | |
{ | |
bool breakFlag = false; | |
Vec2 v(0, 0); | |
for (auto& n : monopole) | |
{ | |
double len = (n.pos - p).length(); | |
if (j > 1 && len <= 1.0) { breakFlag = true; break; } | |
if (n.isNPole) v -= (n.pos - p) / (len*(len*len + 32.0*32.0)); | |
else v += (n.pos - p) / (len*(len*len + 32.0*32.0)); | |
} | |
const double width = (Log2(v.length()) + 20.0) / 4.0; | |
const Color color = Palette::White; | |
if (width < 0) break; | |
if (j % 20 == 0) Triangle(-width*3, -width*3, width*3, 0, -width*3, width*3).rotated(Atan2(v.y, v.x)).movedBy(p).draw(color); | |
if (m.isNPole) | |
{ | |
Line(p, p + v.normalized()*accuracy).draw(width, color); | |
p += v.normalized()*accuracy; | |
} | |
else | |
{ | |
Line(p, p - v.normalized()*accuracy).draw(width, color); | |
p -= v.normalized()*accuracy; | |
} | |
if (breakFlag) break; | |
} | |
} | |
} | |
for (auto& m : monopole) | |
{ | |
if (m.isNPole) | |
{ | |
Circle(m.pos, 24).draw(Palette::Red); | |
mFont(L"N").drawCenter(m.pos, Palette::Darkred); | |
} | |
else | |
{ | |
Circle(m.pos, 24).draw(Palette::Blue); | |
mFont(L"S").drawCenter(m.pos, Palette::Darkblue); | |
} | |
} | |
if (Input::MouseL.released && selectedMonopole != NULL) | |
{ | |
Monopole& m = *selectedMonopole; | |
if (Graphics2D::GetTransform().transform(m.pos).y > Window::Size().y - 64) | |
{ | |
Erase_if(monopole, [=](Monopole& t) { return &t == selectedMonopole; }); | |
} | |
selectedMonopole = NULL; | |
} | |
if (Input::MouseL.clicked) | |
{ | |
if (Graphics2D::GetTransform().inverse().transform(Vec2(0, Window::Size().y - 64)).y < Mouse::PosF().y) | |
{ | |
const Vec2 p1(48, Window::Size().y - 32); | |
const Vec2 p2(112, Window::Size().y - 32); | |
if (p1.distanceFrom(Graphics2D::GetTransform().transform(Mouse::PosF())) < 24) | |
{ | |
monopole.push_back(Monopole(Mouse::PosF(), true)); | |
selectedMonopole = &monopole.back(); | |
} | |
if (p2.distanceFrom(Graphics2D::GetTransform().transform(Mouse::PosF())) < 24) | |
{ | |
monopole.push_back(Monopole(Mouse::PosF(), false)); | |
selectedMonopole = &monopole.back(); | |
} | |
} | |
else | |
{ | |
for (auto& m : monopole) | |
{ | |
if (m.pos.distanceFrom(Mouse::PosF()) < 24.0) | |
{ | |
selectedMonopole = &m; | |
} | |
} | |
} | |
} | |
if (Input::MouseL.pressed && selectedMonopole != NULL) | |
{ | |
Monopole& m = *selectedMonopole; | |
m.pos = Mouse::PosF(); | |
} | |
} | |
Rect(0, Window::Size().y - 64, Window::Size().x, 64).draw(Palette::Lightgrey).drawFrame(4, 0, Palette::Gray); | |
const Vec2 p1(48, Window::Size().y - 32); | |
const Vec2 p2(112, Window::Size().y - 32); | |
Circle(p1, 24).draw(Palette::Red); | |
mFont(L"N").drawCenter(p1, Palette::Darkred); | |
Circle(p2, 24).draw(Palette::Blue); | |
mFont(L"S").drawCenter(p2, Palette::Darkblue); | |
{ | |
auto t1 = camera.createTransformer(); | |
if (Input::MouseL.pressed && selectedMonopole != NULL) | |
{ | |
Monopole& m = *selectedMonopole; | |
Circle(m.pos, 32).draw(Palette::White); | |
if (m.isNPole) | |
{ | |
Circle(m.pos, 24).draw(Palette::Red); | |
mFont(L"N").drawCenter(m.pos, Palette::Darkred); | |
} | |
else | |
{ | |
Circle(m.pos, 24).draw(Palette::Blue); | |
mFont(L"S").drawCenter(m.pos, Palette::Darkblue); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment