Creating a Solar System Simulation with Python and Pygame
This project is a fantastic demonstration of using object-oriented programming to create infinitely scalable programs by instantiating classes based on various sets of data. Ready to explore the galaxies from the comfort of your home? Let’s get started!
Here’s what you can expect by the end of this tutorial:
If you’re eager to grab the code for yourself to run it or use it for your projects, you can find the GitHub repo here.
Step 1: Setting Up the Basics
We begin by importing essential modules such as math
and random
which are used for calculating ‘orbits’ and setting initial positions for various celestial bodies. To bring our simulation to life on screen, we’ll use Pygame. We also import json
to manage our configuration files conveniently.
from math import sin, cos, pi, radians
from random import randrange, uniform
import pygame as pg
import json
Our simulation reads two JSON files, settings.json
and bodies.json
. The settings.json
file contains essential settings for our Pygame display, while the bodies.json
file holds the data for the celestial bodies in our solar system, such as size, colour, distance from the sun, velocity, etc. Make sure these files are in the same directory as your Python file for these relative imports to work.
with open("settings.json", "r") as file:
SETTINGS = json.load(file)
with open("bodies.json", "r") as file:
BODIES = json.load(file)
#SETUP WINDOW
FPS = SETTINGS["Screen"]["FPS"]
WIN = pg.display.set_mode((SETTINGS["Screen"]["Width"], SETTINGS["Screen"]["Height"]), pg.RESIZABLE)
pg.display.set_caption(SETTINGS["Screen"]["Title"])
Step 2: Creating Classes for Our Simulation
We define a MoveableCameraGroup
class to handle camera movements. This class is important because it allows users to interact with the simulation through mouse inputs. It also controls the zoom function and the camera reset operation, handled by the space bar press. Additionally, it handles the creation of celestial bodies such as stars, asteroids, planets, and moons.
class MoveableCameraGroup(pg.sprite.Group):
"""
SPRITE GROUP SUBCLASS TO HANDLE MOUSE INPUTS AS OFFSETS FOR A 'CAMERA'
- CLICK AND DRAG CAMERA
- SCROLL WHEEL ZOOM
- SPACE BAR TO RESET POSITIONS
"""
def __init__(self, SETTINGS):
super().__init__()
self.SETTINGS = SETTINGS
self.incriment_up = SETTINGS["Scales"]["Incriments"]["Up"]
self.incriment_down = SETTINGS["Scales"]["Incriments"]["Down"]
self.offset = pg.math.Vector2() #TO APPLY TO SPRITES
self.clickstart_offset = pg.math.Vector2() #NORMALISE AFTER CLICK
self.dragging = False #WHEN TO APPLY OFFSET TO SPRITES
self.reset_scales()
self.astroid_distance_start = BODIES["Asteroids"]["Distance"]["Start"]
self.astroid_distance_end = BODIES["Asteroids"]["Distance"]["End"]
#... GET FULL CODE ON GITHUB: https://github.com/jmwhitworth/Pygame-Solar-System
Step 3: Creating Objects for Stars and Celestial Bodies
Stars in our simulation are objects of the star
class, which is a subclass of Pygame’s Sprite
class. Each star has properties such as size, position, and colour. This basic class allows stars to be statically generated and displayed in any single location on the viewport.
class star(pg.sprite.Sprite):
def __init__(self, sprite_group, name, size, x, y, colour):
super().__init__(sprite_group)
self.sprite_group = sprite_group
self.base_size = size
self.base_radius = 0
self.base_velocity = 0
self.size = self.base_size * self.sprite_group.scale_size
self.radius = 0
self.velocity = 0
self.name = name
self.x = x
self.y = y
self.colour = colour
self.surface = pg.display.get_surface()
#... GET FULL CODE ON GITHUB: https://github.com/jmwhitworth/Pygame-Solar-System
Celestial bodies that orbit around other bodies, such as planets and their moons, are objects of the satellite
class. This is a subclass of the star
class. These bodies use the star
classes basic properties such as colour and position, but they also have additional properties like orbit radius and velocity. This arrangement allows us to create moving sprites without duplicating code.
class satellite(star):
def __init__(self, sprite_group, name, parent_name, size, radius, velocity, colour):
super().__init__(sprite_group, name, size, 0, 0, colour)
self.base_radius = radius
self.base_velocity = velocity
self.radius = self.base_radius * sprite_group.scale_distance
self.velocity = self.base_velocity * sprite_group.scale_velocity
self.parent = sprite_group.get_body_by_name(parent_name)
self.center_of_rotation_x = self.parent.x
self.center_of_rotation_y = self.parent.y
self.angle = radians(uniform(0,360))
self.x = self.center_of_rotation_x + self.radius * cos(self.angle)
self.y = self.center_of_rotation_y - self.radius * sin(self.angle)
#... GET FULL CODE ON GITHUB: https://github.com/jmwhitworth/Pygame-Solar-System
Step 4: Executing Our Simulation
Lastly, our main function, run(), creates a MoveableCameraGroup object and populates it with celestial bodies, using the data from our bodies.json file. It then enters a loop where it updates the screen, handles events, and applies camera controls.
This run function is then called using an if statement that ensures the code is only executed when this Python file is called directly, allowing this Python file and its classes to be imported into other files if required.
def run():
visible_sprites = MoveableCameraGroup(SETTINGS)
visible_sprites.create_sprites()
clock = pg.time.Clock()
run = True
while run:
clock.tick(FPS)
WIN.fill((0, 0, 0))
visible_sprites.update()
pg.display.update()
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
visible_sprites.camera_controller(event)
quit()
if __name__ == '__main__':
run()
To execute the program, navigate to the directory containing your Python file in your terminal and type python filename.py
.
Conclusion
Now that you have successfully created your solar system simulation, feel free to experiment with the code and see what other celestial bodies you can add or customize.
Remember, coding is all about problem-solving and creativity. The integration of Python with Pygame provides a powerful and flexible platform to create stunning simulations like our solar system simulation.
If you run into any common errors such as file not found, make sure your JSON files are in the same directory as your Python file.
Thanks for joining us on this cosmic journey! Don’t forget to check out the GitHub repo for the full code of this project. Explore the solar system from your computer screen and let us know what cool modifications you make!
Leave a Reply