In my last post, I added my own modifications to the tutorial Making Breakout by Leonel at codeNtronix. He also has a number of tutorials about drawing 3D graphics using python and pygame. I was intrigued by his simulation of a 3D Starfield made using Python and Pygame. (Thanks Leonel for creating such useful tutorials).
His simulation uses a few basic 3D to 2D algorithms, which I don’t fully understand but they are effective at creating the desired effect. He created this effect with just 80 lines of source code, Click here to download the full source code from CodeNTronics.
I analysed the code myself to see if I could recreate this simulation in Scratch.
Python code: 81 lines from CodeNTronics, with comments added by me.
# """ # 3D Starfield Simulation # Developed by Leonel Machava <firstname.lastname@example.org> # # http://codeNtronix.com # http://twitter.com/codentronix # """ import pygame, math from random import randrange class Simulation: def __init__(self, num_stars, max_depth): # SM- each star needs an individual variable for x,y,depth. pygame.init() # SM-- does a bunch of pygame stuff to set up screen and clock. self.screen = pygame.display.set_mode((640, 480)) pygame.display.set_caption("3D Starfield Simulation (visit codeNtronix.com)") self.clock = pygame.time.Clock() self.num_stars = num_stars self.max_depth = max_depth self.init_stars() # SM- Tells the program to make the list of stars def init_stars(self): """ Create the starfield """ self.stars =  for i in range(self.num_stars): # A star is represented as a list with this format: [X,Y,Z] star = [randrange(-25,25), randrange(-25,25), randrange(1, self.max_depth)] self.stars.append(star) def move_and_draw_stars(self): # """ Move and draw the stars """ SM Converts the xy coordinates to cartesian to centre stars on screen origin_x = self.screen.get_width() / 2 origin_y = self.screen.get_height() / 2 for star in self.stars: # The Z component is decreased on each frame. SM-- Star Moves closer star -= 0.19 # If the star has past the screen (I mean Z<=0) then we # reposition it far away from the screen (Z=max_depth) # with random X and Y coordinates. if star <= 0: star = randrange(-25,25) star = randrange(-25,25) star = self.max_depth # Convert the 3D coordinates to 2D using perspective projection. k = 128.0 / star # SM I don't know where Leonel got this constant 128/depth but it works x = int(star * k + origin_x) #SM-- moves starfield origin towards centre of screen y = int(star * k + origin_y) # Draw the star (if it is visible in the screen). # We calculate the size such that distant stars are smaller than # closer stars. Similarly, we make sure that distant stars are # darker than closer stars. This is done using Linear Interpolation. if 0 <= x < self.screen.get_width() and 0 <= y < self.screen.get_height(): size = (1 - float(star) / self.max_depth) * 5 shade = (1 - float(star) / self.max_depth) * 255 self.screen.fill((shade,shade,shade),(x,y,size,size)) def run(self): """ Main Loop """ while 1: # Lock the framerate at 50 FPS. self.clock.tick(50) # Handle events. for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() return self.screen.fill((0,0,0)) self.move_and_draw_stars() pygame.display.flip() if __name__ == "__main__": Simulation(256, 32).run()
The python program presents a much more realistic starfield and is much more versatile. But the scratch program accomplishes the same task in 1/4 the length and it is much easier for me to tinker with the variables and formulas to change the appearance in SCRATCH. It is an accomplishment that I can understand enough of Python to recreate the essential features of a program in SCRATCH. To use the analogy of spoken languages, I think that I have progressed to the point that I can understand a bit of what I read and hear in PYTHONESE, but I cannot yet speak it like a native. This is very good progress for 10 days. To extend the spoken language analogy, one of the common exercises for people learning a second language is to translate passages from one language to another. That is exactly what I attempted here, and I am quite satisfied with the results.