Skip to content

Instantly share code, notes, and snippets.

@loganzartman
Created April 5, 2019 07:38
Show Gist options
  • Save loganzartman/039a902fe61594d6ca29e70fac587415 to your computer and use it in GitHub Desktop.
Save loganzartman/039a902fe61594d6ca29e70fac587415 to your computer and use it in GitHub Desktop.
termpixels demo
"""
star-run.py
dependencies: termpixels 0.0.6 (via pip)
"""
import operator
import math
from random import uniform
from termpixels import App, Color
class Vec:
def __init__(self, x, y):
self.x = x
self.y = y
def _component_op(self, op, other):
if isinstance(other, Vec):
return Vec(op(self.x, other.x), op(self.y, other.y))
return Vec(op(self.x, other), op(self.y, other))
def __add__(self, other):
return self._component_op(operator.add, other)
def __sub__(self, other):
return self._component_op(operator.sub, other)
def __mul__(self, other):
return self._component_op(operator.mul, other)
def __truediv__(self, other):
return self._component_op(operator.truediv, other)
def __mod__(self, other):
return self._component_op(operator.mod, other)
def __str__(self):
return "({}, {})".format(self.x, self.y)
def print_block_ysub(screen, x, y, **kwargs):
frac = y % 1
if frac > 0.5:
screen.print("▄\n▀", int(x), int(y), **kwargs)
else:
screen.print("█", int(x), int(y), **kwargs)
VIEW_BAND = Vec(20, 5)
class Player:
def __init__(self):
self.p = Vec(0,30)
self.v = Vec(0,0)
def update(self, screen, world):
#if world.height_at(self.p.x) + 2 > self.p.y:
# raise Exception("Game over")
self.p = self.p + self.v
self.v.y -= 0.05
self.v *= 0.98
h = world.height_at(round(self.p.x))
if h > self.p.y:
self.v.y = h - self.p.y
self.p.y = h
p = self.p - world.scroll
print_block_ysub(screen, p.x, screen.h - p.y, fg=Color.rgb(1,0.1,0.3))
self.update_view(screen, world)
def update_view(self, screen, world):
view_left = world.scroll.x + VIEW_BAND.x
view_right = world.scroll.x + screen.w - VIEW_BAND.x
view_top = world.scroll.y + VIEW_BAND.y
view_bottom = world.scroll.y + screen.h - VIEW_BAND.y
if self.p.x > view_right:
world.scroll.x = self.p.x - screen.w + VIEW_BAND.x
if self.p.x < view_left:
world.scroll.x = self.p.x - VIEW_BAND.x
if self.p.y > view_bottom:
world.scroll.y = self.p.y - screen.h + VIEW_BAND.y
if self.p.y < view_top:
world.scroll.y = self.p.y - VIEW_BAND.y
def jump(self):
self.v.y += 1
def left(self):
self.v.x -= 1
def right(self):
self.v.x += 1
class World:
def __init__(self):
self.scroll = Vec(0,0)
def height_at(self, x):
def octave(n, x):
n += 1
return math.sin(x * n * 0.03317) ** 3 * 4 / n
acc = 10
for i in range(5):
acc += octave(i, x)
return acc
def update(self, screen):
for x in range(screen.w):
h = self.height_at(x + self.scroll.x)
y = screen.h + self.scroll.y
i = 0
while h - i >= 0:
f = i / h
col = Color.rgb(f, f, f)
screen.print(":" if h - i > 0.5 else ".", x, int(y - i), fg=col)
i += 1
class Starfield:
def __init__(self):
self.stars = None
def rebuild(self, screen, n=100):
self.stars = [(Vec(uniform(0, screen.w), uniform(0, screen.h)), uniform(0, 1)) for i in range(n)]
def update(self, screen, world):
if self.stars is None:
return
for p, depth in self.stars:
p = (p - world.scroll / (depth * 2 + 1)) % Vec(screen.w, screen.h)
col = Color.hsl(0.8, 0.7, 1-depth)
screen.print("*", round(p.x), round(screen.h-p.y), fg=col)
class RunApp(App):
def __init__(self):
super().__init__(framerate=60)
def on_start(self):
self.world = World()
self.player = Player()
self.starfield = Starfield()
self._dirty = True
def on_resize(self):
self._dirty = True
def on_frame(self):
if self._dirty:
self.starfield.rebuild(self.screen)
self._dirty = False
self.screen.clear()
self.starfield.update(self.screen, self.world)
self.world.update(self.screen)
self.player.update(self.screen, self.world)
self.screen.update()
def on_key(self, k):
if k == "z" or k == " ":
self.player.jump()
if k == "a" or k == "left":
self.player.left()
if k == "d" or k == "right":
self.player.right()
if __name__ == "__main__":
RunApp().start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment