Skip to content

Instantly share code, notes, and snippets.

@salt-die
Last active May 30, 2020 21:23
Show Gist options
  • Save salt-die/c7db1ea3ce4ecc77dee0e71d85e1aa14 to your computer and use it in GitHub Desktop.
Save salt-die/c7db1ea3ce4ecc77dee0e71d85e1aa14 to your computer and use it in GitHub Desktop.
2d raycaster that runs in your terminal!
from collections import defaultdict
import os
import time
import numpy as np
from pynput import keyboard
from pynput.keyboard import Key
TERMX, TERMY = os.get_terminal_size()
def center(*lines):
for line in lines:
yield line.center(TERMX)
class RayCaster:
keys = defaultdict(bool)
directions = ((Key.up, (-1, 0)),
(Key.right, (0, 1)),
(Key.down, (1, 0)),
(Key.left, (0, -1)))
running = True
def __init__(self, DIM, pos=(10,10)):
self.DIM = DIM
self.grid = np.pad(np.full(DIM, 1, dtype=int), pad_width=1,
mode='constant', constant_values=2)
for _ in range(40):
self.grid[np.random.randint(DIM[1]), np.random.randint(DIM[0])] = 2
self.pos = np.array(pos)
self.listener = keyboard.Listener(on_press=self.pressed)
self.listener.start()
def pressed(self, key):
self.keys[key] = True
def grid_rays(self, angle):
angle = np.array([np.cos(angle), np.sin(angle)])
with np.errstate(divide="ignore"):
delta = abs(1/angle)
step = 2 * np.heaviside(angle, 1) - 1
side_dis = ((step + 1) / 2) * delta
map_pos = self.pos.copy()
while True:
side = 0 if side_dis[0] < side_dis[1] else 1
side_dis[side] += delta[side]
map_pos[side] += step[side]
self.revealed[tuple(map_pos)] = self.grid[tuple(map_pos)]
if self.grid[tuple(map_pos)] == 2:
break
def print_revealed(self):
print(*center(*(" ".join(" .W@"[value] for value in row)
for row in self.revealed)), sep="\n")
def start(self):
while self.running:
self.revealed = np.zeros_like(self.grid)
# Cast rays
for theta in np.linspace(0, 2*np.pi, 100, endpoint=False):
self.grid_rays(theta)
self.revealed[tuple(self.pos)] = 3
os.system("clear")
self.print_revealed()
time.sleep(.2)
# Input handling
for key, direction in self.directions:
if (self.keys[key] and
all(1 <= pos + dir_ <= dim for pos, dir_, dim in zip(self.pos, direction, self.DIM))):
self.pos += direction
self.keys[key] = False
if self.keys[Key.esc]:
self.running = False
self.listener.stop()
if __name__=="__main__":
RayCaster((40, 40)).start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment