# [SOLVED] Newtonian gravity

Attention Topic was automatically imported from the old Question2Answer platform.

Morning all, I’ve just started with godot and thought I’d make a procedural solar system to get to grips with it and I’ve somehow managed to make anti-gravity! My poor little procedural planets are pushing apart…

``````func gravity(delta, obj):
distance = target_position - current_position
direction = distance.normalized()
acceleration = direction * GRAVITY * mass / (distance*distance)
current_position += acceleration * delta
current_position = get_child(1).move_and_slide(current_position)
``````

My target / current positions are the Vector3 of the global origins. So, all I want to do is the classic Fg = Gm1m2/r^2 which expands to M1A = GM1*M2/r^2, M1 cancels giving A = G * M / r^2 which I multiply by the direction. What I don’t get is that minusing the direction doesn’t change anything…

This is my first project so I’m sure it’s just a schoolboy error.

Thanks!

Think I’m on the road to the answer, looks like I’ve mixed up my translation with my basis. Let me see if I can solve this.

Surely this isnt the issue, but i think you should multiply acceleration by squared delta to get position.
Edit: Oh, i see you are using `current_position` in `move_and_slide`. Move and slide should take a velocity as parameter, and returns the updated velocity. You are updating `current_position`, and then using it as a position to get the direction. I mean, you are using `current_position` sometimes as velocity and sometimes as position. Do you have a minimal project to reproduce this on my machine?

p7f | 2020-07-23 14:06

Yeah, saw that thanks, silly mistake - that’s what I mean’t by mixing up my translation with my basis, on `current_position` - here’s the latest version.

``````func gravity(delta, obj):
distance = target_position - current_position
direction = distance.normalized()
acceleration = direction * GRAVITY * mass / (distance * distance)
if acceleration.x != acceleration.x:
acceleration.x = 0.0
if acceleration.y != acceleration.y:
acceleration.y = 0.0
if acceleration.z != acceleration.z:
acceleration.z = 0.0
velocity += acceleration * delta
velocity = get_child(1).move_and_slide(velocity)
current_position += velocity
``````

It’s definitely distance and not acceleration that needs squaring. I’m just testing this now, suspect something is still wrong.

I had to hack a fix here, when the objects were aligned on an axis the distance would be zero, eg `Vector3(0, 0, 100)` and I was getting a div by zero error so I had to add the ugly `if acceleration.z != acceleration.z:` and use the fact it’s not addressing a memory location as a bool. If you know a more elegant solution I’d appreciate it.

Right, fixed the problem and I now have orbiting planets.

If anyone is interested the above had two mistakes:

1. I passed distance in as a Vector3. This caused problems every time the planet passed an axis, distance would fall to or near zero and acceleration would go off the charts. Instead I just used distance_to and passed in a float.
2. I was updating current_position in the loop. Ordinarily that would be fine (says he who’s been coding Godot for a week!) but because gravity has 11 decimal points and the mass of the moon was 1 * 10^18 we get floating point rounding errors which accumulate so instead I picked up the values afresh on each iteration. If I need more performance in the future what I could do is pass it back and then update it every tenth iteration or whatever to correct any drift. Anyway, it’s fine for now.

Really interesting little project.

cool you get it working! Would you mind posting the answer and selecting it so others can see its solved?

p7f | 2020-07-23 17:14

No probs, here you go:

``````func gravity(delta, obj_1, obj_2):
obj_1.velocity += (obj_2.global_transform.origin\
- obj_1.global_transform.origin).normalized()\
* GRAVITY * obj_2.mass\
/ pow((obj_2.global_transform.origin.\
distance_to(obj_1.global_transform.origin)), 2) * delta
obj_1.move_and_slide(obj_1.velocity)
``````

To solve an n body problem you just need to loop through each object in the scene and pass in the current object you’re evaluating as `obj_1` and then the second object as `obj_2.` Obviously, don’t forget to add an evaluation on the loop so that it doesn’t pass the same object as `obj_1` and `obj_2` - or you’ll have made a black hole!