1

So im trying to simulate gravity between 2 (and hopefully more) planets in python using pygame. I've run itto 3 main problems that i just can't seem to figure out. The first one is that the small moon that im trying to simulate first just goes towards the big planet completely wrong, if you copy paste the code below you can see that it goes 45 degrees up utnil they're at the same y-axis and then goes right inside the planet. I'm pretty sure that isn't how gravity work. The 2nd problem is that i don't know how i could add a start-velocity to the moon so that its actually capable of going into orbit. The 3rd problem is that I have no clue how to add more planets/moons without really long lines of code. Any help would be appreaciated! Code:

import pygame
import math
''
w = 1280
h = 720
g = 25
def main():
 pygame.init()
 running = True
 xm1 = float(200)
 ym1 = float(660)
 xm2 = float(w/2)
 ym2 = float(h/2)
 mass1 = int(10)
 mass2 = int(100)
 while running:
 screen = pygame.display.set_mode((w, h))
 pygame.draw.circle(screen, (0, 255, 0), (xm1, ym1), 15, 15)
 pygame.draw.circle(screen, (255, 0, 0), (xm2, ym2), 45, 45)
 distance = math.sqrt((xm1-xm2)**2 + (ym1-ym2)**2)
 if ym1 > ym2:
 ym1 += g * mass2 / -distance ** 2
 else:
 ym1 -= g * mass2 / -distance ** 2
 if ym1 < ym2:
 ym2 += g * mass1 / -distance ** 2
 else:
 ym2 -= g * mass1 / -distance ** 2
 if xm1 > xm2:
 xm1 += g * mass2 / -distance ** 2
 else:
 xm1 -= g * mass2 / -distance ** 2
 if xm1 < xm2:
 xm2 += g * mass1 / -distance ** 2
 else:
 xm2 -= g * mass1 / -distance ** 2
 if distance <= 60:
 running = False
 pass
 pygame.display.update()
main()
asked Nov 14, 2020 at 17:07
4
  • 2
    Here's a small hint for you: There are no "if" statements in nature. Gravity – as every other force – does not have conditionals. When simulating things, you'll encounter conditionals mostly to deal with collisions, but that's just because the fundamental physics of collisions happens on such small scales (electromagnetic fields acting between atoms) and such large numbers of particles involved, that you can't practically do it numerically. Commented Nov 14, 2020 at 17:17
  • I think you need to research how to simulate the effect of gravity between two untethered masses - I’d have thought the initial x and y velocity of the masses matters rather a lot, and also the time interval to update the simulation. For linear movement v=u+at Commented Nov 14, 2020 at 17:18
  • @datenwolf Yes I'd like to not use if statements but whenever one of the objects passes each others x or y position i have to substract and not add force and I don't think i could do that without if statements. I probably have to just start over and think of another way of doing it because i don't think thiis way will work Commented Nov 14, 2020 at 17:31
  • @Noah9111: No, you don't have to switch between adding/subtracting. You only add. The gravitational force between two masses as a vector is F = (r-R)·m·M·G / distance(r,R)³, where r and R are the position vectors. Note the use of the exponent in the denominator being 3, so that with the vector difference in the numerator you get the inverse square law (G is the gravitational constant). Commented Nov 14, 2020 at 17:36

2 Answers 2

2

I rewrote your code so that it actually simulates free fall as described by Newton's laws. Never mind, that this naive implementation is terribly unstable, numerically for small distances. Essentially this is numerically integrating a differential equation, and some method like by Runge-Kutta or similar should be applied. Anyway, the gist is

def gravity(m1,r1,m2,r2):
 d = vsub(r2,r1);
 return vmul(d, m1*m2/(vlen(d)**3))
def main():
 pygame.init()
 screen = pygame.display.set_mode((w, h))
 running = True
 r1 = (200., 660.)
 r2 = (w/2., h/2.)
 v1 = ( 0.3, 0)
 v2 = (-0, 0)
 m1 = 10.
 m2 = 100.
 while running:
 screen.fill((0,0,0))
 pygame.draw.circle(screen, map(int, (0, 255, 0)), map(int, r1), 15, 15)
 pygame.draw.circle(screen, map(int, (255, 0, 0)), map(int, r2), 45, 45)
 F = gravity(m1,r1,m2,r2)
 v1 = vadd(v1, vmul(F, G/m1));
 v2 = vadd(v2, vmul(F, -G/m2));
 r1 = vadd(r1, v1)
 r2 = vadd(r2, v2)
 pygame.display.update()
main()

I'll leave it as an exercise for you to implement the vadd, vsub, vmul, and vlen functions.

answered Nov 14, 2020 at 18:10
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much! I'll try to add the other functions myself
0

To your 3rd Question if didn't find a solution yourself and the anwer isn't too late, classes would help

It would be something like that:

class Planetary_objekt():
 def __init__(mass = 1,
 x = 0, y = 0,
 velocity = [0,0],
 color = 255,255,255,
 radius = 100
 ):
 self.mass = mass
 self.x = x
 self.y = y
 self.x_velocity = velocity[0]
 self.y_velocity = velocity[1]
 
 def draw(self):
 pygame.draw.circle(screen, map(int, self.color), map(int, self.radius), self.x, self.y)
answered Jun 19, 2022 at 14:14

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.