#!/usr/bin/env python # Animation Template. User must define a mydraw(brush,gc) # Canonical Version of Spring 2008. import pygtk import gtk import gobject import time import threading from random import * width,height = 900,700 delaytime = 50 # millisecond delay between animation frames window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.set_title("Simplified Drawing Example") window.connect("destroy", lambda w: gtk.main_quit()) area = gtk.DrawingArea() area.set_size_request(width,height) window.resize(width,height) window.add(area) window.show_all() window.move(0,0) gc0 = area.window.new_gc() cmap = gc0.get_colormap() # common colors green = cmap.alloc_color(red=0,green=65535,blue=0) blue = cmap.alloc_color(red=0,green=0,blue=65535) red = cmap.alloc_color(red=65535,green=0,blue=0) white = cmap.alloc_color("white") black = cmap.alloc_color("black") gray = cmap.alloc_color("gray") yellow = cmap.alloc_color("yellow") purple = cmap.alloc_color("purple") gc0.set_foreground(green) gc0.set_background(blue) gc0.line_width = 1 # double buffering setup dbuf = gtk.gdk.Pixmap(area.window,width,height,-1) gc1 = dbuf.new_gc() gc1.set_colormap(cmap) ### Thread control syn = threading.Event() # throttles mainloop syn2 = threading.Event() # throttles user thread syn.clear() syn2.clear() stopall = False # for cleanup class MyThread ( threading.Thread ): def __init__(self,brush,gc): self.win = brush self.dgc = gc threading.Thread.__init__(self) def run ( self ): global mydraw mydraw(self.win,self.dgc) eehandler = 0 def area_expose_cb(area, event): global mainloop,eehandler my = MyThread(dbuf,gc1) my.start() # start student thread, which calls mydraw area.handler_block(eehandler) # prevent restart when window moves. mainloop(area.window) # start main animation refresh cycle return True # get ready for expose event eehandler = area.connect("expose_event", area_expose_cb) # animation refresh control loop: def mainloop(brush): if not stopall: syn.wait() # wait for permission to refresh screen syn.clear() # reset for next round brush.draw_drawable(gc0,dbuf,0,0,0,0,width,height) # refresh syn2.set() # informs user thread to goto next iteration eid = gobject.timeout_add(delaytime, mainloop, brush) # reschedule return False # end mainloop def updateDisplay(): syn.set() # release mainloop to refresh screen syn2.wait() # synch with mainloop before looping again syn2.clear() # reset for next round # end updateDisplay def cleanup(): global stopall stopall = True syn.set() syn2.set() # end cleanup # easier to use functions for drawing circle/sphere def drawcircle(brush,gc,x,y,radius,fill): brush.draw_arc(gc,fill,x-radius,y-radius,2*radius,2*radius,0,360*64) ######################## YOUR CODE GOES BELOW ############################ # distance function def dist(x1,y1,x2,y2): dx = x1-x2 dy = y1-y2 return (dx*dx + dy*dy)**0.5 #dist # collide - skip floating point comps def collide(x1,y1,x2,y2,r1,r2): dx = abs(x1-x2) dy = abs(y1-y2) if (dx(width-radius)): x = radius # right to left if (y(height-radius)): y = radius # bottom to top return (x,y) #wraparound #### Class for a sphere class sphere: def __init__(self,x0,y0,r0,c0): self.X = x0 # center coordinates self.Y = y0 self.R = r0 # radius self.C = c0 # color self.DX = 0 # initial zero movement vector self.DY = 0 # init def setvector(self,cx,cy): # set movement vector self.DX = cx self.DY = cy # setvector def move(self): # move according to movement vector self.X += self.DX self.Y += self.DY self.X,self.Y = wraparound(self.X,self.Y,self.R) #move def draw(self,brush,gc): # draw with graphical context to buffer gc.set_foreground(self.C) # set color drawcircle(brush,gc,self.X,self.Y,self.R,True) # draw def collide(self,B): # detect and effect collision with sphere B ds = dist(self.X,self.Y,B.X,B.Y) # distance if ds <= self.R+B.R: # collision detected self.DX,B.DX = B.DX,self.DX # swap movement vectors self.DY,B.DY = B.DY,self.DY # collide # class sphere ##### A function called 'mydraw' must be defined: def mydraw(brush,gc): # animate n spheres n = 8 # number of spheres to animate colors =[red,green,blue,white,purple,yellow] # available colors S=[] # array of spheres # Initial loops to set up spheres: i = 0 # loop counter while i