commit 707a0bd9b1e211fb8aa3549ba5f3115ca57e68f0
Author: anon <anon@anon.anon>
Date:   Tue Dec 10 20:23:03 2024 +0100

    init

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cb71b6d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.out
+.gdb_history
diff --git a/Block1D.hpp b/Block1D.hpp
new file mode 100644
index 0000000..b7d931f
--- /dev/null
+++ b/Block1D.hpp
@@ -0,0 +1,76 @@
+#ifndef PHYSICS_HEADER
+#define PHYSICS_HEADER
+
+/* A red cube which can only move horizontally.
+ * NOTES:
+ *  > there is no speed limit, but touching either end of
+ *     the movement area will reset the speed to 0.
+ */
+class Block1D {
+  public:
+    // Block properties
+    const int block_size = 30;
+    const int guard_size = 10;
+    // Movement bounds
+    const float min_x = screenWidth/10;
+    const float max_x = screenWidth-(screenWidth/10);
+
+    // Movement state
+    Vector2 position  = {min_x, screenHeight/2};
+    Vector2 direction = {0, 0};
+    float speed = 0;
+    double last_update;
+
+    // ---
+
+    void display(void) {
+        /* Guard line top
+         *     Block
+         * Guard line bottom
+         */
+        DrawRectangle(min_x, position.y-guard_size, max_x-min_x, guard_size, GRAY);         
+        DrawRectangle(position.x, position.y, block_size, block_size, RED); 
+        DrawRectangle(min_x, position.y+block_size, max_x-min_x, guard_size, GRAY); 
+
+        // Hud
+        DrawText(TextFormat("X: %5.2f", position.x), 10, 10, 20, DARKGRAY);
+        DrawText(TextFormat("Y: %5.2f", position.y), 10, 40, 20, DARKGRAY);
+        DrawText(TextFormat("Speed: %5.2f", speed), 10, 70, 20, DARKGRAY);
+
+    }
+
+    void control(Vector2 click) {
+        direction = diff(click, position);
+        speed    += abs(direction.x);
+        direction = (Vector2) {
+            .x = signum(direction.x),
+            .y = 0,
+        };
+    }
+
+    void update(void) {
+        double update_time = GetTime();
+
+        float delta = speed * (update_time - last_update) * direction.x;
+
+        if (position.x + delta < min_x) {
+            position.x = min_x;
+            speed = 0;
+        } else
+        if (position.x + delta > (max_x-block_size)) {
+            position.x = max_x-block_size;
+            speed = 0;
+        } else {
+            position.x += speed * (update_time - last_update) * direction.x;
+            if (speed - 1.1f > 0) {
+                speed -= 1.1f;
+            } else {
+                speed = 0;
+            }
+        }
+
+        last_update = update_time;
+    }
+} content;
+
+#endif
diff --git a/Block2D.hpp b/Block2D.hpp
new file mode 100644
index 0000000..d52a559
--- /dev/null
+++ b/Block2D.hpp
@@ -0,0 +1,71 @@
+#ifndef PHYSICS_HEADER
+#define PHYSICS_HEADER
+
+class Block2d {
+  public:
+    Vector2 position  = {screenWidth/2, screenHeight/2};
+    Vector2 direction = {0, 0};
+    const float max_speed = 1200;
+    Vector2 speed = {0, 0};
+    double last_update;
+
+    Block2d(void) {
+        last_update = GetTime();
+    }
+
+    void accelerate(float * v, float extra) {
+        if (abs(*v + extra) < max_speed) {
+            *v = abs(*v + extra);
+        } else {
+            *v = max_speed;
+        }
+    }
+
+    void control(Vector2 click) {
+        direction = diff(position, click);
+        Vector2 speed_addition = {
+            direction.x,
+            direction.y,
+        };
+        accelerate(&speed.x, speed_addition.x);
+        accelerate(&speed.y, speed_addition.y);
+        direction = (Vector2) {
+            .x = signum(direction.x),
+            .y = signum(direction.y),
+        };
+    }
+
+    void decelerate(float * v) {
+        if (*v - 1.1f > 0) {
+            *v -= 1.1f;
+        } else {
+            *v = 0;
+        }
+    }
+
+    void update(void) {
+        double update_time = GetTime();
+        position.x -= speed.x * (update_time - last_update) * direction.x;
+        position.y -= speed.y * (update_time - last_update) * direction.y;
+
+        decelerate(&speed.x);
+        decelerate(&speed.y);
+
+        last_update = update_time;
+    }
+
+    void display(void) {
+        // Block
+        DrawRectangle(position.x, position.y, 30, 30, RED);
+
+        // Hud
+        DrawText(TextFormat("X: %5.2f", position.x), 10, 10, 20, DARKGRAY);
+        DrawText(TextFormat("Y: %5.2f", position.y), 10, 40, 20, DARKGRAY);
+        DrawText(TextFormat("Speed X: %5.2f", speed.x), 10, 70, 20, DARKGRAY);
+        DrawText(TextFormat("Speed Y: %5.2f", speed.y), 10, 100, 20, DARKGRAY);
+    }
+
+
+} content;
+
+#endif
diff --git a/BlockProjectile.hpp b/BlockProjectile.hpp
new file mode 100644
index 0000000..0a76900
--- /dev/null
+++ b/BlockProjectile.hpp
@@ -0,0 +1,46 @@
+#error "Not implemented."
+
+#if 0
+  const float G = 9.8f;
+  const float mass = 10.0f;
+  const float x0 = 400.0f;
+  const float y0 = 500.0f;
+
+  float v0 = 50.0f;
+  float angle = 45.0f;
+  float v = v0;
+  float x = x0;
+  float y = y0;
+  float t0 = GetTime();
+
+  vector<Vector2> trajectory;
+
+      float dt = GetTime() - t0;
+      v = (G/mass) * dt;
+      x = x0 + (v0*sin(radians(angle + 90.0f))) * dt;
+      y = y0 + (v0*cos(radians(angle + 90.0f)) + G*dt) * dt * v;
+
+      trajectory.push_back((Vector2) { .x = x, .y = y });
+
+      if (y > screenHeight) {
+          v0 = (rand() % 100) + 20.0f;
+          angle = rand() % 180;
+          v = v0;
+          y = y0;
+          x = x0;
+          t0 = GetTime();
+          trajectory.clear();
+      }
+
+  ------
+
+      for (const auto &v : trajectory) {
+          DrawPixel(v.x, v.y, BLUE);
+      }
+
+      DrawCircleV((Vector2){x, y}, 10, RED);
+
+      DrawText("Stone Trajectory Simulation", 10, 10, 20, DARKGRAY);
+      DrawText(TextFormat("Time: %.2f s", dt), 10, 40, 20, DARKGRAY);
+      DrawText(TextFormat("Velocity: %.2f Angle: %.2f", v, angle), 10, 70, 20, DARKGRAY);
+#endif
diff --git a/BouncyBlock1D.hpp b/BouncyBlock1D.hpp
new file mode 100644
index 0000000..0535149
--- /dev/null
+++ b/BouncyBlock1D.hpp
@@ -0,0 +1,76 @@
+
+#ifndef PHYSICS_HEADER
+#define PHYSICS_HEADER
+
+/* A red cube which can only move horizontally and is mode of rubber.
+ */
+class Block1D {
+  public:
+    // Block properties
+    const int block_size = 30;
+    const int guard_size = 10;
+    const float restitution = 0.72f;
+    // Movement bounds
+    const float min_x = screenWidth/10;
+    const float max_x = screenWidth-(screenWidth/10);
+
+    // Movement state
+    Vector2 position  = {min_x, screenHeight/2};
+    Vector2 direction = {0, 0};
+    float speed = 0;
+    double last_update;
+
+    // ---
+
+    void display(void) {
+        /* Guard line top
+         *     Block
+         * Guard line bottom
+         */
+        DrawRectangle(min_x, position.y-guard_size, max_x-min_x, guard_size, GRAY);         
+        DrawRectangle(position.x, position.y, block_size, block_size, RED); 
+        DrawRectangle(min_x, position.y+block_size, max_x-min_x, guard_size, GRAY); 
+
+        // Hud
+        DrawText(TextFormat("X: %5.2f", position.x), 10, 10, 20, DARKGRAY);
+        DrawText(TextFormat("Y: %5.2f", position.y), 10, 40, 20, DARKGRAY);
+        DrawText(TextFormat("Speed: %5.2f", speed), 10, 70, 20, DARKGRAY);
+    }
+
+    void control(Vector2 click) {
+        direction = diff(click, position);
+        speed    += abs(direction.x);
+        direction = (Vector2) {
+            .x = signum(direction.x),
+            .y = 0,
+        };
+    }
+
+    void update(void) {
+        double update_time = GetTime();
+
+        float delta = speed * (update_time - last_update) * direction.x;
+
+        if (position.x + delta < min_x) {
+            position.x = min_x;
+            speed = speed * restitution;
+            direction.x = direction.x * -1;
+        } else
+        if (position.x + delta > (max_x-block_size)) {
+            position.x = max_x-block_size;
+            speed = speed * restitution;
+            direction.x = direction.x * -1;
+        } else {
+            position.x += speed * (update_time - last_update) * direction.x;
+            if (speed - 1.1f > 0) {
+                speed -= 1.1f;
+            } else {
+                speed = 0;
+            }
+        }
+
+        last_update = update_time;
+    }
+} content;
+
+#endif
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..6bf71dd
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,50 @@
+// @BAKE g++ -o $*.out $@ -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 -ggdb
+#include <math.h>
+#include <stdlib.h>
+#include <vector>
+#include "raylib.h"
+
+#include "util.hpp"
+
+const int screenWidth  = 800;
+const int screenHeight = 600;
+
+using namespace std;
+
+/* All of the following headers define an object:
+ *  Interface Content {
+ *      void display(void);
+ *      void control(Vector2 click);
+ *      void update(void);
+ *  } content;
+ * Why not polymorhpism?
+ *   I'll let you know this is static polymorphysm
+ *   with a static template method, also, fuck you.
+ * Please uncomment only one at a time.
+ */
+//#include "Block1D.hpp"
+//#include "BouncyBlock1D.hpp"
+#include "Block2D.hpp"
+//#inline "BlockProjectile.hpp"
+
+int main() {
+    InitWindow(screenWidth, screenHeight, "Physics Simulation");
+    SetTargetFPS(60);
+
+    while (!WindowShouldClose()) {
+        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
+            content.control(GetMousePosition());
+        }
+
+        content.update();
+
+      BeginDrawing();
+        ClearBackground(RAYWHITE);
+        content.display();
+      EndDrawing();
+    }
+
+    CloseWindow();
+
+    return 0;
+}
diff --git a/util.hpp b/util.hpp
new file mode 100644
index 0000000..dae4d30
--- /dev/null
+++ b/util.hpp
@@ -0,0 +1,22 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+static inline
+float radians(const float degree) {
+    return degree * (M_PI / 180.0f);
+}
+
+static inline
+Vector2 diff(Vector2 a, Vector2 b) {
+    return (Vector2) {
+        .x = a.x - b.x,
+        .y = a.y - b.y,
+    };
+}
+
+static inline
+float signum(float x) {
+    return (x > 0) - (x < 0);
+}
+
+#endif