def on_resize(): buf.resize(app.screen.w, app.screen.h) for x in range(buf.w): for y in range(buf.h): col = Color.rgb(0, 0, 0) if (x + y) % 2 else Color.rgb( 0.1, 0.1, 0.1) buf.put_char(" ", x, y, bg=col)
def frame_gameover(): dark = Color.rgb(0.2,0.2,0.2) app.screen.clear() app.screen.blit(game_buffer, 0, ui_height) print_hcenter(app.screen, "Game over!", y=3, fg=Color.rgb(1,1,0), bg=dark) print_hcenter(app.screen, "Press enter to restart", y=4, fg=Color.rgb(0.75,0.75,0.75), bg=dark) print_hcenter(app.screen, "Press escape to exit", y=5, fg=Color.rgb(0.75,0.75,0.75), bg=dark) app.screen.update()
def main(): # example of manually controlling terminal b = detect_backend() b.enter_alt_buffer() b.cursor_pos = (0, 0) b.fg = Color.rgb(0, 1, 0) b.write("Hello world from {}\n".format(b.terminal_name)) b.cursor_pos = (0, 0) b.fg = Color.rgb(1, 0, 0) b.write("Hello\n") cols, rows = b.size b.write("Screen size: {}x{} hello\n".format(cols, rows)) b.flush() sleep(1) b.exit_alt_buffer()
def main(): app = App(framerate=float("inf")) colors = [Color.rgb(r,g,b) for r in (0, 1) for g in (0, 1) for b in (0, 1)] pixels = [PixelData(char="▄", fg=col1, bg=col2) for col1 in colors for col2 in colors] t0 = perf_counter() n_frames = 0 n_updates = 0 update_time = 0 @app.on("frame") def on_frame(): nonlocal n_frames, n_updates, update_time for x in range(app.screen.w): for y in range(app.screen.h): app.screen[x,y].set(choice(pixels)) app.screen.update() n_frames += 1 n_updates += app.screen._update_count update_time += app.screen._update_duration app.run() updates_per_ms = n_updates / update_time / 1000 updates_per_ms_real = n_updates / (perf_counter() - t0) / 1000 print("Updates per ms (updating): {:.2f}".format(updates_per_ms)) print("Updates per ms (real time): {:.2f}".format(updates_per_ms_real)) print("Average update time ms: {:.2f}".format(update_time / n_frames * 1000)) print("Average potential FPS: {:.2f}".format(n_frames / update_time))
def on_frame(): app.screen.clear() app.screen.cursor_pos = (c_x, c_y) P.update(buf, w, h) P.draw(app.screen, buf, w, h) if show_help: app.screen.print(helptext, 1, 1, fg=Color.rgb(1, 1, 1)) app.screen.update()
def redraw(app): white = Color.rgb(1, 1, 1) gray = Color.rgb(0.5, 0.5, 0.5) yellow = Color.rgb(1, 1, 0) app.screen.clear(bg=Color(0, 0, 0)) app.screen.fill(1, 1, app.screen.w - 2, app.screen.h - 2, bg=Color.rgb(0.2, 0.2, 0.2)) app.screen.print("Termpixels version {}\n".format(termpixels.__version__), 2, 2, fg=white) app.screen.print("Detected terminal: ", x=2, fg=gray) app.screen.print(app.backend.terminal_name, fg=yellow) app.screen.print("\n") app.screen.print("Color support: ", x=2, fg=gray) app.screen.print(app.backend.color_mode, fg=yellow) app.screen.print("\n") steps = app.screen.w - 4 for x in range(steps): app.screen.print(" ", x=x + 2, bg=Color.hsl(x / steps, 1, 0.5)) app.screen.print("\n") app.screen.print("Last keypress: ", x=2, fg=gray) app.screen.print(repr(app.key), fg=white) app.screen.print("\n") app.screen.print("Last render time: ", x=2, fg=gray) app.screen.print("{:.1f}ms".format(app.screen._update_duration * 1000), fg=white) app.screen.print("\n") if app.mouse: app.screen.print(" ", app.mouse.x, app.mouse.y, bg=white) app.screen.update()
def frame_game(): nonlocal control_x, control_y nonlocal score, hiscore nonlocal mode # handle input if control_x != 0 and not worm.intersecting(worm.x + control_x, worm.y): worm.vx = control_x worm.vy = 0 control_x = 0 if control_y != 0 and not worm.intersecting(worm.x, worm.y + control_y): worm.vy = control_y worm.vx = 0 control_y = 0 if worm.intersecting(food_x, food_y): score += 1 worm.length += 1 hiscore = max(hiscore, score) save_hiscore(hiscore) move_food() game_buffer.clear() game_buffer.print("░░", food_x * 2, food_y) try: worm.update(game_buffer) except GameOver: mode = MODE_GAMEOVER multiply_buffer(game_buffer, 0.4) return # draw app.screen.clear() app.screen.print("~TermWorm~", 0, 0) app.screen.print("Score: {}".format(score), 0, 1, fg=Color.rgb(.7,.7,.7)) app.screen.print(" Hi: {}".format(hiscore), fg=Color.rgb(.7,.7,0)) draw_box(app.screen, 0, 2, app.screen.w, 1, chars=BOX_CHARS_DOUBLE) app.screen.blit(game_buffer, 0, ui_height) app.screen.update()
def main(): backend = App().backend backend.enter_alt_buffer() colors = [ Color.rgb(1, 0, 0), Color.rgb(1, 1, 0), Color.rgb(0, 1, 0), Color.rgb(0, 1, 1), Color.rgb(0, 0, 1), Color.rgb(1, 0, 1) ] t0 = perf_counter() frames = 0 pos = 0 while frames < 10000: backend.bg = colors[frames % len(colors)] backend.write(" ") backend.flush() frames += 1 t1 = perf_counter() backend.exit_alt_buffer() backend.flush() tpf = (t1 - t0) / frames print("Terminal: {}\n".format(backend.terminal_name)) print("Avg time per frame: {:.4f}\n".format(tpf)) print("Avg framerate: {:.2f}\n".format(1 / tpf))
def update(self, buffer): self.old += [(self.x, self.y)] if len(self.old) > self.length: self.old.pop(0) for i, (x, y) in enumerate(self.old): col = Color.rgb(1,1,0) buffer.print("██", x * 2, y, fg=col) if self.intersecting(self.x + self.vx, self.y + self.vy): raise GameOver() self.x += self.vx self.y += self.vy self.wrap(buffer)
def on_frame(self): if self.need_resize: self.do_resize() for x in range(self.screen.w): for y in range(1, self.screen.h*2): i = y*self.screen.w + x self.propagate(i) self.screen.clear() self.screen.print(TITLE, self.screen.w // 2 - TITLE_W // 2, 2, fg=Color.rgb(1,1,1), bg=Color.rgb(0,0,0)) for x in range(self.screen.w): for y in range(0, self.screen.h): i = y*2*self.screen.w + x top = min(36, self.heightmap[i]) bot = min(36, self.heightmap[i+self.screen.w]) if top > 0 or bot > 0: self.screen.print("▄", x, y, bg=COLOR_MAP[top], fg=COLOR_MAP[bot]) self.screen.update()
def on_frame(): for x, p in enumerate(cols): # update colors for i in range(int(p.length) + 1): col = Color.hsl(HUE / 360, 1, (1 - i / p.length)**2) a.screen.at(x, int(p.pos - i + p.speed), clip=True).fg = col # render new characters for i in range(int(p.speed) + 1): pos = p.pos + i a.screen.print(" ", x, int(pos - p.length), fg=Color.rgb(0, 0, 0)) a.screen.print(randchar(), x, int(pos)) # randomly change a character a.screen.print(randchar(), x, int(p.pos + p.speed - randint(1, int(p.length)))) # move particle p.pos += p.speed if p.pos - p.length >= a.screen.h: cols[x] = Particle() a.screen.update()
def on_frame(): w = app.screen.w h = app.screen.h colormap = [Color.rgb(0,0,0) for x in range(w) for y in range(h * 2)] dx = app.mouse_x - app.mouse_px dy = app.mouse_y - app.mouse_py l = math.sqrt(dx ** 2 + dy ** 2) d = math.atan2(dy, dx) j = min(25, int(l)) * 6 for i in range(j): f = i / j ll = l* random.uniform(0.25, 0.5) dd = d + random.uniform(-0.25, 0.25) vx = ll * math.cos(dd) vy = ll * math.sin(dd) app.particles.append(Particle(app.mouse_px + dx * f, app.mouse_py + dy * f, vx, vy)) app.screen.clear() for i, p in enumerate(app.particles): col = Color.hsl(i/len(app.particles), 1.0, 0.5) steps = math.hypot(p.vx, p.vy) for step in range(int(steps + 1)): f = step / steps px = int(p.x - p.vx * f) py = int(p.y - p.vy * f) if px >= 0 and py >= 0 and px < w and py < h * 2: colormap[py * w + px] += RED p.update() if p.x < 0 or p.y < 0 or p.x >= w or p.y >= h * 2: app.particles.remove(p) draw_colormap_2x(app.screen, colormap, 0, 0, w=w, h=h * 2) app.screen.update() app.mouse_px = app.mouse_x app.mouse_py = app.mouse_y
def on_start(): app.screen.print("Resize the terminal.", 1, 1, fg=Color.rgb(0, 1, 0)) app.screen.update()
from termpixels import App, Color if __name__ == "__main__": # it's possible to not "start" an App and just use its terminal backend. term = App().backend term.fg = Color.rgb(1, 0, 1) term.write("Hello world\n") term.flush() term.fg = Color.rgb(1, 1, 0) term.flush() print("print() works too; just flush first.")
import sys from termpixels import App, Color from time import perf_counter AQUA = Color.rgb(0, 1, 1) def main(): app = App(framerate=float("inf")) app.t0 = perf_counter() app.frames = 0 app.pos = 0 @app.on("frame") def on_frame(): app.pos = (app.pos + 1) % (app.screen.w * app.screen.h) x = app.pos % app.screen.w y = app.pos // app.screen.w app.screen.clear() app.screen.print(" " * 5, x, y, bg=AQUA) app.screen.update() app.frames += 1 app.t1 = perf_counter() @app.on("after_stop") def on_after_stop(): tpf = (app.t1 - app.t0) / app.frames print("Terminal: {} ({}x{})\n".format(app.backend.terminal_name, app.screen.w, app.screen.h)) print("Avg time per frame: {:.4f}\n".format(tpf)) print("Avg framerate: {:.2f}\n".format(1 / tpf))
if "name" in node and node["name"] == name: return node return None return find(layout[ROOT]) def _merge(source, target): result = target.copy() for k, v in source.items(): result[k] = v return result STYLE_DEFAULTS = { "bg": Color.rgb(0.2, 0.2, 0.2), "fg": Color.rgb(0.8, 0.8, 0.8), "h-align": "left", "v-align": "top" } def _parse_style(style): s = style.copy() if "fg" in s: s["fg"] = Color(s["fg"]) if "bg" in s: s["bg"] = Color(s["bg"]) return s
import math import time from termpixels import App, Color, Buffer from termpixels.drawing import draw_box, draw_hline, draw_spinner, draw_progress, draw_colormap, draw_colormap_2x from termpixels.drawing import BOX_CHARS_LIGHT_DOUBLE_TOP, SPINNER_PIPE, SPINNER_MOON, SPINNER_BAR, SPINNER_CLOCK, SPINNER_DOTS, PROGRESS_SMOOTH from termpixels.util import wrap_text WHITE = Color.rgb(1, 1, 1) GREY = Color.rgb(0.5, 0.5, 0.5) YELLOW = Color.rgb(0.5, 0.5, 0) BRIGHT_YELLOW = Color.rgb(1, 1, 0) GREEN = Color.rgb(0, 0.5, 0) LIPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec erat quis turpis ultrices eleifend id et urna. Praesent ultricies orci fermentum, placerat eros id, scelerisque mi. Aenean lobortis pellentesque diam, vel auctor felis semper in. Aliquam cursus diam sit amet lorem faucibus, eget sagittis eros bibendum. Maecenas dignissim libero." # a frightening hand-drawn smiley face SMILEY = list(map( lambda b: [None, YELLOW, GREEN, GREY][b], [0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 1, 0, 1, 3, 3, 3, 1, 0, 0, 0, 1, 1, 1, 0, 0] )) def main(): app = App() inner_buffer = Buffer(0, 0)
from termpixels import App, Color from unicodedata import category COL_FG = Color.rgb(0.8, 0.8, 0.8) COL_CTRL = Color.rgb(0.8, 0.0, 0.8) COL_NUM = Color.rgb(0.8, 0.4, 0.0) COL_PUNC = Color.rgb(0.0, 0.4, 0.8) COL_SEP = Color.rgb(0.2, 0.0, 0.2) def main(): app = App(mouse=True) in_buffer = [] @app.input.on("raw_input") def on_raw(data): in_buffer.append(data) def print_escape(line, x, y): app.screen.print_pos = (x, y) for ch in line: fg = COL_FG bg = None cat = category(ch) if "C" in cat: fg = COL_CTRL elif "N" in cat: fg = COL_NUM elif "P" in cat:
import random import math from termpixels import App, Color from termpixels.drawing import draw_colormap_2x RED = Color.rgb(0.25,0.1,0.05) class Particle: def __init__(self, x, y, vx = 0, vy = 0): self.x = x self.y = y self.vx = vx self.vy = vy def update(self): self.x += self.vx self.y += self.vy self.vy += 0.1 def main(): app = App(mouse=True, framerate=60) app.mouse_x = 0 app.mouse_y = 0 app.mouse_px = 0 app.mouse_py = 0 app.particles = [] @app.on("mouse") def on_mouse(m): app.mouse_x = m.x
from termpixels import App, Color from random import random from time import perf_counter helptext = """Use mouse or arrow keys to move cursor. Use left/right click or Z/X to add/remove sand.""" props = { "air": { "color": Color.rgb(0, 0, 0), "falling": False, "density": 1, "sliding": False }, "sand": { "falling": True, "density": 2, "sliding": True } } class P: def __init__(self, *, color, falling, density, sliding): self.color = color self.falling = falling self.density = density self.sliding = sliding @staticmethod def update(buf, w, h):
def start(): global cols cols = [Particle() for x in range(a.screen.w)] a.screen.clear(fg=Color.rgb(0, 0, 0))
def on_frame(): clock_time = time.strftime("%H:%M:%S", time.gmtime()) app.screen.print("Clock: " + clock_time, 1, 1) try: app.backend.window_title = clock_time except: app.screen.print("Terminal does not support setting window title", 1, 2, fg=Color.rgb(1,0,0)) app.screen.update()
def on_start(): app.buffer = Buffer(16, 4) app.buffer.clear(bg=Color.rgb(0.2, 0, 0), fg=Color.rgb(1, 0.5, 0.5)) app.buffer.print("Hello world")
from termpixels import App, Color, Buffer, SparseBuffer a = App() b = Buffer(16, 8) sb = SparseBuffer(16, 8) b.clear(bg=Color.rgb(0.5, 0, 0)) b.print("Hello Buffer!") sb.clear(bg=Color.rgb(0, 0.5, 0)) sb.print("Hello Sparse!") @a.on("frame") def frame(): a.screen.clear() a.screen.blit(b, 1, 1) a.screen.blit(sb, 1 + b.w + 1, 1) a.screen.print_pos = (1, 1 + b.h + 1) a.screen.print(f"Pixels in buffer: {b.w * b.h}\n") a.screen.print(f"Pixels in sparse buffer: {sb._pixel_count}\n") a.screen.update() if __name__ == "__main__": a.run()