-
Notifications
You must be signed in to change notification settings - Fork 0
/
pytrix.py
165 lines (132 loc) · 5.57 KB
/
pytrix.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# Copyright 2023 Elijah Gordon (NitrixXero) <[email protected]>
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import random
import time
import argparse
from colorama import init, Fore, Style
import shutil
import string
init(autoreset=True)
COLORS = {
"green": Fore.GREEN,
"red": Fore.RED,
"blue": Fore.BLUE,
"yellow": Fore.YELLOW,
"magenta": Fore.MAGENTA,
"cyan": Fore.CYAN,
"white": Fore.WHITE,
"black": Fore.BLACK,
}
class MatrixColumn:
def __init__(self, x, screen_height, bold, char_set, rainbow_mode, default_color):
self.x = x
self.screen_height = screen_height
self.head = 0
self.tail_start = -1
self.tail_length = random.randint(screen_height // 4, screen_height // 2)
self.done = False
self.bold = bold
self.char_set = char_set
self.rainbow_mode = rainbow_mode
self.default_color = default_color
def step(self):
if self.done:
return False
self.head += 1
if self.head >= self.screen_height:
self.done = True
return True
def get_character_at(self, y):
color = random.choice(list(COLORS.values())) if self.rainbow_mode else self.default_color
style = Style.BRIGHT if self.bold else Style.NORMAL
if y == self.head:
return random.choice(self.char_set), Fore.WHITE + style
elif self.tail_start <= y < self.head:
return random.choice(self.char_set), color + style
elif y == self.tail_start - 1:
return ' ', Fore.BLACK
return None, None
def update_tail(self):
if self.tail_start < self.head:
self.tail_start += 1
return self.tail_start < self.screen_height
class MatrixAnimation:
def __init__(self, max_columns, frame_delay, char_set, bold, rainbow_mode, color):
self.max_columns = max_columns
self.frame_delay = frame_delay
self.bold = bold
self.char_set = char_set
self.rainbow_mode = rainbow_mode
self.color = COLORS.get(color, Fore.GREEN)
self.columns = []
self.screen_width, self.screen_height = self.get_terminal_size()
def get_terminal_size(self):
return shutil.get_terminal_size()
def add_column(self):
if len(self.columns) < self.max_columns:
x = random.randint(0, self.screen_width - 1)
if all(column.x != x for column in self.columns):
self.columns.append(MatrixColumn(x, self.screen_height, self.bold, self.char_set, self.rainbow_mode, self.color))
def update_columns(self):
for column in self.columns[:]:
if not column.step() and not column.update_tail():
self.columns.remove(column)
def draw_frame(self):
frame = [[' ' for _ in range(self.screen_width)] for _ in range(self.screen_height)]
colors = [['' for _ in range(self.screen_width)] for _ in range(self.screen_height)]
for column in self.columns:
for y in range(self.screen_height):
char, color = column.get_character_at(y)
if char:
frame[y][column.x] = char
colors[y][column.x] = color
print('\033c', end='')
for y in range(self.screen_height):
line = ''.join(colors[y][x] + frame[y][x] for x in range(self.screen_width))
print(line)
def run(self):
try:
while True:
current_width, current_height = self.get_terminal_size()
if current_width != self.screen_width or current_height != self.screen_height:
self.screen_width, self.screen_height = current_width, current_height
self.columns = []
self.add_column()
self.update_columns()
self.draw_frame()
time.sleep(self.frame_delay)
except KeyboardInterrupt:
print('\033c', end='')
def parse_arguments():
parser = argparse.ArgumentParser(description="Matrix-style animation in Python.")
parser.add_argument("-b", action="store_true", help="Enable bold characters")
parser.add_argument("-V", action="store_true", help="Print version and exit")
parser.add_argument("-u", type=int, choices=range(0, 11), default=4, help="Screen update delay (0-10, default 4)")
parser.add_argument("-C", type=str, choices=list(COLORS.keys()), default="green", help="Matrix color (default green)")
parser.add_argument("-r", action="store_true", help="Rainbow mode")
return parser.parse_args()
if __name__ == "__main__":
args = parse_arguments()
if args.V:
print("Matrix terminal animation Version 1.0")
exit()
char_set = list(string.printable[:-6])
animation = MatrixAnimation(
max_columns=20,
frame_delay=args.u / 40,
char_set=char_set,
bold=args.b,
rainbow_mode=args.r,
color=args.C,
)
animation.run()