#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# Simulating Gravity accurately

edited October 2017

Hello!

I'm relatively new to p5.js, and have been working on a physics simulation where I want to accurately simulate gravity in a window that allows for scaling units.

The problem I had was scaling such that I could set my gravity.y vector to 9.8, and have 1 meter = 1 pixel, such that the object accelerates down at 9.8px/x^2. However, at a frameRate of 60, there's problems. I discovered that I had to do G.mult(someFactor) to make it accurate. Here's the formula that made it work:

``````function fS(n) {
total = 0;
for (var i = 0; i <= n; i++) {
total += i;
}
return 1/(total*2);
}

someFactor = fS( frameRate() );
``````

I also have a simScale variable that changes the meters/pixels ratio, and currently it's messing up the physics i.e it only produces the right outputs when its equal to 1 (1m = 1px). Here's the entire code, looking for suggestions as to how to improve.

=======================================

``````function fS(n) {
total = 0;
for (var i = 0; i <= n; i++) {
total += i;
}
return 1/(total*2);
}

function setup() {
counter = 0;
fR = 60;
frameRate(fR);
W = windowWidth;
H = windowHeight;
ground = H;
simScale = 1;
frameScale = fS(fR);
G = createVector(0, 9.8);
G.mult(simScale);

createCanvas(W, H);
ball = new Ball();
}

function draw() {
background(2);
ball.show();
counter++;
}

function Ball() {

this.r = 10;

this.dropHeight = 123    // height in meters you want to drop from

this.initHeight = ground - this.dropHeight - this.r;
this.pos = createVector(0, this.initHeight / simScale);
this.acceleration = createVector(0, 0);
this.velocity = createVector(0, 0);
this.altitude = ground - this.pos.y - this.r;

this.updatePos = function() {
var scaledG = p5.Vector.mult(G, frameScale);
if (this.pos.y > ground - this.r) {
this.pos.y = ground - this.r;
noLoop();
}
this.altitude = ground - this.pos.y - this.r;
this.acceleration.mult(0);
}

this.show = function() {
this.updatePos();
ellipse(W/2, this.pos.y, this.r*2, this.r*2);
fill(200);
text("Scale: 1m = " + simScale + " px(s)", 200, 30);
text("Altitude: " + (this.altitude/simScale).toFixed(2) + " m", 20, 30);
text("Elapsed: " + (counter/fR).toFixed(2) + " s", 20, 50);
text("Displacement: " + Math.abs(this.initHeight - this.pos.y).toFixed(2) + " m", 20, 70);
text("Velocity: " + (this.velocity.y * fR).toFixed(2) + " m/s", 20, 90);
}

}
``````
Tagged:

• Looks like you're increasing the acceleration each frame.
Constant acceleration would be more accurate.

• edited October 2017

For each frame, I'm adding gravitational acceleration to the this.acceleration vector, and then applying that to the velocity vector, and then zeroing out this.acceleration `this.acceleration.mult(0)`, that way acceleration is constant, and velocity compounds.

@lorensheets If you want an accurate simulation then don't rely on the framerate for animation timing. Instead use time-based animation.

• :-O

THANKS!

• @lorensheets you're right my bad

• Euler Integration
• Verlet Integration
• Runge-Kutta Integration

https://gafferongames.com/post/integration_basics

https://gafferongames.com/post/fix_your_timestep

some nice WebGL demos:

• T_D, perfect, thank you. This is exactly what I need.