Files
Physics-Engine/PhysicsEngine/Core/Program.cs

234 lines
9.0 KiB
C#

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);
}
}
}