Gravity in the Cyclone Physics Engine - c++

I'm building up a 2D physics engine in c++ based on the Cyclone Physics Engine, http://procyclone.com, and I'm trying to figure out why the code uses a gravity vector multiplied by the mass to add force to an object,
void psiclone::Gravity::addForce(Body* body, double seconds) {
body->addForce(gravity * body->mass);
}
instead of
body->addForce(gravity * seconds);
Granted, the code does provide an update() including
velocity.mX += acceleration.getX() * seconds;
but with 2 objects being effected by gravity, shouldn't they both hit the ground at the same time even if they have different masses??

From physics, we know that force = mass * acceleration. Thus to calculate acceleration, they just divide force by mass. They are just sticking with physics definitions of the terms. gravity * seconds would be velocity.

Thank you for the replies; Upon further investigation I was missing a line in my update function ( cyclone's particle::integrate() ) multiplying the acceleration vector by the body's inverseMass:
acceleration *= inverseMass;
velocity += acceleration * seconds;
position += velocity * seconds;
This allowed two body's of differing mass to both fall to the bottom of the screen and hit at the same time.

Related

Asteroids game c++ inertia

I'm trying to make my asteroid keep moving once I press a button.
void Ship::applyThrust()
{
_v.setX(_v.getX() - sin(2 * M_PI * (_angle / 360)) * 2.5);
_v.setY(_v.getY() + cos(2 * M_PI * (_angle / 360)) * 2.5);
}
This is the formula I have to help my ship move.
The _v.setX and _vsetY updates the X and Y position
The M_PI is just 3.14.
The _angle is how much of a rotation I set with my left and right arrow keys and
The 2.5 is how many frames per I want it to move
My ship is moving just fine, the problem is that I'm trying to simulate space inertia and have my ship continue moving.
Any ideas on how would be the logic for this?
Thanks,
Inside of your game loop, you'll need a function that updates the position of the ship based on its x and y velocity. You're close in getting the new x and y coordinates of your ship, but you don't account for the velocity of the ship. When you apply thrust, get the x and y components of your velocity, not your new position. You'll have an additional function to update position which should be called within the game loop at a timed interval - e.g. every time you update the frame. So your applyThrust function should actually update your ship's velocity. That means you'll need to add variables to your Ship class for your ship's position and your ship's velocity if you don't already have them. I'm breaking out the components of position and velocity for simplicity, but you'll probably want to store them in a vector for clarity:
class Ship
{
private float xpos, ypos; // current position of your ship
private float velocityX, velocityY; // current velocity of your ship
}
Then, when you apply thrust, you change the velocity, and remember that applyThrust is only called when the thrust button is pushed, not every frame as the position update is:
void Ship::applyThrust()
{
/*
Assume 1 total unit of thrust is applied each time you hit the thrust button
so you break down the velocity into x and y components depending on the direction
your ship is facing.
*/
// thrustUnit is how much thrust each thrust button press gets you, it's arbitrary
// and can be the 2.5 multiplier you're using in your question
float thrustUnit = 1.0;
// now get the x and y thrust components of velocity based on your ship's direction
// assuming 0 degrees is pointing to the right
float newVX, newVY = 0.0;
newVX = thrustUnit * cos(_angle);
newVY = thrustUnit * sin(_angle); // radian conversion left out to save space
// Update your ship's velocity
updateVelocity(newVX, newVY);
}
updateVelocity will look something like: (note that the velocity is additive so it continues to drift unless a thrust is applied in the opposite direction - the same as if it were in a frictionless medium such as space)
void Ship::updateVelocity(newVX, newVY)
{
// update the x component
velocityX += newVX;
velocityY += newVY;
}
So now you'll also need an updatePosition function that takes into account your ship's velocity. This gets called with each frame update:
void Ship::updatePosition()
{
// add the x component of velocity to the ship's x position
// assuming xpos and ypos are variables in the Ship class for tracking position
xpos += velocityX;
ypos += velocityY;
}
Now the position of the ship changes incrementally according to each velocity component at each frame update. You can also make thrustUnit a member variable to allow for power-ups that can either boost or decrease your thrust component for your ship's speed and being able to control it better with a smaller thrustUnit or giving it hyperspeed with a large thrustUnit.
Good luck with your game!

How to get position in 3D cordinates using mpu 6050?

I am working in a project using MPU6050 with my designed chip to detect object movement.
Project is divided into 2 phases:
Phase I: visualize object orientation (DONE)
Phase II: visualize object position in 3D cordinates with gyroscope and accelerator.I follow instructions from this website:http://www.x-io.co.uk/oscillatory-motion-tracking-with-x-imu/. The position must be derived from this through ‘double integration’; the accelerometer is first integrated to yield a velocity and then again to yield the position.
void COpenGLControl::Update()
{
double mX;
double mY;
double mZ;
mX = mXCordinate*9.81; // mXCordinate-> X accelerator
mY = mYCordinate*9.81; // mYCordinate-> Y accelerator
mZ = mZCordinate*9.81; // mZCordinate-> Z accelerator
/* linear velocity*/
curVelX = preVelX + mX *sampleRate;
curVelY = preVelY + mY*sampleRate;
curVelZ = preVelZ + mZ*sampleRate;
/* linear location*/
curLoX = preLoX + curVelX*sampleRate;
curLoY = preLoY + curVelY*sampleRate;
curLoZ = preLoZ + curVelZ*sampleRate;
preVelX = curVelX;
preVelY = curVelY;
preVelZ = curVelZ;
preLoX = curLoX;
preLoY = curLoY;
preLoZ = curLoZ;
}
Then curLoX, curLoY, curLoZ is used to visualize 3D object with openGL:
glPushMatrix();
glTranslatef(curLoY,curLoX,curLoZ); //-> object moving visualization
glBegin(GL_QUADS);
........
glPopMatrix();
My purpose is that when moving object up, down, left, right, the 3D object will have the same movement. But object just only move when I rotate my device not linear movement following in http://www.x-io.co.uk/oscillatory-motion-tracking-with-x-imu/.
How can I solve this problems?
Accelerometers don't give you the object's position, but the, well it's in their name, acceleration, i.e. the rate of change of velocity.
You have to double integrate over time the values from the accelerometer to determine the position of the object. But there's a catch: Technically doing this is only valid for bodies in free fall. Down here on Earth (and every other massive body in the universe) there's gravity. The mechanical effect of gravity is acceleration. So down here on Earth you can measure a constant acceleration of about 9.81m/s² towards the Earth's center of gravity (you already have a constant of 9.81 up there but you completely misunderstood what it means).
There is no physically correct way to compensate for that. Acceleration is acceleration and in fact we are all moved in spacetime by it (that's why time is progressing a little slower down here on Earth than in outer space) and if you plotted the movement of the IMU in 4D spacetime it'd be the actual proper movement.
What you probably want to see however is the relative movement in the local accelerated frame of reference. If you assume a constant acceleration, that you can take this acceleration vector and subtract it from the measured values. Of course with every rotation of the IMU the acceleration vector will rotate, so you have to integrate the IMU rotation and apply that on the acceleration offset vector before subtracting. Assuming that relative movements are short and have a rather high frequency you may get away with low-pass filtering the accelerometer signal to determine the gravity offset vector.

SFML - Move object towards coord

so I am working on an AI system with C++ and SFML in which I want the enemies to follow the player. Im going to create it so the enemies are moving towards the point at which the player was 30 frames ago (so it will constantly updating). But my question is simple, what is the math behind getting the enemy to move to a specific point? Like let's say the player is at (230, 400) and the enemy is at (100, 200) how do I get the enemy (using the .move() function with a speed of 3) to move to that point? Any help would be fantastic!
---UPDATED BELOW WITH CURRENT CODE FOR HANDLING MOVEMENT-----
float angle = atan2(v2iEnemyPos[1].y - rsPlayer.getPosition().y, v2iEnemyPos[1].x - rsPlayer.getPosition().x);
angle =angle * 180 / (atan(1) * 4);
sf::Vector2f newpos((cos(angle))*2, (sin(angle))*2);
std::cout << newpos.x << " " << newpos.y << std::endl;
rsEnemy[1].move(newpos.x, newpos.y);
rwWinOne.draw(rsPlayer);
rwWinOne.display();
rwWinOne.clear();
The direction to move your enemy into is simply the difference between the player position and the enemy position. However, you want the enemies to move with constant speed, so you need to normalize the result. This will give you the direction as a vector of length 1.
Vector2u direction = normalize(player.getPosition() - enemy.getPosition());
You can now multiply this direction by the speed constant of that enemy's type. The result is a vector with it's length depending on the speed factor instead of the distance to the player. Just use the result to move your enemy.
enemy.move(speed * direction);
However, you perform that once a frame and framerates can vary between machines and configurations. Therefore, you should add a the elapsed time since the last move call, which might be your frame time, as factor to the equation. This way, if a frame takes a longer than usual, the enemy will be moved further to comprehend this, and vice versa.
// Initialize a timer
sf::Clock clock;
// Get elapsed time at the beginning of a frame
// I multiply this by target framerate to get a value around one
float delta = clock.restart().asSeconds() * 60;
// Move all objects based on elapsed time
Vector2u direction = normalize(player.getPosition() - enemy.getPosition());
enemy.move(delta * speed * direction);
By the way, basic knowledge of linear algebra is needed very often in game development, so you might pay out to attend an online course.
You should consider the elapsed time (since last frame) - dt - in your calculation.
The enemy has a given speed: enemy_velocity.
I won't use the move() function, but the SetPosition().
You have to calculate the new position of the enemy:
enemy.x += dt * enemy_velocity * cos(angle);
enemy.y += dt * enemy_velocity * sin(angle);
And affect it with SetPosition().

C++/SDL Gravity in Platformer

I'm currently trying to get a form of gravity (it doesn't need to be EXACTLY gravity, no realism required) into my platformer game, however I'm stumbling over logic on this.
The following code is what I use when the up arrow or W is pressed, (jumping)
if (grounded_)
{
velocity_.y -= JUMP_POWER;
grounded_ = false;
}
In my Player::Update() function I have
velocity_.y += GRAVITY;
There's more in that function but it's irrelevant to the situation.
Currently the two constants are as follows: GRAVITY = 9.8f; and JUMP_POWER = 150.0f;
The main issue I'm having with my gravity that I cannot find the proper balance between my sprite being able to make his jumps, and being way too floaty.
Long story short, my questions is that my sprite's jumps as well as his regular falling from one platform to another are too floaty, any ideas on how to scale it back to something a tad more realistic?
Instead of thinking in terms of the actual values, think in terms of their consequences.
So, the initial velocity is -jump_power, and the acceleration gravity. A little calculus gives
y = -Height = -jump_power * t + 1/2 * gravity * t^2
This assumes a small time step.
Then, the
time_in_flight = 2 * time_to_vertex = jump_power/gravity
and the vertex is
height(time_to_vertex) = jump_power^2/(4 * gravity)
Solving these, and adjusting for time step and fixing negatives
jump_power = (4 * height / time) * timestep_in_secs_per_update
gravity = (2 * jump_power / time) * timestep_in_secs_per_update
That way, you can mess with time and height instead of the less direct parameters. Just use the equations to gravity and jump_power at the start.
const int time = 1.5; //seconds
const int height = 100 //pixels
const int jump_power = (4 * height / time) * timestep_in_secs_per_update;
const int gravity = (2 * jump_power / time) * timestep_in_secs_per_update;
This is a technique from maths, often used to rearrange a family of differential equations in terms of 'dimensionless' variables. This way the variables won't interfere when you try to manipulate the equations characteristics. In this case, you can set the time and keep it constant while changing the power. The sprite will still take the same time to land.
Of course 'real' gravity might not be the best solution. You could set gravity low and just lower the character's height while they are not grounded.
You need think unit system correctly.
The unit of the gravity is meter per second squared. ( m/(s*s) )
The unit of a velocity is meter per second. ( m/s )
The unit of a force is Newton. ( N = kg*m/(s*s) )
Concept example:
float gravity = -9.8; // m/(s*s)
float delta_time = 33.333333e-3f; // s
float mass = 10.0f; // Kg
float force = grounded_ ? 150.0f : gravity; // kg*m/(s*s)
float acceleration = force / mass; // m/(s*s)
float velocity += acceleration * delta_time; // m/s
float position += velocity * delta; // m
It is based on the basic Newton's Equation of motion and Euler's Method.

Apply physics to player using bullet physics

So I've had a lot of problems trying to properly get physics applied to the play by using bullet physics. I've tried kinematic bodies to an unsuccess. I am now trying now trying to use a rigid body I've had little successfully. Pasted below is the updating code for the player's matrix and the rigid bodies location. My question is how could I update the player's position correctly.
Update Player's rigid body and the camera's matrix *the gCamera.matrix is just the projection and view matrix's multiplyed together
physics.PlayerBody->getMotionState()->getWorldTransform(k);
k.getOpenGLMatrix(glm::value_ptr(gCamera.matrix));
btVector3 j;
j = physics.PlayerBody->getLinearVelocity();
gCamera.position.x = j.getX();
gCamera.position.y = j.getY();
gCamera.position.z = j.getZ();
btVector3 pastPos;
pastPos.setX(gCamera.position.x);
pastPos.setY(gCamera.position.y);
pastPos.setZ(gCamera.position.z);
gCamera.GetInput(window);
float lVelocityX = sin(gCamera.horizontalAngle * 3.14159265359 / 180) * 2;
float lVelocityY = physics.PlayerBody->getLinearVelocity().y();
float lVelocityZ = cos(gCamera.verticalAngle * 3.14159265359 / 180) * 2;
//physics.PlayerBody->setLinearVelocity(btVector3(lVelocityX, lVelocityY, lVelocityZ));
physics.PlayerBody->setLinearVelocity(btVector3(gCamera.position.x, gCamera.position.y, gCamera.position.z));
btTransform t;
t.setFromOpenGLMatrix(glm::value_ptr(gCamera.matrix));
physics.PlayerBody->getMotionState()->setWorldTransform(t);
physics.PlayerBody->setCenterOfMassTransform(t);
If you want to be in control of where the player is, then use kinematic. I know you've had trouble but that's just the best solution.
If you want physics to move player, you need a rigid body and apply forces to move it.
It is not possible to move a rigid body yourself in a reliable way. Where I have had to teleport objects in the past I have removed and added a new rigid body, but you do not want to be doing that every frame for your player.