Files
Physics-Engine/PhysicsEngine/Core/Program.cs
2026-09-03 17:27:52 +02:00

183 lines
6.7 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 = Color.DarkGray;
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 = Color.DarkGray;
world.AddBody(ceiling);
Box leftWall = new Box(new Vector2(-wallThickness * 0.5f, worldHeight * 0.5f), new Vector2(wallThickness, worldHeight + wallThickness * 2), 0f);
leftWall.BaseColor = Color.DarkGray;
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 = Color.DarkGray;
world.AddBody(rightWall);
// 2. Static Ramps and Platforms
Box platform = new Box(new Vector2(9.0f, 4.5f), new Vector2(3.5f, 0.3f), 0f);
platform.BaseColor = Color.Gray;
platform.Friction = 0.8f;
world.AddBody(platform);
Box ramp = new Box(new Vector2(2.0f, 3.5f), new Vector2(3.5f, 0.3f), 0f);
ramp.Rotation = 0.35f; // Slopes down toward center stack
ramp.BaseColor = Color.Gray;
ramp.Friction = 0.6f;
world.AddBody(ramp);
// 3. Main Ground Box Tower (5 boxes high)
float stackX = 5.0f;
float boxHeight = 0.6f;
float boxWidth = 0.6f;
float startY = worldHeight - (boxHeight * 0.5f); // Sits cleanly on the floor surface (Y = 7.2)
Color[] stackColors = new Color[]
{
Color.DarkGreen, Color.Green, Color.Lime, Color.DarkPurple, Color.Yellow
};
for (int i = 0; i < 5; i++)
{
float y = startY - (i * boxHeight);
Box stackBox = new Box(new Vector2(stackX, y), new Vector2(boxWidth, boxHeight), 20f);
stackBox.BaseColor = stackColors[i % stackColors.Length];
stackBox.Friction = 0.8f;
stackBox.Restitution = 0.0f;
world.AddBody(stackBox);
}
// 4. Secondary Platform Stack (3 boxes high)
float platformStackX = 9.0f;
float platformTopY = 4.5f - 0.15f; // Top surface of platform
float platformStartY = platformTopY - (boxHeight * 0.5f);
for (int i = 0; i < 3; i++)
{
float y = platformStartY - (i * boxHeight);
Box pBox = new Box(new Vector2(platformStackX, y), new Vector2(0.5f, boxHeight), 12f);
pBox.BaseColor = Color.Blue;
pBox.Friction = 0.8f;
pBox.Restitution = 0.0f;
world.AddBody(pBox);
}
// 5. Dynamic Circles for Stack Interaction
// Circle balanced on top of the main ground stack
float mainStackTopY = startY - (4 * boxHeight) - (boxHeight * 0.5f);
Circle stackCap = new Circle(new Vector2(stackX, mainStackTopY - 0.3f), 0.3f, 8f);
stackCap.BaseColor = Color.Orange;
stackCap.Friction = 0.8f;
stackCap.Restitution = 0.0f;
world.AddBody(stackCap);
// Heavy ball spawned on the ramp to roll down and strike the main stack
Circle rollingBall = new Circle(new Vector2(1.0f, 1.5f), 0.45f, 350f);
rollingBall.BaseColor = Color.Red;
rollingBall.Friction = 0.5f;
rollingBall.Restitution = 0.1f;
world.AddBody(rollingBall);
// Bouncy ball dropped over the platform stack to test stability under impact
Circle droppingBall = new Circle(new Vector2(9.0f, 0.8f), 0.35f, 10f);
droppingBall.BaseColor = Color.Gold;
droppingBall.Friction = 0.4f;
droppingBall.Restitution = 0.4f;
droppingBall.Velocity = new Vector2(0.0f, 2.0f);
world.AddBody(droppingBall);
}
}
}