#!/usr/bin/env python """ particles "cannon" screen saver written by Felix "Albert" Liard """ from graphics import * from random import * from time import * class Particle: def __init__(self, window, colors, x=0, y=0): # position self.px = x self.py = y # direction self.dx = randint(5,25) self.dy = randint(-10,10) self.size = randint(4,25) self.color = colors[randint(0,len(colors)-1)] # once in a while... BIG & FAST particle if randint(1,100) == 42: # 42 = answer to everything! self.size = 50 self.dx = 25 circle = Circle(Point(x,y),self.size) circle.setOutline(self.color) circle.setFill(self.color) circle.draw(window) self.circle = circle # logical particle obj to physical circle def destroy(self, particles_list): del particles_list[self.circle] # remove obj from dictionary self.circle.undraw() # delete from screen del self.circle # remove physical object too! del self def initialize_window(sizex,sizey,color='black'): w = GraphWin('Particles Cannon',sizex,sizey) w.setCoords(0,0,sizex,sizey) w.setBackground(color) seed() return w def read_colors(): colors = [] with open('tclTK-colors.txt','r') as file: for line in file: (color,_) = line.strip().split(' ',1) colors.append(color) return colors def main(): particles_list = {} maxX = 1920 maxY = 500 Yorigin = 0 Ydirection = 'UP' colors = read_colors() window = initialize_window(maxX,maxY) for _ in range(100): # start with 100 objects particle = Particle(window, colors, 0, Yorigin) particles_list[particle.circle] = particle while True: # keep generating new particles as old ones leave screen particle = Particle(window, colors, 0, Yorigin) particles_list[particle.circle] = particle # origin of particle goes up/down along Y axis.. cool effect if Yorigin <= 0: Ydirection = 'UP' if Yorigin >= maxY: # reverse when @top Ydirection = 'DOWN' Yorigin += 10 if Ydirection == 'UP' else -10 # update position of all existing particles # c = phys circle, p = logical particle obj for c,p in particles_list.items(): # EDGE detect, if not at edge keep moving if 0 < p.px+p.dx < maxX and 0 < p.py+p.dy < maxY: p.px += p.dx p.py += p.dy # if at Y edge then alter course to "bounce" if p.py+p.dy >= maxY or p.py+p.dy <= 0: p.dy = -(p.dy) p.py += p.dy c.move(p.dx,p.dy) #...finally, draw circle at next position # destroy when X edge reached (far left off-screen or far right) if p.px+p.dx >= maxX or p.px < -50: p.destroy(particles_list) if __name__ == '__main__': main()