I am relatively new to programming, only a few months at university. I am trying to create a gravity field strength visualization pygame program. For that I have a function which calculates the gravity field at each pixel due to a certain number of masses randomly distributed around the given screen. This function is a modified version of my gravitational force calculator, it calculates the total gravitational force experienced by a mass due to a certain number of masses and it works as expected. The field calculator function is similar but slightly modified, although, when I print the 2D array, which contains the same amount of elements as pixels in the screen of pygame, all elements are 0 apart from the bottom row and I cannot seem to figure out why.
#Function to calculate gravitational field at each point on the screen caused by all other masses whose mass and positions are defined in lists along with the size of the screen
def gravfield(mass, x, y, screen_width, screen_height):
#Define screen position points
x_screen = list(range(screen_width))
y_screen = list(range(screen_height))
#Define array containing all field magnitudes at each pixel position of the screen
field = np.zeros((screen_width, screen_height))
#Calculate the gravitational field from each mass by the vector method
for i in range(len(x_screen)):
for n in range(len(y_screen)):
#Define lists which contains the field contributions of each mass
x_fields = []
y_fields = []
for j in range(len(mass)):
#Calculate position vector from the mass causing the field to the point affected
x_distance = x[j] - x_screen[i]
y_distance = y[j] - y_screen[n]
#Calculate distance between the mass and point and also provide a unique value to the pixel which contains the ball to prevent division by zero
distance = np.sqrt((x_distance**2) + (y_distance**2))
if distance == 0:
x_fields = 0
y_fields = 0
else:
#Calculate the unit vector of the shortest path between the mass and point
x_unit_vector = x_distance / distance
y_unit_vector = y_distance / distance
#Calculate magnitude of the field
magnitude = (G * mass[j] * 1) / (distance ** 2)
#Calculate the component of the field in each direction and add them to a list which contains field components caused by all the other masses
x_field = (magnitude * x_unit_vector)
y_field = (magnitude * y_unit_vector)
x_fields.append(x_field)
y_fields.append(y_field)
#Sum all the field components in each direction to get the resultant field and then its magnitude which is assigned to an array where each position corresponds to a pixel on the screen
gx = sum(x_fields)
gy = sum(y_fields)
g = np.sqrt((gx**2) + (gy**2))
field[n, i] = g
return field
This is my current field function, it takes a list of masses, their coordinates and the dimensions of the screen and returns a field array from numpy where each element corresponds to a pixel on the screen. I expected the values to not be all zeros almost everywhere. I tried using a screen of 100x100 with one mass at (50, 50) with a mass of 6,000,000,000,000 but still nothing.
You need to vectorise, which basically means deleting all of your code. Numpy is not intended to run in Python loops (the loops are written for you in C).
The choice of pygame is questionable, depending on what you're doing; I demonstrate with matplotlib instead.
Don't define G yourself; import it from scipy.