Browse Source

Add gravity force and add inpulse force using the mouse.

Godzil 1 year ago
parent
commit
ca5c03e6ec
4 changed files with 70 additions and 15 deletions
  1. 42 14
      source/app.cpp
  2. 6 1
      source/include/app.h
  3. 2 0
      source/include/physics/force.h
  4. 20 0
      source/physics/force.cpp

+ 42 - 14
source/app.cpp

@@ -29,8 +29,8 @@ void application::setup()
     this->running = graphics::openWindow();
     this->millisecsPreviousFrame = SDL_GetTicks();
 
-    this->particles.push_back(new particle(50, 100, 1.0, 4));
-    this->particles.push_back(new particle(200, 100, 3.0, 12));
+    this->particles.push_back(new particle(200, 200, 1, 6));
+    this->particles.push_back(new particle(500, 500, 20.0, 20));
 }
 
 void application::input()
@@ -71,12 +71,27 @@ void application::input()
         case SDL_MOUSEBUTTONDOWN:
             if (event.button.button == SDL_BUTTON_LEFT)
             {
-                int x, y;
-                SDL_GetMouseState(&x, &y);
-                particle *part = new particle(x, y, 1., 5);
-                this->particles.push_back(part);
+                this->leftButtonPressed = true;
             }
             break;
+
+        case SDL_MOUSEBUTTONUP:
+            if (event.button.button == SDL_BUTTON_LEFT)
+            {
+                if (this->leftButtonPressed)
+                {
+                    vec2 impulseDirection = (particles[0]->position - this->mouseCursor).unitVector();
+                    double impulseMagnitude = (particles[0]->position - this->mouseCursor).magnitude() * 5.0;
+                    particles[0]->velocity = impulseDirection * impulseMagnitude;
+                }
+                this->leftButtonPressed = false;
+            }
+            break;
+
+        case SDL_MOUSEMOTION:
+            this->mouseCursor.x = event.motion.x;
+            this->mouseCursor.y = event.motion.y;
+            break;
         }
     }
 }
@@ -109,18 +124,26 @@ void application::syncAndDeltatime()
 void application::update()
 {
     this->syncAndDeltatime();
-
     updateTime.start();
 
     for (auto part:this->particles)
     {
-        part->addForce(this->pushForce);
-
-        vec2 friction = force::generateFrictionForce(*part, 10 * PIXELS_PER_METER);
+        vec2 friction = force::generateFrictionForce(*part, 20);
         part->addForce(friction);
+    }
 
+    vec2 attraction = force::generateGravitationalForce(*this->particles[0], *this->particles[1],
+                                                        1000, 5, 100);
+    this->particles[0]->addForce(attraction);
+    this->particles[1]->addForce(-attraction);
+
+    for (auto part:this->particles)
+    {
         part->integrate(deltaTime);
+    }
 
+    for (auto part:this->particles)
+    {
         // check the particles position and keep the particle in the window.
         if ( ((part->position.y - part->radius) <= 0) ||
              ((part->position.y + part->radius) >= graphics::height()))
@@ -160,13 +183,18 @@ void application::render()
 {
     renderTime.start();
 
-    graphics::clearScreen(0xFF056263);
-
-    for (auto part:this->particles)
+    graphics::clearScreen(0xFF0F0721);
+    if (this->leftButtonPressed)
     {
-        graphics::draw::fillCircle(part->position.x, part->position.y, part->radius, 0xFFFFFFFF);
+        graphics::draw::line(this->particles[0]->position.x, this->particles[0]->position.y,
+                             this->mouseCursor.x, this->mouseCursor.y, 0xFFFFFFFF);
     }
 
+    graphics::draw::fillCircle(this->particles[0]->position.x, this->particles[0]->position.y,
+                               this->particles[0]->radius, 0xFFAA3300);
+    graphics::draw::fillCircle(this->particles[1]->position.x, this->particles[1]->position.y,
+                               this->particles[1]->radius, 0xFF00FFFF);
+
     graphics::draw::text(5, 5, 0x11FF22, "Wait time: %02.2f ms", waitTime.get());
     graphics::draw::text(5, 17, 0x11FF22, "Update time: %02.2f ms", updateTime.get());
     graphics::draw::text(5, 29, 0x11FF22, "Render time: %02.2f ms", renderTime.get());

+ 6 - 1
source/include/app.h

@@ -28,8 +28,13 @@ private:
 
     vec2 pushForce = vec2(0, 0);
 
+    vec2 mouseCursor;
+
+    const double G = 0.00000000006674;
+    bool leftButtonPressed;
+
 public:
-    application() : running(false) {};
+    application() : running(false), leftButtonPressed(false) {};
     ~application() = default;
 
     void parseParameters(int argc, char *argv[]);

+ 2 - 0
source/include/physics/force.h

@@ -18,6 +18,8 @@ class force
 public:
     static vec2 generateFrictionForce(const particle &particleRef, double k);
     static vec2 generateDragForce(const particle &particleRef, double k);
+    static vec2 generateGravitationalForce(const particle &a, const particle &b, double g,
+                                           double minDistance = 0, double maxDistance = INFINITY);
 };
 
 #endif /* PHYSICENGINE_FORCE_H */

+ 20 - 0
source/physics/force.cpp

@@ -9,6 +9,8 @@
 
 #include <physics/force.h>
 
+#include <algorithm>
+
 vec2 force::generateDragForce(const particle &particleRef, double k)
 {
     vec2 dragForce;
@@ -34,4 +36,22 @@ vec2 force::generateFrictionForce(const particle &particleRef, double k)
     frictionForce = frictionDirection * frictionMagnitude;
 
     return frictionForce;
+}
+
+vec2 force::generateGravitationalForce(const particle &a, const particle &b, double g, double minDistance,
+                                       double maxDistance)
+{
+    vec2 attractionForce;
+    vec2 d = b.position - a.position;
+    double distanceSquared = d.magnitudeSquared();
+
+    vec2 attractionDirection = d.unitVector();
+
+    distanceSquared = std::clamp(distanceSquared, minDistance, maxDistance);
+
+    double attractionMagnitude = g * (a.mass * b.mass) / distanceSquared;
+
+    attractionForce = attractionDirection * attractionMagnitude;
+
+    return attractionForce;
 }