Skip to content

Instantly share code, notes, and snippets.

@voltuer
Last active May 21, 2020 02:55
Show Gist options
  • Save voltuer/0c49ca0e6ca482b1f486228069e3608f to your computer and use it in GitHub Desktop.
Save voltuer/0c49ca0e6ca482b1f486228069e3608f to your computer and use it in GitHub Desktop.
Matrix rain en python

Ejecutar animación sin instalar nada

python3 -c "import zlib, base64;exec(zlib.decompress(base64.b64decode('eJyVVVtv0zAUfvevMPCAQ900KfdpRhpNL9PaTSsVMCEUZYnbmiV262Skk/jx+BLTy4oED0lsn+Pv+3x8zsmzJ537UnZuGe9Q/hOuHqql4C8BK1ZCVlAmPBOFm6X3sqSlm1WsoOCS+MErMCFd0CNhAHLSDcA1CbvvIBiQVwEYkZm8pyCjc3iOZt4JaEB8/YlLWqHAA3Dmc5HRPHlA2lstrJB6LXJxm+SwB2CPNLt6V+NPnc7LP7YJgBMSthrr+Pyyr8zd14ZPYWzpyiqRVZyKXMgd6BGAIwedJjxOlwlfUOcGAWRzOFIgDoVx5kC2gq6m8ZfR+ayPwyAIti/FAudCQgYZ13FcUDRohVoShAuCtEs7fzHwWvkLptceU1y3GA7wAhuoPfsqYdasnz0lH8dnvQvlT/OSHgo3u8J9/+G03788CqFDeGdCmJNv6VIi5h0cJ9h0Qxxs3va978rJp5uK8gz9zXcwePMG68/7yPuuFEpa3UsOc/CZKBpDVxi6xmBTz0+XgqUUfbYeF0c89IfxCh0kAd6d290VmuG1BqiXLKdQ55qO0Ybsc611vNe+pIX4SdFGzzJyodMGnpED0hBP9PoDo3kG51IUkCmSDc7wmUVJVisdlY1V4IzlitKMTLSWCAtck0DddOCE1ae72rVEQaJ2pg6lhmyOxGlg80gQtQfW2mgsamdgDLUxuCSAY0VbY3OSr2poKO20b6ZmGJGoZXS58xjFzuHEFEP0SNnMT7KsrCRSTlhdIH5cGL+apbP449U4soHYlXGyrbODrKlxwbhC3rtKe/Q/vKzh/aFGEa69neQ/iib+Cc01BV2ITeF4Rypa/IfAY5DHQuMuS6EcFpFhq4+w7ZE9h8+PkAWehXdxUttuyKCNojbzWqG5ghubPTc6eZoae4xz3bqxQNz2c93WARySb6oJrEnOygpZtTstu22Ct191UzTEuhyboEp9zKGJHFedBEltSJdk5i9olS5N9SmJ6fKJa9j96RSqKjRLQmZIHds7gRrgVtLkTg30H8ovc0pX6NJqdqQm5VBOORp6pz1PwZjJ2vtgK2vo6ta2DA8o6jjmSUHjmJCncVwkjMfx0+0PppZ6h0TcA78BAnIsaA==')))"

Cómo minificar el script matrix.py usando pyminifier para crear un comando como el anterior:

Esto minificará matrix.py y lo guardará como tmp.py, luego lo ejecutará para probar si corre o no, ya que a veces por la aleatoriedad de los caracteres del minificador, no corre. Si corre sabremos que quedó bien el script y podemos hacer lo que queramos con tmp.py

# Minificar e intentar ejecutar
pyminifier --obfuscate-variables --obfuscate-functions --gzip -o tmp.py matrix.py ; python tmp.py
# Original: https://github.com/gineer01/matrix-rain
import random
import curses
import time
# Sleep between frame after refresh so that user can see the frame. Value 0.01 or lower results in flickering because
# the animation is too fast.
SLEEP_BETWEEN_FRAME = .04
# How fast the rain should fall. In config, we change it according to screen.
FALLING_SPEED = 2
# The max number of falling rains. In config, we change it according to screen.
MAX_RAIN_COUNT = 10
# Color gradient for rain
COLOR_STEP = 20
START_COLOR_NUM = 128 # The starting number for color in gradient to avoid changing the first 16 basic colors
NUMBER_OF_COLOR = 40
USE_GRADIENT = False
# Reset the config value according to screen size
def config(stdscr):
curses.curs_set(0)
stdscr.nodelay(True)
init_colors()
global MAX_RAIN_COUNT
MAX_RAIN_COUNT = curses.COLS//2
global FALLING_SPEED
FALLING_SPEED = 1 + curses.LINES//25
def init_colors():
curses.start_color()
global USE_GRADIENT
USE_GRADIENT = curses.can_change_color() # use xterm-256 if this is false
if USE_GRADIENT:
curses.init_color(curses.COLOR_WHITE, 1000, 1000, 1000)
for i in range(NUMBER_OF_COLOR + 1):
green_value = (1000 - COLOR_STEP * NUMBER_OF_COLOR) + COLOR_STEP * i
curses.init_color(START_COLOR_NUM + i, 0, green_value, 0)
curses.init_pair(START_COLOR_NUM + i, START_COLOR_NUM + i, curses.COLOR_BLACK)
else:
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
def get_matrix_code_chars():
l = [chr(i) for i in range(0x21, 0x7E)]
# half-width katakana. See https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms
l.extend([chr(i) for i in range(0xFF66, 0xFF9D)])
return l
MATRIX_CODE_CHARS = get_matrix_code_chars()
def random_char():
return random.choice(MATRIX_CODE_CHARS)
def random_rain_length():
return random.randint(curses.LINES//2, curses.LINES)
def rain(stdscr, pool):
while True:
x = random.choice(pool)
pool.remove(x)
max_length = random_rain_length()
speed = random.randint(1, FALLING_SPEED)
yield from animate_rain(stdscr, x, max_length, speed)
pool.append(x)
def animate_rain(stdscr, x, max_length, speed=FALLING_SPEED):
"""
A rain consists of 3 parts: head, body, and tail
Head: the white leading rain drop
Body: the fading trail
Tail: empty space behind the rain trail
:param stdscr: curses's screen object
:param x: the column of this rain on the screen
:param max_length: the length of this rain
:param speed: how fast a rain should fall (the number of lines it jumps each animation frame)
:return: None
"""
head, middle, tail = 0, 0, 0
while tail < curses.LINES:
middle = head - max_length//2
if (middle < 0):
middle = 0
tail = head - max_length
if tail < 0:
tail = 0
else:
show_tail(stdscr, tail, x, speed)
show_body(stdscr, head, middle, tail, x)
show_head(stdscr, head, x)
head = head + speed
yield
def show_head(stdscr, head, x):
if head < curses.LINES:
stdscr.addstr(head, x, random_char(), curses.COLOR_WHITE | curses.A_BOLD)
def show_body(stdscr, head, middle, tail, x):
if USE_GRADIENT:
for i in range(tail, min(head, curses.LINES)):
stdscr.addstr(i, x, random_char(), get_color(i, head, tail))
else:
for i in range(tail, min(middle, curses.LINES)):
stdscr.addstr(i, x, random_char(), curses.color_pair(1))
for i in range(middle, min(head, curses.LINES)):
stdscr.addstr(i, x, random_char(), curses.color_pair(1) | curses.A_BOLD)
def show_tail(stdscr, tail, x, speed):
for i in range(max(0, tail - speed), min(tail, curses.LINES)):
stdscr.addstr(i, x, ' ', curses.color_pair(0))
def get_color(i, head, tail):
color_num = NUMBER_OF_COLOR - (head - i) + 1
if color_num < 0:
color_num = 0
return curses.color_pair(START_COLOR_NUM + color_num)
def main(stdscr):
# stdscr.addstr(0, 0, "Press any key to start. Press any key (except SPACE) to stop.")
# ch = stdscr.getch() # Wait for user to press something before starting
config(stdscr)
rains = []
pool = list(range(curses.COLS - 1))
while True:
add_rain(rains, stdscr, pool)
for r in rains:
next(r)
ch = stdscr.getch()
if ch != curses.ERR and ch != ord(' '): # Use space to proceed animation if nodelay is False
break
time.sleep(SLEEP_BETWEEN_FRAME)
def add_rain(rains, stdscr, pool):
if (len(rains) < MAX_RAIN_COUNT) and (len(pool) > 0):
rains.append(rain(stdscr, pool))
if __name__ == "__main__":
curses.wrapper(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment