Skip to content

Instantly share code, notes, and snippets.

@comefrombottom
Created May 11, 2024 10:34
Show Gist options
  • Save comefrombottom/fa778bbe20061f398f1051a10fbcd8ab to your computer and use it in GitHub Desktop.
Save comefrombottom/fa778bbe20061f398f1051a10fbcd8ab to your computer and use it in GitHub Desktop.
# 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