Last active
February 21, 2023 17:57
-
-
Save benekastah/ec703f11b696e158bd11dffbb0cfc33d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
import subprocess, sys, time | |
FRAME_RATE = 30 | |
def wrap_pos(pos: int, canvas_size: int): | |
while True: | |
pos %= canvas_size | |
yield pos | |
pos += 1 | |
class GameObject: | |
image = None | |
devlogs = [] | |
def __init__(self, position, velocity=None): | |
self.position = position | |
self.start_position = position | |
self.velocity = velocity or (0, 0) | |
def tick(self, dt, canvas_size): | |
self.devlogs = [] | |
self.position = (self.start_position[0] + self.velocity[0] * dt, self.start_position[1] + self.velocity[1] * dt) | |
def wrap_position(self, pos, canvas_size, image_size): | |
return pos % canvas_size | |
def positions(self, pos: int, canvas_size: int, image_size: int): | |
while True: | |
pos = self.wrap_position(pos, canvas_size, image_size) | |
yield pos | |
pos += 1 | |
def draw(self, canvas): | |
for y_pos, line in zip(self.positions(round(self.position[1]), len(canvas), self.height), self.full_image): | |
try: | |
for x_pos, ch in zip(self.positions(round(self.position[0]), len(canvas[y_pos]), self.width), line): | |
canvas[y_pos][x_pos] = ch | |
except IndexError: | |
pass | |
@property | |
def full_image(self): | |
return self.image + self.devlogs | |
@property | |
def width(self): | |
return max(len(l) for l in self.full_image) | |
@property | |
def height(self): | |
return len(self.full_image) | |
def log(self, msg): | |
self.devlogs.append(str(msg)) | |
class BounceyBall(GameObject): | |
dt_offset = 0 | |
def __init__(self, position, velocity=None): | |
super().__init__(position, velocity) | |
def wrap_position(self, pos, canvas_size, image_size): | |
moving_left = int(pos / canvas_size) % 2 == 0 | |
if moving_left: | |
pos = abs(pos) % canvas_size | |
else: | |
pos = canvas_size - (pos % canvas_size) | |
return pos | |
def positions(self, pos: int, canvas_size: int, image_size: int): | |
# width_edge = canvas_size - image_size | |
# wrapped_pos = self.wrap_position(pos, canvas_size, image_size) | |
# moving_left = int(pos / canvas_size) % 2 == 0 | |
while True: | |
pos = self.wrap_position(pos, canvas_size, image_size) | |
yield pos | |
pos += 1 | |
class SquattyP(BounceyBall): | |
image = [ | |
' .:------::. ', | |
' :--:.. ..:--:. ', | |
' --: .:::::. :--. ', | |
' .-: :--:....::--: :=: ', | |
' :=. :--. ... .--. :=: ', | |
' .=: :=: .--:::--. :=. -= ', | |
' := =- :=: :=. -- .=:', | |
' -= .=: -=. .=: -= .=:', | |
' -= .=: -=-. :-- .=- :=.', | |
' -= .=: -=::---:. .-- -- ', | |
' -= .=: -=. .--: .-- ', | |
' -= --. -=-------:. :=: ', | |
' -=--: :=: .--: ', | |
' -= .-=--::::::---:. ', | |
' -=::-=-: ...... ', | |
] | |
class Cloud(GameObject): | |
image = [ | |
' _ _', | |
' ( ` )_', | |
' ( ) `)', | |
'(_ (_ . _) _)', | |
] | |
def __init__(self, canvas_size, min_velocity=5, max_velocity=10): | |
position = tuple( | |
random.uniform(0, d) | |
for d in canvas_size | |
) | |
velocity = [ | |
random.uniform(min_velocity, max_velocity) | |
for _ in range(2) | |
] | |
# let horizontal velocity be bigger than vertical | |
velocity[1] /= 4 | |
super().__init__(position, velocity) | |
class Star(GameObject): | |
stages = ['*', '·', ' '] | |
last_twinkle = 0 | |
def __init__(self, canvas_size, min_twinkle_rate=.2, max_twinkle_rate=.8): | |
self.stage = random.choice(range(len(self.stages))) | |
position = tuple( | |
random.uniform(0, d) | |
for d in canvas_size | |
) | |
self.twinkle_rate = random.uniform(min_twinkle_rate, max_twinkle_rate) | |
super().__init__(position) | |
@property | |
def image(self): | |
return [self.stages[self.stage]] | |
def tick(self, dt, canvas_size): | |
if (dt - self.last_twinkle) > self.twinkle_rate: | |
self.last_twinkle = dt | |
self.stage = (self.stage + 1) % len(self.stages) | |
def main(height=40, width=100): | |
canvas_size = (width, height) | |
objects = [ | |
*(Star(canvas_size) for _ in range(80)), | |
*(Cloud(canvas_size) for _ in range(3)), | |
SquattyP((10, 8), (20, 20)), | |
*(Cloud(canvas_size) for _ in range(2)), | |
] | |
start_t = time.time() | |
while True: | |
td = time.time() - start_t | |
canvas = [[' ' for _ in range(width)] for _ in range(height)] | |
for obj in objects: | |
obj.draw(canvas) | |
obj.tick(td, canvas_size) | |
subprocess.run('clear') | |
print('\n'.join(''.join(line) for line in canvas)) | |
sys.stdout.flush() | |
time.sleep(1 / FRAME_RATE) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment