using System.Numerics; using Raylib_cs; namespace PhysicsEngine { class Program { private static Font robotoFont; private static WorldModel world; static void Main(string[] args) { Raylib.SetConfigFlags(ConfigFlags.FullscreenMode | ConfigFlags.VSyncHint); Raylib.InitWindow(0, 0, "Physics Engine"); robotoFont = Raylib.LoadFont("Roboto-Regular.ttf"); Raylib.SetTextureFilter(robotoFont.Texture, TextureFilter.Bilinear); Camera camera = new Camera(); world = new WorldModel(); Scenario(); const float physicsTimeStep = 1.0f / 60.0f; float accumulator = 0.0f; // main loop while (!Raylib.WindowShouldClose()) { float frameTime = Raylib.GetFrameTime(); if (frameTime > 0.25f) { frameTime = 0.25f; } // update Camera camera.Update(frameTime); // update physics accumulator accumulator += frameTime; while (accumulator >= physicsTimeStep) { UpdatePhysics(physicsTimeStep); accumulator -= physicsTimeStep; } // render loop Raylib.BeginDrawing(); Raylib.ClearBackground(MuiDarkColor.BackgroundDefault.ToColor()); camera.DrawGrid(); // draw bodies Raylib.BeginMode2D(camera.RaylibCamera); RenderScene(); Raylib.EndMode2D(); camera.DrawHUD(); DrawText("Physics Engine", 20, 20, 30, MuiDarkColor.TextPrimary.ToColor()); Raylib.EndDrawing(); } Raylib.UnloadFont(robotoFont); Raylib.CloseWindow(); } public static void DrawText(string text, int posX, int posY, float fontSize, Color color) { Raylib.DrawTextEx(robotoFont, text, new Vector2(posX, posY), fontSize, 1.0f, color); } private static void UpdatePhysics(float dt) { world.Step(dt); } private static void RenderScene() { foreach (var body in world.Bodies) { body.Draw(); } } private static void Scenario() { float worldWidth = 12.8f; float worldHeight = 7.2f; float wallThickness = 1.0f; // 1. Static World Borders Box floor = new Box(new Vector2(worldWidth * 0.5f, worldHeight + (wallThickness * 0.5f)), new Vector2(worldWidth + wallThickness * 2, wallThickness), 0f); floor.BaseColor = new Color(60, 60, 60); floor.Friction = 0.9f; world.AddBody(floor); Box ceiling = new Box(new Vector2(worldWidth * 0.5f, -wallThickness * 0.5f), new Vector2(worldWidth + wallThickness * 2, wallThickness), 0f); ceiling.BaseColor = new Color(60, 60, 60); world.AddBody(ceiling); Box leftWall = new Box(new Vector2(-wallThickness * 0.5f, worldHeight * 0.5f), new Vector2(wallThickness, worldHeight + wallThickness * 2), 0f); leftWall.BaseColor = new Color(60, 60, 60); world.AddBody(leftWall); Box rightWall = new Box(new Vector2(worldWidth + wallThickness * 0.5f, worldHeight * 0.5f), new Vector2(wallThickness, worldHeight + wallThickness * 2), 0f); rightWall.BaseColor = new Color(60, 60, 60); world.AddBody(rightWall); // ========================================================================= // TEST 1: Ultra-Tall Thin Skyscraper (X = 2.0) // 18-box high column testing vertical constraint propagation and slop // ========================================================================= float singleStackX = 2.0f; float colBoxWidth = 0.5f; float colBoxHeight = 0.35f; int towerHeight = 18; for (int i = 0; i < towerHeight; i++) { float y = worldHeight - (colBoxHeight * 0.5f) - (i * colBoxHeight); Box box = new Box(new Vector2(singleStackX, y), new Vector2(colBoxWidth, colBoxHeight), 10f); // Color gradient using integer calculations int r = Math.Clamp(30 + i * 11, 0, 255); int g = Math.Clamp(140 - i * 6, 0, 255); int b = Math.Clamp(255 - i * 5, 0, 255); box.BaseColor = new Color(r, g, b); box.Friction = 0.85f; box.Restitution = 0.0f; world.AddBody(box); } // ========================================================================= // TEST 2: 10-Tier Staggered Pyramid (Centered at X = 6.2) // 55 boxes in multi-contact arrangement testing shear and load distribution // ========================================================================= int pyramidTiers = 10; float pBoxWidth = 0.45f; float pBoxHeight = 0.30f; float pyramidCenterX = 6.2f; for (int row = 0; row < pyramidTiers; row++) { int boxesInRow = pyramidTiers - row; float rowY = worldHeight - (pBoxHeight * 0.5f) - (row * pBoxHeight); float startX = pyramidCenterX - ((boxesInRow - 1) * pBoxWidth * 0.5f); for (int col = 0; col < boxesInRow; col++) { float x = startX + (col * pBoxWidth); Box pBox = new Box(new Vector2(x, rowY), new Vector2(pBoxWidth - 0.01f, pBoxHeight - 0.01f), 15f); // Heatmap color gradient (Integer args) int r = Math.Min(255, 180 + row * 8); int g = Math.Min(255, row * 26); int b = 30; pBox.BaseColor = new Color(r, g, b); pBox.Friction = 0.9f; pBox.Restitution = 0.0f; world.AddBody(pBox); } } // ========================================================================= // TEST 3: Interlocked Double Tower Structure (X = 10.0 and X = 11.0) // Parallel columns tied together by heavy cross-planks every 4 tiers // ========================================================================= float towerAX = 10.0f; float towerBX = 11.0f; float tBoxWidth = 0.45f; float tBoxHeight = 0.32f; int towerRows = 16; for (int row = 0; row < towerRows; row++) { float y = worldHeight - (tBoxHeight * 0.5f) - (row * tBoxHeight); int r = 50; int g = Math.Min(255, 100 + row * 8); int b = Math.Min(255, 180 + row * 4); // Column A Box Box boxA = new Box(new Vector2(towerAX, y), new Vector2(tBoxWidth, tBoxHeight), 12f); boxA.BaseColor = new Color(r, g, b); boxA.Friction = 0.8f; boxA.Restitution = 0.0f; world.AddBody(boxA); // Column B Box Box boxB = new Box(new Vector2(towerBX, y), new Vector2(tBoxWidth, tBoxHeight), 12f); boxB.BaseColor = new Color(r, g, b); boxB.Friction = 0.8f; boxB.Restitution = 0.0f; world.AddBody(boxB); // Cross-plank binder every 4th level if (row % 4 == 3) { float plankY = y - (tBoxHeight * 0.5f) - 0.08f; Box plank = new Box(new Vector2((towerAX + towerBX) * 0.5f, plankY), new Vector2(1.6f, 0.16f), 30f); plank.BaseColor = new Color(220, 160, 40); plank.Friction = 0.95f; plank.Restitution = 0.0f; world.AddBody(plank); } } // ========================================================================= // TEST 4: High-Mass Top Stressers // ========================================================================= // Heavy weight on top of thin skyscraper float capY = worldHeight - (towerHeight * colBoxHeight) - 0.4f; Box heavyCap = new Box(new Vector2(singleStackX, capY), new Vector2(0.8f, 0.8f), 150f); heavyCap.BaseColor = new Color(240, 40, 40); heavyCap.Friction = 0.9f; world.AddBody(heavyCap); // Heavy sphere dropping onto the peak of the pyramid Circle impactBall = new Circle(new Vector2(pyramidCenterX, 0.5f), 0.45f, 250f); impactBall.BaseColor = new Color(255, 80, 0); impactBall.Friction = 0.7f; impactBall.Restitution = 0.05f; world.AddBody(impactBall); } } }