예제 #1
0
 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)
예제 #2
0
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
예제 #3
0
 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()
예제 #4
0
 def on_resize():
     app.screen.clear()
     app.screen.fill(0, 0, app.screen.w, app.screen.h, bg=Color(0, 255, 0))
     app.screen.fill(1,
                     1,
                     app.screen.w - 2,
                     app.screen.h - 2,
                     bg=Color(0, 0, 0))
     app.screen.print("{} x {}".format(app.screen.w, app.screen.h), 2, 2)
     app.screen.update()
예제 #5
0
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()
예제 #6
0
    def on_frame():
        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(45, int(l)) * 2
        for i in range(j):
            f = i / j
            ll = l * random.uniform(0.25, 0.5)
            dd = d + random.uniform(-0.2, 0.2)
            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)
            app.screen.print(" ", int(p.x), int(p.y), bg=col)
            p.update()
            if p.x < 0 or p.y < 0 or p.x >= app.screen.w or p.y >= app.screen.h:
                app.particles.remove(p)
        app.screen.update()

        app.mouse_px = app.mouse_x
        app.mouse_py = app.mouse_y
예제 #7
0
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))
예제 #8
0
 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()
예제 #9
0
def log(s):
    global scroll_y
    for line in splitlines_print(s):
        b.print(line, fg=Color.hsl(time() * 0.2, 0.5, 0.4))
        b.print_pos = (0, b.print_pos[1] + 1)
        b.extend_to(0, b.print_pos[1] + 1)
    if autoscroll:
        scroll_y = b.print_pos[1] - a.screen.h
예제 #10
0
 def do_box(buffer):
     if drag_start is None or mouse_pos is None:
         return
     x, y, w, h = corners_to_box(*drag_start, *mouse_pos)
     # draw_box(buffer, x, y, w, h, chars=BOX_CHARS_DOUBLE, fg=Color.hsl(perf_counter(), 1.0, 0.5))
     draw_frame(buffer,
                x,
                y,
                w,
                h,
                chars=FRAME_CHARS_DOUBLE,
                fg=Color.hsl(perf_counter(), 1.0, 0.5))
예제 #11
0
    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()
예제 #12
0
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))
예제 #13
0
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()
예제 #14
0
    def interact(place):
        nonlocal show_help
        show_help = False

        x = c_x
        y = c_y * 2
        if x >= 0 and x < w and y >= 0 and y < h:
            if place:
                buf[y * w + x] = P(color=Color.hsl(perf_counter() * 0.25, 1,
                                                   0.5),
                                   **props["sand"])
            else:
                buf[y * w + x] = P(**props["air"])
예제 #15
0
    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
예제 #16
0
    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)
예제 #17
0
    def on_frame():
        app.screen.clear()  # remove everything from the screen
        text = "Hello world, from termpixels!"

        for i, c in enumerate(text):
            f = i / len(text)
            color = Color.hsl(f + time(), 1,
                              0.5)  # create a color from a hue value
            x = app.screen.w // 2 - len(
                text) // 2  # horizontally center the text
            offset = sin(time() * 3 + f * 5) * 2  # some arbitrary math
            y = round(app.screen.h / 2 +
                      offset)  # vertical center with an offset
            app.screen.print(c, x + i, y,
                             fg=color)  # draw the text to the screen buffer

        app.screen.update()  # commit the changes to the screen
예제 #18
0
 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()
예제 #19
0
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()
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.")
예제 #21
0
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))
예제 #22
0
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)
예제 #23
0
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
예제 #24
0
        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

예제 #25
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:
예제 #26
0
 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")
예제 #27
0
from termpixels.app import LegacyApp
from random import randint

# http://fabiensanglard.net/doom_fire_psx/

TITLE = u"""
   ▄▄▄▄▀ ▄███▄   █▄▄▄▄ █▀▄▀█ █ ▄▄  ▄█     ▄  ▄███▄   █      ▄▄▄▄▄   
▀▀▀ █    █▀   ▀  █  ▄▀ █ █ █ █   █ ██ ▀▄   █ █▀   ▀  █     █     ▀▄ 
    █    ██▄▄    █▀▀▌  █ ▄ █ █▀▀▀  ██   █ ▀  ██▄▄    █   ▄  ▀▀▀▀▄   
   █     █▄   ▄▀ █  █  █   █ █     ▐█  ▄ █   █▄   ▄▀ ███▄ ▀▄▄▄▄▀    
  ▀      ▀███▀     █      █   █     ▐ █   ▀▄ ▀███▀       ▀          
                  ▀      ▀     ▀       ▀                            
"""
TITLE_W = max(len(l) for l in TITLE.splitlines())

COLOR_MAP = [Color(i[0], i[1], i[2]) for i in [
    (0x07,0x07,0x07), (0x1F,0x07,0x07), (0x2F,0x0F,0x07), (0x47,0x0F,0x07),
    (0x57,0x17,0x07), (0x67,0x1F,0x07), (0x77,0x1F,0x07), (0x8F,0x27,0x07),
    (0x9F,0x2F,0x07), (0xAF,0x3F,0x07), (0xBF,0x47,0x07), (0xC7,0x47,0x07),
    (0xDF,0x4F,0x07), (0xDF,0x57,0x07), (0xDF,0x57,0x07), (0xD7,0x5F,0x07),
    (0xD7,0x5F,0x07), (0xD7,0x67,0x0F), (0xCF,0x6F,0x0F), (0xCF,0x77,0x0F),
    (0xCF,0x7F,0x0F), (0xCF,0x87,0x17), (0xC7,0x87,0x17), (0xC7,0x8F,0x17),
    (0xC7,0x97,0x1F), (0xBF,0x9F,0x1F), (0xBF,0x9F,0x1F), (0xBF,0xA7,0x27),
    (0xBF,0xA7,0x27), (0xBF,0xAF,0x2F), (0xB7,0xAF,0x2F), (0xB7,0xB7,0x2F),
    (0xB7,0xB7,0x37), (0xCF,0xCF,0x6F), (0xDF,0xDF,0x9F), (0xEF,0xEF,0xC7),
    (0xFF,0xFF,0xFF)]]

class DoomTerm(LegacyApp):
    def __init__(self):
        super().__init__(framerate=24)
예제 #28
0
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()
예제 #29
0
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):
예제 #30
0
def start():
    global cols
    cols = [Particle() for x in range(a.screen.w)]
    a.screen.clear(fg=Color.rgb(0, 0, 0))