Building a screen saver

We will start by building a screen saver. The program will consist of several random-colored and random-sized balls bouncing all over the screen at random velocity, as shown in the following screenshot:

Let's create a class to generate balls with random attributes. Accordingly, we define a new class named RandomBall. Refer the code file 8.01_screensaver:

class RandomBall:

def __init__(self, canvas):
self.canvas = canvas
self.screen_width = canvas.winfo_screenwidth()
self.screen_height = canvas.winfo_screenheight()
self.create_ball()

def create_ball(self):
self.generate_random_attributes()
self.create_oval()

def generate_random_attributes(self):
self.radius = r = randint(40, 70)
self.x_coordinate = randint(r, self.screen_width - r)
self.y_coordinate = randint(r, self.screen_height - r)
self.x_velocity = randint(6, 12)
self.y_velocity = randint(6, 12)
self.color = self.generate_random_color()

def generate_random_color(self):
r = lambda: randint(0, 0xffff)
return '#{:04x}{:04x}{:04x}'.format(r(), r(), r())

def create_oval(self):
x1 = self.x_coordinate - self.radius
y1 = self.y_coordinate - self.radius
x2 = self.x_coordinate + self.radius
y2 = self.y_coordinate + self.radius
self.ball = self.canvas.create_oval( x1, y1, x2, y2, fill=self.color,
outline=self.color)

def move_ball(self):
self.check_screen_bounds()
self.x_coordinate += self.x_velocity
self.y_coordinate += self.y_velocity
self.canvas.move(self.ball, self.x_velocity, self.y_velocity)

def check_screen_bounds(self):
r = self.radius
if not r < self.y_coordinate < self.screen_height - r:
self.y_velocity = -self.y_velocity
if not r < self.x_coordinate < self.screen_width - r:
self.x_velocity = -self.x_velocity

Here's the description for the preceding code:

  • Two key methods here are create_ball and move_ball. All other methods are helpers to these two methods. The __init__ method takes a canvas as a parameter and then calls the create_ball method to draw the ball on the given canvas. To move the ball around, we will explicitly need to call the move_ball method.
  • The create_ball method uses the canvas.create_oval() method and move_ball uses the canvas.move(item, dx, dy) method, where dx and dy are x and y offsets for the canvas item.
  • Also, note how we create a random color for the ball. Because the hexadecimal color coding system uses up to four hexadecimal digits for each of red, green, and blue, there are up to 0xffff possibilities for each color. We, therefore, create a lambda function that generates a random number from 0-0xffff, and use this function to generate three random numbers. We convert this decimal number to its two-digit equivalent hexadecimal notation using the format specifier #{:04x}{:04x}{:04x} to get a random color code for the ball.

That is all there is to the RandomBall class. We can use this class to create as many ball objects as we want to display in our screensaver.

Next, let's create the ScreenSaver class that will show the actual screensaver:

class ScreenSaver:

balls = []

def __init__(self, number_of_balls):
self.root = Tk()
self.number_of_balls = number_of_balls
self.root.attributes('-fullscreen', True)
self.root.attributes('-alpha', 0.1)
self.root.wm_attributes('-alpha',0.1)
self.quit_on_interaction()
self.create_screensaver()
self.root.mainloop()

def create_screensaver(self):
self.create_canvas()
self.add_balls_to_canvas()
self.animate_balls()

def create_canvas(self):
self.canvas = Canvas(self.root)
self.canvas.pack(expand=1, fill=BOTH)

def add_balls_to_canvas(self):
for i in range(self.number_of_balls):
self.balls.append(RandomBall(self.canvas))

def quit_on_interaction(self):
for seq in ('<Any-KeyPress>', '<Any-Button>', '<Motion>'):
self.root.bind(seq, self.quit_screensaver)

def animate_balls(self):
for ball in self.balls:
ball.move_ball()
self.root.after(30, self.animate_balls)

def quit_screensaver(self, event):
self.root.destroy()

The description of the code is as follows:

  •  The __init__ method of the ScreenSaver class takes the number of balls (number_of_balls) as its argument
  • We use root.attributes ( -fullscreen, True ) to remove the enclosing frame from the parent window and make it a full-screen window.
  • The quit_on_interaction method binds the root to call our quit_screensaver method in case of any interactions from the user's end.
  • We then create a canvas to cover the entire screen with Canvas(self.root) with pack ( expand=1, fill=BOTH ) options to fill the entire screen.
  • We create several random ball objects using the RandomBall class, passing along the Canvas widget instance as its arguments.
  • We finally make a call to the animate_balls method, which uses the standard widget.after() method to keep running the animation in a loop at a regular interval of 30 milliseconds.
  • To run the screen saver, we instantiate an object from our ScreenSaver class, passing the number of balls as its argument as follows: ScreenSaver(number_of_balls=18)

Our screensaver is now ready! In fact, if you are working on the Windows platform, and when you learn to create an executable program from Python programs (discussed in Chapter 10Miscellaneous Tips), you can create an executable file with a .exe extension for this screensaver. You can then change its extension from .exe to .scr, right-click, and select Install to add it to your list of screensavers.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.74.160