Bouncing DVD Logo
If you are of a certain age, you’ll remember those ancient technological devices called DVD players. When not playing DVDs, they would display a diagonally traveling DVD logo that bounced off the edges of the screen. This program simulates this colorful DVD logo by making it change direction each time it hits an edge. We’ll also keep track of how many times a logo hits a corner of the screen. This creates an interesting visual animation to look at, especially for the magical moment when a logo lines up perfectly with a corner.
You can’t run this program from your integrated development environment (IDE) or editor because it uses the bext module. Therefore, it must be run from the Command Prompt or Terminal in order to display correctly. You can find more information about the bext module at https://pypi.org/project/bext/.
bouncing_dvd_logo.py
1
2"""Bouncing DVD Logo, by Al Sweigart al@inventwithpython.com
3A bouncing DVD logo animation. You have to be "of a certain age" to
4appreciate this. Press Ctrl-C to stop.
5
6NOTE: Do not resize the terminal window while this program is running.
7This code is available at https://nostarch.com/big-book-small-python-programming
8Tags: short, artistic, bext"""
9
10import sys, random, time
11
12try:
13 import bext
14except ImportError:
15 print('This program requires the bext module, which you')
16 print('can install by following the instructions at')
17 print('https://pypi.org/project/Bext/')
18 sys.exit()
19
20# Set up the constants:
21WIDTH, HEIGHT = bext.size()
22# We can't print to the last column on Windows without it adding a
23# newline automatically, so reduce the width by one:
24WIDTH -= 1
25
26NUMBER_OF_LOGOS = 5 # (!) Try changing this to 1 or 100.
27PAUSE_AMOUNT = 0.2 # (!) Try changing this to 1.0 or 0.0.
28# (!) Try changing this list to fewer colors:
29COLORS = ['red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white']
30
31UP_RIGHT = 'ur'
32UP_LEFT = 'ul'
33DOWN_RIGHT = 'dr'
34DOWN_LEFT = 'dl'
35DIRECTIONS = (UP_RIGHT, UP_LEFT, DOWN_RIGHT, DOWN_LEFT)
36
37# Key names for logo dictionaries:
38COLOR = 'color'
39X = 'x'
40Y = 'y'
41DIR = 'direction'
42
43
44def main():
45 bext.clear()
46
47 # Generate some logos.
48 logos = []
49 for i in range(NUMBER_OF_LOGOS):
50 logos.append({COLOR: random.choice(COLORS),
51 X: random.randint(1, WIDTH - 4),
52 Y: random.randint(1, HEIGHT - 4),
53 DIR: random.choice(DIRECTIONS)})
54 if logos[-1][X] % 2 == 1:
55 # Make sure X is even so it can hit the corner.
56 logos[-1][X] -= 1
57
58 cornerBounces = 0 # Count how many times a logo hits a corner.
59 while True: # Main program loop.
60 for logo in logos: # Handle each logo in the logos list.
61 # Erase the logo's current location:
62 bext.goto(logo[X], logo[Y])
63 print(' ', end='') # (!) Try commenting this line out.
64
65 originalDirection = logo[DIR]
66
67 # See if the logo bounces off the corners:
68 if logo[X] == 0 and logo[Y] == 0:
69 logo[DIR] = DOWN_RIGHT
70 cornerBounces += 1
71 elif logo[X] == 0 and logo[Y] == HEIGHT - 1:
72 logo[DIR] = UP_RIGHT
73 cornerBounces += 1
74 elif logo[X] == WIDTH - 3 and logo[Y] == 0:
75 logo[DIR] = DOWN_LEFT
76 cornerBounces += 1
77 elif logo[X] == WIDTH - 3 and logo[Y] == HEIGHT - 1:
78 logo[DIR] = UP_LEFT
79 cornerBounces += 1
80
81 # See if the logo bounces off the left edge:
82 elif logo[X] == 0 and logo[DIR] == UP_LEFT:
83 logo[DIR] = UP_RIGHT
84 elif logo[X] == 0 and logo[DIR] == DOWN_LEFT:
85 logo[DIR] = DOWN_RIGHT
86
87 # See if the logo bounces off the right edge:
88 # (WIDTH - 3 because 'DVD' has 3 letters.)
89 elif logo[X] == WIDTH - 3 and logo[DIR] == UP_RIGHT:
90 logo[DIR] = UP_LEFT
91 elif logo[X] == WIDTH - 3 and logo[DIR] == DOWN_RIGHT:
92 logo[DIR] = DOWN_LEFT
93
94 # See if the logo bounces off the top edge:
95 elif logo[Y] == 0 and logo[DIR] == UP_LEFT:
96 logo[DIR] = DOWN_LEFT
97 elif logo[Y] == 0 and logo[DIR] == UP_RIGHT:
98 logo[DIR] = DOWN_RIGHT
99
100 # See if the logo bounces off the bottom edge:
101 elif logo[Y] == HEIGHT - 1 and logo[DIR] == DOWN_LEFT:
102 logo[DIR] = UP_LEFT
103 elif logo[Y] == HEIGHT - 1 and logo[DIR] == DOWN_RIGHT:
104 logo[DIR] = UP_RIGHT
105
106 if logo[DIR] != originalDirection:
107 # Change color when the logo bounces:
108 logo[COLOR] = random.choice(COLORS)
109
110 # Move the logo. (X moves by 2 because the terminal
111 # characters are twice as tall as they are wide.)
112 if logo[DIR] == UP_RIGHT:
113 logo[X] += 2
114 logo[Y] -= 1
115 elif logo[DIR] == UP_LEFT:
116 logo[X] -= 2
117 logo[Y] -= 1
118 elif logo[DIR] == DOWN_RIGHT:
119 logo[X] += 2
120 logo[Y] += 1
121 elif logo[DIR] == DOWN_LEFT:
122 logo[X] -= 2
123 logo[Y] += 1
124
125 # Display number of corner bounces:
126 bext.goto(5, 0)
127 bext.fg('white')
128 print('Corner bounces:', cornerBounces, end='')
129
130 for logo in logos:
131 # Draw the logos at their new location:
132 bext.goto(logo[X], logo[Y])
133 bext.fg(logo[COLOR])
134 print('DVD', end='')
135
136 bext.goto(0, 0)
137
138 sys.stdout.flush() # (Required for bext-using programs.)
139 time.sleep(PAUSE_AMOUNT)
140
141
142# If this program was run (instead of imported), run the game:
143if __name__ == '__main__':
144 try:
145 main()
146 except KeyboardInterrupt:
147 print()
148 print('Bouncing DVD Logo, by Al Sweigart')
149 sys.exit() # When Ctrl-C is pressed, end the program.