This program mimics the “digital stream” visualization from the science fiction movie The Matrix. Random beads of binary “rain” stream up from the bottom of the screen, creating a cool, hacker-like visualization. (Unfortunately, due to the way text moves as the screen scrolls down, it’s not possible to make the streams fall downward without using a module such as bext.)
The Program in Action
When you run digitalstream.py, the output will look like this:
Like Project 15, “Deep Cave,” this program uses the scrolling caused by print() calls to create an animation. Each column is represented by an integer in the columns list: columns is an integer for the leftmost column, columns is an integer for the column to the right of that one, and so on. The program initially sets these integers to 0, meaning it prints ' ' (an empty space string) instead of a stream in that column. Randomly, it changes each integer to a value between MIN_STREAM_LENGTH and MAX_STREAM_LENGTH. That integer decreases by 1 each time a line is printed. As long as a column’s integer is greater than 0, the program prints a random 1 or 0 in that column. This produces the “digital stream” effect you see on the screen.
1. """Digital Stream, by Al Sweigart [email protected]
2. A screensaver in the style of The Matrix movie's visuals.
3. View this code at https://nostarch.com/big-book-small-python-projects
4. Tags: tiny, artistic, beginner, scrolling"""
6. import random, shutil, sys, time
8. # Set up the constants:
9. MIN_STREAM_LENGTH = 6 # (!) Try changing this to 1 or 50.
10. MAX_STREAM_LENGTH = 14 # (!) Try changing this to 100.
11. PAUSE = 0.1 # (!) Try changing this to 0.0 or 2.0.
12. STREAM_CHARS = ['0', '1'] # (!) Try changing this to other characters.
14. # Density can range from 0.0 to 1.0:
15. DENSITY = 0.02 # (!) Try changing this to 0.10 or 0.30.
17. # Get the size of the terminal window:
18. WIDTH = shutil.get_terminal_size()
19. # We can't print to the last column on Windows without it adding a
20. # newline automatically, so reduce the width by one:
21. WIDTH -= 1
23. print('Digital Stream, by Al Sweigart [email protected]')
24. print('Press Ctrl-C to quit.')
28. # For each column, when the counter is 0, no stream is shown.
29. # Otherwise, it acts as a counter for how many times a 1 or 0
30. # should be displayed in that column.
31. columns =  * WIDTH
32. while True:
33. # Set up the counter for each column:
34. for i in range(WIDTH):
35. if columns[i] == 0:
36. if random.random() <= DENSITY:
37. # Restart a stream on this column.
38. columns[i] = random.randint(MIN_STREAM_LENGTH,
41. # Display an empty space or a 1/0 character.
42. if columns[i] > 0:
43. print(random.choice(STREAM_CHARS), end='')
44. columns[i] -= 1
46. print(' ', end='')
47. print() # Print a newline at the end of the row of columns.
48. sys.stdout.flush() # Make sure text appears on the screen.
50. except KeyboardInterrupt:
51. sys.exit() # When Ctrl-C is pressed, end the program.
After entering the source code and running it a few times, try making experimental changes to it. The comments marked with (!) have suggestions for small changes you can make. On your own, you can also try to figure out how to do the following:
Include characters besides just 1s and 0s.
Include shapes besides lines, including rectangles, triangles, and diamonds.
Exploring the Program
Try to find the answers to the following questions. Experiment with some modifications to the code and rerun the program to see what effect the changes have.
What happens if you change print(' ', end='') on line 46 to print('.', end='')?
What error message do your get if you change PAUSE = 0.1 on line 11 to PAUSE = -0.1?
What happens if you change columns[i] > 0 on line 42 to columns[i] < 0?
What happens if you change columns[i] > 0 on line 42 to columns[i] <= 0?
What happens if you change columns[i] -= 1 on line 44 to columns[i] += 1?