First commit
This commit is contained in:
parent
c060d03dff
commit
84088247b4
73
main.py
Normal file
73
main.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
# import shutil # shutil.get_terminal_size(fallback=(0, 0))
|
||||
import os
|
||||
import math
|
||||
|
||||
from pixel import Pixel, Screen
|
||||
|
||||
WIDTH, HEIGHT = 100, 30
|
||||
STD_HANDLE = 1 # Would want this to be 0, but it can cause issues
|
||||
|
||||
def shad_background(pixel: Pixel, x: int, y: int, time: float):
|
||||
uv = (x / WIDTH, y / HEIGHT)
|
||||
|
||||
h = math.sin(uv[0] * math.pi + uv[1] * 10.0 + time + math.cos(uv[0] * uv[1] + uv[1] * 7.1823) * math.sin(uv[0] * 14.2))
|
||||
pixel.background_color.set(h, h, h)
|
||||
|
||||
def shad_wave(pixel: Pixel, x: int, y: int, time: float): # https://www.shadertoy.com/view/Wd23W3
|
||||
uv = (x / WIDTH, y / HEIGHT)
|
||||
|
||||
def hsv2rgb(h, s, v) -> tuple:
|
||||
r,g,b = 0,0,0
|
||||
|
||||
i = int(h * 6)
|
||||
f = h * 6 - i
|
||||
p = v * (1 - s)
|
||||
q = v * (1 - f * s)
|
||||
t = v * (1 - (1 - f) * s)
|
||||
|
||||
o = i % 6
|
||||
|
||||
if o == 0:
|
||||
r,g,b = v,t,p
|
||||
elif o == 1:
|
||||
r,g,b = q,v,p
|
||||
elif o == 2:
|
||||
r,g,b = p,v,t
|
||||
elif o == 3:
|
||||
r,g,b = p,q,v
|
||||
elif o == 4:
|
||||
r,g,b = t,p,v
|
||||
else:
|
||||
r,g,b = v,p,q
|
||||
|
||||
return r, g, b
|
||||
|
||||
def step(edge: float, value: float) -> float:
|
||||
return 1.0 if value > edge else 0.0
|
||||
|
||||
def strip(h: float, thickness: float, y: float) -> float:
|
||||
return step(y + h - thickness, step(1., y + h + thickness))
|
||||
|
||||
col = [0.0, 0.0, 0.0]
|
||||
|
||||
f = 0.0
|
||||
while f < math.pi * 2:
|
||||
a = strip(.5 + math.cos(uv[0] * 2. + time * 3.) * .15,
|
||||
.005,
|
||||
uv[1] + math.cos(uv[0] * 3. + time * 2. + f) * .25)
|
||||
|
||||
_col = hsv2rgb(f / math.pi / 2., 1., 1.)
|
||||
for i in range(3):
|
||||
col[i] += a * _col[i]
|
||||
|
||||
f += math.pi / 4.
|
||||
|
||||
pixel.text_color.set(*col)
|
||||
|
||||
|
||||
screen = Screen(WIDTH, HEIGHT, STD_HANDLE, [
|
||||
shad_background
|
||||
#shad_wave
|
||||
])
|
||||
|
||||
screen.mainloop()
|
140
pixel.py
Normal file
140
pixel.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
import os
|
||||
import datetime
|
||||
|
||||
from time import sleep # debug
|
||||
|
||||
class Color:
|
||||
cache_closest_printable_color = 0
|
||||
|
||||
def __init__(self, r: float = 0.0, g: float = 0.0, b: float = 0.0):
|
||||
self.set(r, g, b)
|
||||
self.update()
|
||||
|
||||
def set(self, r, g, b):
|
||||
self.r, self.g, self.b = r, g, b
|
||||
|
||||
def update(self):
|
||||
self._r, self._g, self._b = self.r, self.g, self.b
|
||||
|
||||
def hasChange(self) -> bool:
|
||||
return any(x != y for x, y in {self._r: self.r, self._g: self.g, self._b: self.b}.items())
|
||||
|
||||
def distance(self, to) -> float:
|
||||
dr = self.r - to.r
|
||||
dg = self.g - to.g
|
||||
db = self.b - to.b
|
||||
return (dr * dr + dg * dg + db * db) ** .5
|
||||
|
||||
def getClosestPrintableColor(self) -> int:
|
||||
if not self.hasChange():
|
||||
return self.cache_closest_printable_color
|
||||
|
||||
closest_distance = float("inf")
|
||||
closest_value = 0
|
||||
for k, v in COLORS.items():
|
||||
distance = self.distance(k)
|
||||
if closest_distance > distance:
|
||||
closest_distance = distance
|
||||
closest_value = v
|
||||
|
||||
self.cache_closest_printable_color = closest_value
|
||||
self.update()
|
||||
|
||||
return closest_value
|
||||
|
||||
class Pixel:
|
||||
char = " "
|
||||
text_color = Color()
|
||||
background_color = Color()
|
||||
|
||||
cached_text_color_value = -1
|
||||
cached_background_color_value = -1
|
||||
|
||||
def __str__(self) -> str:
|
||||
color = ""
|
||||
|
||||
text_color = self.text_color.getClosestPrintableColor()
|
||||
if text_color != self.cached_text_color_value:
|
||||
color += COLOR_FORMAT % (text_color + COLOR_TEXT)
|
||||
self.cached_text_color_value = text_color
|
||||
|
||||
background_color = self.background_color.getClosestPrintableColor()
|
||||
if background_color != self.cached_background_color_value:
|
||||
color += COLOR_FORMAT % (background_color + COLOR_BACKGROUND)
|
||||
self.cached_background_color_value = background_color
|
||||
|
||||
|
||||
return color + self.char
|
||||
|
||||
def reset(self):
|
||||
self.cached_text_color_value = -1
|
||||
self.cached_background_color_value = -1
|
||||
|
||||
class Screen:
|
||||
def __init__(self, width: int, height: int, std_handle: int = 0, render_funcs = []):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.std_handle = std_handle
|
||||
self.render_funcs = render_funcs
|
||||
|
||||
self.time_start = datetime.datetime.now()
|
||||
self.buffer = ""
|
||||
|
||||
def get_time(self):
|
||||
return (datetime.datetime.now() - self.time_start).total_seconds()
|
||||
|
||||
def write(self, string):
|
||||
self.buffer += string
|
||||
|
||||
def flush(self):
|
||||
print(self.buffer, end="", flush=True)
|
||||
self.buffer = ""
|
||||
|
||||
def mainloop(self):
|
||||
pixel = Pixel()
|
||||
|
||||
while True:
|
||||
width, height = os.get_terminal_size(self.std_handle)
|
||||
if width < self.width or height < self.height:
|
||||
Screen.clear()
|
||||
print("Unable to print the screen, a terminal with %dx%d (and above) chars are required to continue" % (self.width, self.height))
|
||||
while width < self.width or height < self.height:
|
||||
width, height = os.get_terminal_size(self.std_handle)
|
||||
|
||||
time = self.get_time()
|
||||
|
||||
for y in range(self.height):
|
||||
for x in range(self.width):
|
||||
for render_func in self.render_funcs:
|
||||
render_func(pixel, x, y, time)
|
||||
self.write(str(pixel))
|
||||
pixel.reset()
|
||||
self.write("\x1b[0m\n") # newline
|
||||
|
||||
#Screen.clear()
|
||||
#self.flush()
|
||||
self.new_flush()
|
||||
#sleep(.01)
|
||||
|
||||
def new_flush(self):
|
||||
self.buffer = "\x1b[0;0H" + self.buffer
|
||||
self.flush()
|
||||
|
||||
@staticmethod
|
||||
def clear():
|
||||
print("\x1b[2J", end="", flush=True)
|
||||
|
||||
COLOR_RESET = 0
|
||||
COLOR_TEXT = 30
|
||||
COLOR_BACKGROUND = 40
|
||||
COLOR_FORMAT = "\x1b[%dm"
|
||||
COLORS = {
|
||||
Color(0.0, 0.0, 0.0): 0,
|
||||
Color(1.0, 0.0, 0.0): 1,
|
||||
Color(0.0, 1.0, 0.0): 2,
|
||||
Color(1.0, 1.0, 0.0): 3,
|
||||
Color(0.0, 0.0, 1.0): 4,
|
||||
Color(1.0, 0.0, 1.0): 5,
|
||||
Color(0.0, 1.0, 1.0): 6,
|
||||
Color(1.0, 1.0, 1.0): 7
|
||||
}
|
Loading…
Reference in New Issue
Block a user