Created
May 11, 2024 10:34
-
-
Save comefrombottom/fa778bbe20061f398f1051a10fbcd8ab 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> // Siv3D v0.6.14 | |
struct Ball | |
{ | |
P2Body body; | |
double r; | |
Color color; | |
}; | |
void Main() | |
{ | |
P2World world(Vec2(0, 980)); | |
const Vec2 ballPos = Scene::CenterF().movedBy(-200, -250); | |
double ballAccum = 0.0; | |
constexpr double ballDt = 1.0 / 20.0; | |
size_t ballIndex = 0; | |
constexpr size_t maxBallCount = 1800; | |
SmallRNG rng(12345); | |
Array<Ball> balls(maxBallCount); | |
for (auto& ball : balls) { | |
ball.r = Random(3, 6, rng); | |
ball.color = HSV(Random(360, rng), 0.8, 0.8); | |
} | |
constexpr P2Material ballMaterial{ | |
.density = 1.0, | |
.restitution = 0.5, | |
.friction = 0.2, | |
.restitutionThreshold = 1.0 | |
}; | |
Array<P2Body> walls; | |
auto createWalls = [&world, &walls]() | |
{ | |
walls << world.createRect(P2Static, Scene::CenterF().movedBy(-200, 100), RectF{ Arg::center(0,0),40,400 }); | |
walls << world.createRect(P2Static, Scene::CenterF().movedBy(200, 100), RectF{ Arg::center(0,0),40,800 }); | |
walls << world.createRect(P2Static, Scene::CenterF().movedBy(0, 300), RectF{ Arg::center(0,0),440,40 }); | |
}; | |
createWalls(); | |
Image image{ U"🥹"_emoji }; | |
double floorY = Scene::Center().y + 300 - 20; | |
Vec2 imageDrawSize; | |
imageDrawSize.x = 400; | |
imageDrawSize.y = imageDrawSize.x / image.horizontalAspectRatio(); | |
Vec2 imageDrawCenter = { Scene::Center().x,floorY - imageDrawSize.y / 2 }; | |
double accum = 0.0; | |
constexpr double dt = 1.0 / 200.0; | |
bool Pause = false; | |
while (System::Update()) | |
{ | |
for (accum += Scene::DeltaTime() * (KeyTab.pressed()?5:1); accum >= dt; accum -= dt) | |
{ | |
world.update(dt); | |
//add ball | |
for (ballAccum += dt; ballAccum >= ballDt; ballAccum -= ballDt) | |
{ | |
if (ballIndex >= maxBallCount)break; | |
for (auto i : step(5)) { | |
if (ballIndex >= maxBallCount)break; | |
auto& ball = balls[ballIndex]; | |
ball.body = world.createCircle(P2Dynamic, ballPos.movedBy(0, 10 * i), ball.r, ballMaterial).setVelocity({ 500,0 }); | |
++ballIndex; | |
} | |
} | |
} | |
if (KeySpace.down()) | |
{ | |
if (Pause) { | |
Pause = false; | |
ballIndex = 0; | |
ballAccum = 0.0; | |
accum = 0.0; | |
} | |
else { | |
Pause = true; | |
for (auto& ball : balls) | |
{ | |
ball.body.release(); | |
} | |
walls.clear(); | |
world = P2World(Vec2(0, 980));//これをしないとなぜか2通りの異なるシミュレーション結果が交互にでる。 | |
createWalls(); | |
ballIndex = maxBallCount; | |
} | |
} | |
if (KeyP.down()) { | |
for (auto& ball : balls) | |
{ | |
auto pos = ball.body.getPos(); | |
Vec2 imageDrawPos = imageDrawCenter - imageDrawSize / 2; | |
Point imageIndex = ((pos - imageDrawPos) / imageDrawSize * image.size()).asPoint(); | |
if (imageIndex.x >= 0 && imageIndex.x < image.width() && imageIndex.y >= 0 && imageIndex.y < image.height()) | |
{ | |
Color color = image[imageIndex]; | |
ball.color = color.withAlpha(255); | |
} | |
else { | |
ball.color = Color(0); | |
} | |
} | |
} | |
for (auto& ball : balls) | |
{ | |
ball.body.draw(ball.color); | |
} | |
for (auto& wall : walls) | |
{ | |
wall.draw(Palette::Gray); | |
} | |
} | |
} | |
// | |
// - Debug ビルド: プログラムの最適化を減らす代わりに、エラーやクラッシュ時に詳細な情報を得られます。 | |
// | |
// - Release ビルド: 最大限の最適化でビルドします。 | |
// | |
// - [デバッグ] メニュー → [デバッグの開始] でプログラムを実行すると、[出力] ウィンドウに詳細なログが表示され、エラーの原因を探せます。 | |
// | |
// - Visual Studio を更新した直後は、プログラムのリビルド([ビルド]メニュー → [ソリューションのリビルド])が必要な場合があります。 | |
// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment