0
\$\begingroup\$

I'm writing a 2D game engine using C++ and SDL2 and started implementing a rigidbody component similar to that of unity to my game objects. I have a method in the rigidbody class called AddForce which takes a 2D vector force as a parameter and calculates the velocity vector using \$F = MA\$.

I use this function to move the character left and right using the keyboard arrows. Now my question is, how do I manage the gravity with this and how do I calculate the resultant force of the gravity and the force applied when pressing either keyboard arrows.

Here is the rigidbody class:

#ifndef RIGIDBODY_H
#define RIGIDBODY_H

//Game engine libraries
#include "gameEngine/Game.h"
#include "gameEngine/GameObject.h"
#include "gameEngine/Component.h"
#include "gameEngine/components/Transform.h"

//GlM library
#include "glm/glm.hpp"

class RigidBody : public Component
{
private:
    Transform* m_transfrom;
private:
    float m_mass;
    float m_acceleration;
    glm::vec2 m_forceApplied;
    glm::vec2 m_velocity;
private:
    float m_deltaTime;

public:
    RigidBody(float mass)
    {
        m_name = "RigidBody";
        m_mass = mass;
        m_acceleration = 0;
        m_forceApplied = glm::vec2(0,0);
        m_velocity = glm::vec2(0,0);
     }
public:
     void AddForce(glm::vec2 force, float deltaTime)
     {   
        float forceMagnitude;
        m_deltaTime = deltaTime;
        m_forceApplied = force;

        forceMagnitude = glm::length(force);
        m_acceleration = forceMagnitude / m_mass;
      }    
 private:
     glm::vec2 CalculateVelocity()
     {
         float velocityMagnitude;
         static glm::vec2 newVelocity = glm::vec2(0,0);

         velocityMagnitude = m_acceleration * m_deltaTime;

         if(m_forceApplied.x != 0 || m_forceApplied.y != 0)
             newVelocity = glm::normalize(m_forceApplied);
         else
           newVelocity = glm::vec2(0,0);

         newVelocity = newVelocity * velocityMagnitude;

         return newVelocity;
      }

 public:
    void Initialize() override
    {
        m_transfrom = m_owner->GetComponent<Transform>("Transform");
    }
    void Update(Game instance, float deltaTime) override
    {
        m_velocity += CalculateVelocity();
        m_transfrom->position.x += m_velocity.x * deltaTime;
        m_transfrom->position.y += m_velocity.y * deltaTime;
    }
    void Render() override
    {

    }
 };

 #endif
\$\endgroup\$
0
\$\begingroup\$

Have a look at semi-implicit Euler integration - there's an example at the end for an 1D spring. This is what you're basically doing. Also, you have no need for working with magnitudes and normalized directions. Just add the applied forces times the delta time to the velocity. That's all you need to do.

Now, to answer your question, you need a force accumulator. See this course for more details. It could be m_forceApplied in your case. And every time you call AddForce you just add force to it. And in CalculateVelocity you just do m_velocity += m_forceApplied * deltaTime / m_mass. And you can add gravity using AddForce and the m * g formula as Sascha was saying. Or you can hardcode it directly: m_velocity += (m_forceApplied / m_mass + gravity) * deltaTime.

Update: I corrected myself, I realized I used the mass wrong in the integration, it was not adding up.

\$\endgroup\$
0
\$\begingroup\$

If you're using a physics model which takes only forces as input, weight is simply the product of the object's mass with a gravity constant. If the object's mass is constant then you can simplify the weight to also be a constant.

If the object is lying on the ground or another surface, you also have to add the reaction force.

The resultant of the forces is the sum of all forces acting on the object : gravity, reaction force if any, force resulting to user input if any.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.