#!/usr/bin/ruby # Import the library. require 'tk' # Dot diameter. Diameter = 10 # Update rate (ms). Frequency = 25 # Canvas size. Width = 400 Height = 300 # Set defaults. Some we keep in constants to use later. BG = '#ccccff' TkOption.add('*background', BG) # Root window. root = TkRoot.new('background' => BG) { title 'Bouncy, Bouncy' } # Canvas. c = TkCanvas.new(root) { width Width height Height pack } # This is the circle that wanders around the canvas. class MovingCircle < TkcOval # Create with a moving circle on the canvas c with indicated color. def initialize(c, color) # Remember the canvas. @canv = c # Choose an initial location at random and create the object there. @xpos = rand(Width - Diameter) @ypos = rand(Height - Diameter) super(c, @xpos, @ypos, @xpos + Diameter, @ypos + Diameter, 'fill' => color) # Chose a velocity at random. 1 to 3 pixels per Frequency in each # dimension. @delx = (rand(3)+1)*(if rand(2) == 1 then 1 else -1 end) @dely = (rand(3)+1)*(if rand(2) == 1 then 1 else -1 end) # Start moving Tk.after(Frequency, proc { self.move } ) end # This adjusts a single dimension by one step, taking account of the # walls. Send a position, increment, and limit, and get back a new pos # and new increment (which might have its sign changed). def del(pos, inc, limit) # Move pos += inc # See if we hit the top or left, and reverse. if pos < 0 then pos = -pos inc = -inc # Likewise check for hitting the right or bottom elsif pos > limit - Diameter then pos = (limit - Diameter) - (pos - (limit - Diameter)) inc = -inc end # Send back the results. return pos, inc end # Move one step, then schedule the next move. def move # Remember current position, and compute the new one. oldx, oldy = @xpos, @ypos @xpos, @delx = del(@xpos, @delx, Width) @ypos, @dely = del(@ypos, @dely, Height) # Tell Tk about it. @canv.move(self, @xpos - oldx, @ypos - oldy) Tk.after(Frequency, proc { self.move } ) end end # Make several balls of different color. for color in [ '#FF9999', '#99FFFF', '#005588', '#992211', '#FF0055' ] MovingCircle.new(c, color) end Tk.mainloop