From a0b673afc1ca7f6ba684fdaaf4af8cff6bbf69c0 Mon Sep 17 00:00:00 2001 From: Justyna Ilczuk Date: Thu, 27 Dec 2012 12:06:08 +0100 Subject: [PATCH] More user friendly. Instructions and so on ^^ --- rutherford.py | 152 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 122 insertions(+), 30 deletions(-) diff --git a/rutherford.py b/rutherford.py index 5870404..917e41e 100644 --- a/rutherford.py +++ b/rutherford.py @@ -1,5 +1,5 @@ from __future__ import division -from math import sqrt, ceil +from math import sqrt, ceil, atan, sin, cos import random, pygame, sys import os import json @@ -15,57 +15,68 @@ BLUE = (30, 30, 180) VERYLIGHT = (210, 210, 210) BLACK = (0,0,0) WHITE = (255, 255, 255) +GRAYISH = (210, 210, 255) TIME_STEP = 0.01 -K = 10000 +K = 50000 X_SCREEN_BORDER = 1200 Y_SCREEN_BORDER = 800 -INITIAL_SPEED_X = 50 +INITIAL_SPEED_X = 200 INITIAL_SPEED_Y = 0 INITIAL_Y = 400 DEFAULT_OLD_X = 2 - INITIAL_SPEED_X*TIME_STEP DEFAULT_OLD_Y = INITIAL_Y - INITIAL_SPEED_Y*TIME_STEP +BEAM_WIDHT = 20 def main(): #create the screen window = pygame.display.set_mode((1200, 800)) colors = [GRAY, VIOLET, RED, GREEN, BLUE, VERYLIGHT, BLACK] - global INITIAL_SPEED_X - global INITIAL_SPEED_Y - global INITIAL_Y + settings = SimulationSettings(K, TIME_STEP, INITIAL_Y, INITIAL_SPEED_X, BEAM_WIDHT, colors) #Initialize universe with some atoms - atom1 = Particle(1000, Vector2(500,500), Vector2(500,500), 20, BLUE) - atom2 = Particle(1, Vector2(2,400), Vector2(2-TIME_STEP*INITIAL_SPEED_X, INITIAL_Y- TIME_STEP*INITIAL_SPEED_Y), 1, RED) - universe = Universe([atom1, atom2]) + universe = Universe(settings) screen = Screen(window, colors, universe) screen.draw_surface() keep_running = True + simulation_running = True while keep_running: - screen.draw_surface() - universe.update_positions() + if(simulation_running): + screen.draw_surface() + universe.update_positions() + else: + screen.draw_static_surface() + for event in pygame.event.get(): if event.type == pygame.QUIT: keep_running = False elif event.type == pygame.KEYUP: if event.key == K_UP : - INITIAL_Y -= 10 + universe.settings.initial_y -= 10 elif event.key == K_DOWN: - INITIAL_Y += 10 + universe.settings.initial_y += 10 elif event.key == K_RIGHT: - INITIAL_SPEED_X += 20 + universe.settings.speed_x += 20 elif event.key == K_LEFT: - INITIAL_SPEED_X -= 20 - if(INITIAL_SPEED_X < 0): - INITIAL_SPEED_X = 0 + universe.settings.speed_x -= 20 + if(universe.settings.speed_x < 0): + universe.settings.speed_x = 0 elif event.key == K_SPACE: - universe.add_particle(Particle(1, Vector2(2,INITIAL_Y), - Vector2(2-TIME_STEP*INITIAL_SPEED_X, INITIAL_Y- TIME_STEP*INITIAL_SPEED_Y), - 1, random.choice(colors))) + universe.add_particle() + elif event.key == K_h: + if(universe.settings.show_instructions): + universe.settings.show_instructions = False + else: + universe.settings.show_instructions = True + elif event.key == K_RETURN: + if(simulation_running): + simulation_running = False + else: + simulation_running = True print "Pygame thread exited." @@ -89,18 +100,71 @@ class Screen: for particle in self.universe.particles: self.draw_particle(particle) + def draw_static_universe(self): + self.draw_guide() + for particle in self.universe.particles: + self.draw_particle(particle) + for x in range(1, len(self.universe.particles)): + self.draw_particle_vector(self.universe.particles[x]) + def draw_particle(self, particle): position = (int(ceil(particle.position.x)), int(ceil(particle.position.y))) pygame.draw.circle(self.window, particle.color, position, 6+ int(particle.mass/100) ) + def draw_particle_vector(self, particle): + factor = 20 + arrow_head_x = 0.50 + arrow_head_y = 0.30 + start_position = (particle.position.x, particle.position.y) + end_position = (int((particle.position.x - particle.old_position.x)*factor +particle.position.x), + int((particle.position.y -particle.old_position.y)*factor + particle.position.y)) + + pygame.draw.aaline(self.window, BLUE, start_position, end_position, 4) + pygame.draw.circle(self.window, RED, end_position, 2) def draw_guide(self): - pygame.draw.line(self.window, BLACK, (0, INITIAL_Y), (X_SCREEN_BORDER,INITIAL_Y), 2) + y = self.universe.settings.initial_y + for x in range(0, 39, 2): + pygame.draw.aaline(self.window, BLACK, (X_SCREEN_BORDER*x/40, y), (X_SCREEN_BORDER*(x+1)/40, y), 4) + + + + def draw_static_surface(self): + self.window.fill(GRAYISH) + self.draw_static_universe() + description_of_simulation_settings = self.prepare_settings_description(self.universe.settings) + for i, text in enumerate(self.communicates + description_of_simulation_settings): + self.print_text(text, 20, 20 + i*20, (0, 0, 0), 24, self.window) + if(self.universe.settings.show_instructions): + for i, text in enumerate(self.universe.settings.instructions): + self.print_text(text, 350, 20 + i*20, (0, 0, 0), 24, self.window) + pygame.display.flip() + + def prepare_settings_description(self, settings): + description = [] + line = "K = {0:d}".format(settings.K) + description.append(line) + line = "Position of the beam is {0:d}".format(settings.initial_y) + description.append(line) + line = "Initial speed of the beam is {0:d}".format(settings.speed_x) + description.append(line) + line = "Width of the beam is {0:d}".format(settings.beam_width) + description.append(line) + line = "Time step is set to {0:f}".format(settings.time_step) + description.append(line) + line = "Press H to show/hide instructions" + description.append(line) + return description + def draw_surface(self): self.window.fill(self.color) self.draw_universe() - for i, text in enumerate(self.communicates): - self.print_text(text, 20, 20 + i*20, (0, 0, 0), 30, self.window) + description_of_simulation_settings = self.prepare_settings_description(self.universe.settings) + for i, text in enumerate(self.communicates + description_of_simulation_settings): + self.print_text(text, 20, 20 + i*20, (0, 0, 0), 24, self.window) + if(self.universe.settings.show_instructions): + for i, text in enumerate(self.universe.settings.instructions): + self.print_text(text, 350, 20 + i*20, (0, 0, 0), 24, self.window) pygame.display.flip() def print_text(self, text,xx,yy,color,text_size, screen): @@ -125,10 +189,30 @@ class Particle: self.color = color self.charge = charge +class SimulationSettings: + def __init__(self, K, time_step, initial_y, speed_x, beam_width, colors): + self.K = K + self.time_step = time_step + self.initial_y = initial_y + self.speed_x = speed_x + self.beam_width = beam_width + self.colors = colors + self.show_instructions = True + self.instructions = [ "Instructions:", + "To change speed, use right and left arrow keys", + "To change position of the beam, use up and down arrow keys", + "To add particle, press space", + "To stop/restart simulation, press enter"] + class Universe: - def __init__(self, particles): - self.particles = particles + def __init__(self, settings): + self.settings = settings + atom1 = Particle(1000, Vector2(500,500), Vector2(500,500), 20, BLUE) + atom2 = Particle(1, Vector2(2,400), Vector2(2-TIME_STEP*INITIAL_SPEED_X, + INITIAL_Y- TIME_STEP*INITIAL_SPEED_Y), 1, RED) + + self.particles = [atom1, atom2] print("Universe has just been created!") def update_accelerations(self): @@ -154,11 +238,13 @@ class Universe: def limit_position(self, particle): if(particle.position.x > X_SCREEN_BORDER or particle.position.y > Y_SCREEN_BORDER or particle.position.x < 0 or particle.position.y < 0): - random_offset = random.randrange(-20, 20) + y = self.settings.initial_y + speed = self.settings.speed_x + random_offset = random.randrange(-self.settings.beam_width, self.settings.beam_width) particle.position.x = 2 - particle.old_position.x = 2 - INITIAL_SPEED_X*TIME_STEP - particle.position.y = INITIAL_Y + random_offset - particle.old_position.y = INITIAL_Y - INITIAL_SPEED_Y*TIME_STEP + random_offset + particle.old_position.x = 2 - speed*self.settings.time_step + particle.position.y = y + random_offset + particle.old_position.y = y + random_offset return particle def compute_acc(self, particle1, particle2): @@ -172,7 +258,13 @@ class Universe: acc2y = -force/particle2.mass*vertical_distance/distance return [Vector2(acc1x, acc1y), Vector2(acc2x, acc2y)] - def add_particle(self, particle): + def add_particle(self): + y = self.settings.initial_y + speed = self.settings.speed_x + colors = self.settings.colors + random_offset = random.randrange(-self.settings.beam_width, self.settings.beam_width) + particle = Particle(1, Vector2(2, y + random_offset), + Vector2(2-self.settings.time_step*speed, y + random_offset), 1, random.choice(colors)) self.particles.append(particle)