#!/usr/bin/env python3 # -*- coding: utf-8 -*- import time import random import os import sys colors = { "black": "\u001b[30m", "red": "\u001b[31m", "green": "\u001b[32m", "yellow": "\u001b[33m", "blue": "\u001b[34m", "magenta": "\u001b[35m", "cyan": "\u001b[36m", "white": "\u001b[37m", "reset": "\u001b[0m", "b_black": "\u001b[30;1m", "b_red": "\u001b[31;1m", "b_green": "\u001b[32;1m", "b_yellow": "\u001b[33;1m", "b_blue": "\u001b[34;1m", "b_magenta": "\u001b[35;1m", "b_cyan": "\u001b[36;1m", "b_white": "\u001b[37;1m", "Reset": "\u001b[0m", } def Colored(string, color): return string if "-m" in sys.argv else ( colors[color] + string + colors["Reset"]) def Clear_Screen(): print("\033[2J") # erase saved lines print("\033[3J") # erase entire screen print("\033[H") # moves cursor to home position def Get_Arguments(): args_dict = {"colors": []} if sys.argv: for arg in sys.argv: if "-i=" in arg: args_dict["intensity"] = int(arg.split("-i=")[1]) if "-t=" in arg: args_dict["timing"] = float(arg.split("-t=")[1]) if arg in colors: args_dict["colors"].append(arg) if not args_dict["colors"]: del args_dict["colors"] return args_dict def New_Drop(): for i in range(intensity): shape = random.choice(DROPSHAPES) color = random.choice(drop_colors) raindrop = { "shape": Colored(shape, color), "x": random.randint(0, xmax), "y": 0, } rainfall.append(raindrop) def Rain(): ## iterate over every line for i in range(ymax): line = " "*xmax ### to avoid splicing of ansi codes, splice in the drops from the end of the line this_line_raindrops = [raindrop for raindrop in rainfall if raindrop["y"] == i] this_line_raindrops.sort(key=lambda y: y["x"]) this_line_raindrops.reverse() ## insert new drops and shift existing drops for raindrop in this_line_raindrops: x = raindrop["x"] line = line[:x] + raindrop["shape"] +line[x:] print(line) ### update raindrop positions for raindrop in rainfall: raindrop["y"] += 1 ## once a raindrop reaches the ground, they splash if raindrop["y"] > ymax-2: raindrop["shape"] = Colored("o", random.choice(drop_colors)) # raindrops outside the window evaporate if raindrop["y"] > ymax: rainfall.remove(raindrop) New_Drop() def Weather_Forecast(): global weather global intensity weather += 1 if weather == 100: weather = 0 intensity += random.choice([-1,1]) if intensity < 1: intensity = 1 if intensity > 10: intensity = 10 size = os.get_terminal_size() xmax = size.columns ymax = int(size.lines) weather = 0 rainfall = [] DROPSHAPES =["|", "│", "┃", "╽", "╿", "║", "┆", "┇", "┊", "┋", "╵", "╹", "╻"] args = Get_Arguments() intensity = args.get("intensity", 1) timing = args.get("timing", 0.08) drop_colors = args.get("colors", ["blue", "b_blue"]) print('\033[?25l', end="") ## hides the cursor New_Drop() try: while True: Rain() time.sleep(timing) Clear_Screen() Weather_Forecast() except KeyboardInterrupt: Clear_Screen() print('\033[?25h', end="") # makes cursor visible again