pygame tutorial example simulation Trinity

Keywords: Python

This tutorial uses Python 3
Reading this article requires some simple physics knowledge.

In the last chapter, we wrote about a small ball bouncing repeatedly under the action of gravity. Now we can simulate the three-body movement.
Three-body motion refers to the motion under the interaction of three celestial bodies with little difference in mass.

I. Define some constants and initialization

from sys import exit
import pygame, math
from pygame.color import *

G     = 900  # Gravitational constant
FPS   = 50   # Frame rate
exact = 50   # Each frame is computed several times, the more times the more accurate, it is dynamic.

pygame.init()  # Initialize pygame
screen = pygame.display.set_mode((640, 480), pygame.DOUBLEBUF, 32)
pygame.display.set_caption("Simulated trisomy")
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 16)

Definition of planetary classes

class Star():
    x , y  = 0, 0  # coordinate
    vx, vy = 0, 0  # Velocity in the X and Y directions
    ax, ay = 0, 0  # Acceleration in the X and Y directions
    m = 0  # quality
    r = 10 # radius

    def __init__(self, x, y, vx, vy, m):
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.m = m

    def set_a(self, other_star):
        '''
        //CALCULATION OF GRAVITY ACCELERATION BETWEEN star AND other_star
        '''
        d_2 = (self.x - other_star.x) ** 2 + (self.y - other_star.y) ** 2
        _x = [-1, 1][self.x < other_star.x]
        _y = [-1, 1][self.y < other_star.y]
        if d_2 != 0:
            a = G * self.m * other_star.m / d_2
        else:
            a = 0
        if self.x != other_star.x:
            ax_ = math.sqrt(a ** 2 / (((self.y - other_star.y) / (self.x - other_star.x)) ** 2 + 1))
            self.ax += ax_ * _x
            self.ay += math.sqrt(a ** 2 - ax_ ** 2) * _y
        else:
            self.ay += a * _y

    def run(self, time):
        '''
        //Location after calculating time time time
        :param time:Time, second 
        :return: 
        '''
        self.ax /= self.m
        self.ay /= self.m
        self.vx += self.ax * time
        self.vy += self.ay * time
        self.x += self.vx * time
        self.y += self.vy * time

3. Setting up Three Planets

star_list = []
dd = 0.00001
star_list.append(Star(200, 300,-30,-math.sqrt(3)*30, 1000))
star_list.append(Star(400, 300,-30, math.sqrt(3)*30, 1000))
star_list.append(Star(300, 300-math.sqrt(3)*100+dd, 60, 0, 1000))

IV. Main Cycle

# Computation of Gravitational Acceleration
def set_a(star_list):
    for i, star in enumerate(star_list):
        star.ax, star.ay = 0, 0
        for j, other_star in enumerate(star_list):
            if i != j:
                star.set_a(other_star)

# Game Main Cycle
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            # Exit the program after receiving the exit time
            exit()

    for i in range(exact):
        set_a(star_list)
        for star in star_list:
            star.run(1 / FPS / exact)
    # Draw the background picture on it.
    screen.fill((0, 0, 0))
    max_v = 0
    for star in star_list:
        max_v = max(max_v, math.sqrt(star.vx**2+star.vy**2))
        pygame.draw.circle(screen, (255, 0, 0), (int(star.x), int(star.y)), star.r)
    exact = min(300,max(30,int(max_v)))*5
    screen.blit(font.render("fps: " + str(clock.get_fps()), 1, THECOLORS["white"]), (0,0))
    screen.blit(font.render("exact: " + str(exact), 1, THECOLORS["white"]), (0,15))

    # Refresh screen
    pygame.display.update()
    time_passed = clock.tick(FPS)

V. Final Effect Chart

A little faster.

Posted by newbeee on Fri, 04 Oct 2019 13:53:53 -0700