Created
February 19, 2025 15:14
-
-
Save justinledwards/02f3f46eafea234952ce4fa3368c0912 to your computer and use it in GitHub Desktop.
Matrix python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import sys | |
import time | |
import random | |
import curses | |
# ANSI escape codes for text formatting | |
LIGHT_GREEN = '\033[92m' | |
DARK_GREEN = "\033[0;32m" | |
BOLDON = '\033[1m' | |
CURSORON = '\x1b[?25h' | |
CURSOROFF = '\x1b[?25l' | |
END = '\033[0m' | |
def clear_terminal(): | |
"""Clear the terminal screen (compatible with Windows and Unix).""" | |
os.system('cls' if os.name != 'posix' else 'clear') | |
def live_type(text, delay, remain, prefix=""): | |
""" | |
Prints text one character at a time with a delay between characters. | |
:param text: The string to display. | |
:param delay: Time delay between characters. | |
:param remain: Time to wait after printing the text. | |
:param prefix: A string printed before the text (for positioning). | |
""" | |
print(prefix, end='') | |
for char in text: | |
print(char, end='', flush=True) | |
time.sleep(delay) | |
time.sleep(remain) | |
def show_message(message, delays, delay_factor, remain, prefix=""): | |
""" | |
Prints a message with a pre-defined per-character delay list. | |
:param message: The message to print. | |
:param delays: A list of delay multipliers for each character. | |
:param delay_factor: A global multiplier for the delays. | |
:param remain: Time to pause after the message is printed. | |
:param prefix: A string printed before the message (for positioning). | |
""" | |
print(prefix, end='') | |
for char, d in zip(message, delays): | |
time.sleep(d * delay_factor) | |
print(char, end='', flush=True) | |
time.sleep(remain) | |
def matrix_rain_effect(duration): | |
""" | |
Displays a Matrix rain effect for a given duration using curses. | |
This function sets up the curses window, then in a loop randomly | |
updates each column with a falling random ASCII character. | |
:param duration: How many seconds to run the effect. | |
""" | |
def run_matrix(stdscr): | |
curses.curs_set(0) | |
stdscr.nodelay(True) | |
sh, sw = stdscr.getmaxyx() | |
curses.start_color() | |
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) | |
# Initialize drop positions for each column | |
columns = [0] * sw | |
start_time = time.time() | |
while time.time() - start_time < duration: | |
stdscr.erase() | |
for x in range(sw): | |
# Occasionally reset the drop to create a staggered look. | |
if random.random() > 0.975: | |
columns[x] = 0 | |
else: | |
columns[x] = (columns[x] + 1) % sh | |
char = chr(random.randint(33, 126)) | |
try: | |
stdscr.addstr(columns[x], x, char, curses.color_pair(1)) | |
except curses.error: | |
pass # Ignore errors when drawing outside the window | |
stdscr.refresh() | |
time.sleep(0.05) | |
stdscr.erase() | |
stdscr.refresh() | |
time.sleep(0.1) | |
curses.wrapper(run_matrix) | |
def handle_interrupt(prefix, delay_factor, remain_factor, exit_msg, exit_msg2): | |
""" | |
Handles KeyboardInterrupt by displaying an alternate sequence. | |
""" | |
clear_terminal() | |
print(prefix, end='') | |
print(END + LIGHT_GREEN + "Switch!") | |
time.sleep(0.6 * remain_factor) | |
clear_terminal() | |
print(prefix, end='') | |
print("Switch!\n\t\tApoc!") | |
time.sleep(1.2 * remain_factor) | |
clear_terminal() | |
print(prefix, end='\n\n\n ') | |
print(exit_msg, flush=True) | |
time.sleep(0.9 * remain_factor) | |
clear_terminal() | |
print(prefix, end='\n ') | |
print(exit_msg2, flush=True) | |
time.sleep(0.6 * remain_factor) | |
clear_terminal() | |
print(prefix, end='') | |
live_type(exit_msg, 0.045 * delay_factor, 3.5 * remain_factor) | |
print(CURSORON + END) | |
clear_terminal() | |
sys.exit() | |
def main(): | |
# Configuration factors (you can adjust these to change the pace) | |
remain_factor = 0.2 # Affects how long messages remain on screen. | |
delay_factor = 0.7 # Affects typing speed. | |
# Positioning prefix for messages | |
prefix = "\n\n\n " | |
# Message definitions | |
ur_name = "Neo" | |
msg1 = f"Wake up, {ur_name}..." | |
msg2 = "The Matrix has you..." | |
msg3 = "Follow the white rabbit." | |
msg4 = f"Knock, knock, {ur_name}." | |
exit_msg = " 671tcH iN Th3 M4tr1x\n" | |
exit_msg2 = " gLiTCh In tH€ WaTriX\n" | |
# Delay arrays measured from the film (ensure these match the message lengths) | |
secs1 = [0, 0.1500, 0.1625, 0.1500, 0.1625, 0.1500, | |
0.1625, 0.1500, 0.1200, 0.1250, 0.1200, | |
0.1250, 0.0625, 0.0875, 0.0625] | |
secs2 = [0, 0.7325, 0.6700, 0.6000, 0.7800, 0.0950, | |
0.1350, 0.1075, 0.5275, 0.6225, 0.0080, | |
0.1200, 0.1475, 0.4500, 0.0080, 0.4275, | |
0.1275, 0.1425, 0.3550, 0.2275, 0.1450] | |
try: | |
clear_terminal() | |
# Pre-sequence Matrix rain (3 seconds) | |
matrix_rain_effect(duration=3) | |
# Set text formatting: bold, light green, and hide the cursor. | |
print(BOLDON + LIGHT_GREEN + CURSOROFF, end='') | |
# Display each message with its timing and then clear the screen. | |
show_message(msg1, secs1, delay_factor, 16.03 * remain_factor, prefix=prefix) | |
clear_terminal() | |
show_message(msg2, secs2, delay_factor, 7.54 * remain_factor, prefix=prefix) | |
clear_terminal() | |
live_type(msg3, 0.1167 * delay_factor, 8.515 * remain_factor, prefix=prefix) | |
clear_terminal() | |
# Print the final message without per-character delays. | |
print(prefix, end='') | |
print(msg4, end='') | |
print(prefix * 2, end='') | |
time.sleep(4) | |
clear_terminal() | |
# Post-sequence Matrix rain (3 seconds) | |
matrix_rain_effect(duration=3) | |
except KeyboardInterrupt: | |
handle_interrupt(prefix, delay_factor, remain_factor, exit_msg, exit_msg2) | |
# Restore cursor and default text formatting | |
print(CURSORON + END, end='') | |
clear_terminal() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment