Skip to content

Instantly share code, notes, and snippets.

@Sorseg
Last active June 16, 2016 06:52
Show Gist options
  • Save Sorseg/02668758ba45626b3afa9b52172939ac to your computer and use it in GitHub Desktop.
Save Sorseg/02668758ba45626b3afa9b52172939ac to your computer and use it in GitHub Desktop.
import turtle
from collections import namedtuple
from math import sin
from random import choice, randint as ri
import time
WIDTH_BASE = [1, 10]
WIDTH_PERIOD = [1, 100]
WIDTH_AMP = [0, 20]
def get_random_period():
return float(choice([13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151]))
COLOR_DIA = [0, 0]
COLOR_AMP = 255
class Osc(namedtuple('Osc', ['width', 'period', 'amp'])):
def val(self, phase):
return int(self.width + (1 + sin(phase / float(self.period))) * self.amp / 2.0)
class Plotter(object):
def __init__(self, scale=5):
self.width = 1000
self.height = 600
self.periods = Periodizer()
self.pen = None
self.color = None
self.scale = scale
def init(self):
turtle.speed(0)
turtle.colormode(255)
self.randomize(False)
def randomize(self, pos=True, phase=0):
if pos:
turtle.setpos(ri(-self.width / 2, self.width / 2), ri(-self.height / 2, self.height / 2))
self.periods.randomize()
self.pen = Osc(width=ri(*WIDTH_BASE), period=ri(*WIDTH_PERIOD), amp=ri(*WIDTH_AMP))
self.color = [Osc(width=ri(*COLOR_DIA), period=ri(1, 100), amp=ri(0, COLOR_AMP)) for _ in range(3)]
self.update_pen(phase)
def update_pen(self, phase):
turtle.pensize(self.pen.val(phase))
turtle.pencolor([c.val(phase) for c in self.color])
def iterate(self, phase):
slight_drift = int(sin(phase / 6410.0) * 360 + sin(phase / 9970.0) * 360)
sped_up_phase = phase * self.scale
angle = int(sin(sped_up_phase / self.periods[0]) * 360 +
sin(sped_up_phase / self.periods[1]) * 40 +
sin(sped_up_phase / self.periods[2]) * 100 +
sin(sped_up_phase / self.periods[3]) * sin(sped_up_phase / self.periods[4]) * 300) + \
slight_drift
thrust = max(10, int(abs(sin(phase / self.periods[3]) * 7) + sin(phase / self.periods[4]) * 4))
turtle.setheading(angle)
turtle.forward(thrust)
self.update_pen(phase)
x, y = turtle.pos()
if abs(x) > self.width / 2 or abs(y) > self.height / 2:
turtle.penup()
self.randomize(phase=phase)
turtle.pendown()
class Periodizer(object):
def __init__(self):
self.periods = []
def __getitem__(self, item):
while len(self.periods) <= item:
self.periods.append(get_random_period())
# print ', '.join('{}:{}'.format(i, p) for i, p in enumerate(self.periods))
return self.periods[item]
def randomize(self):
self.periods = [get_random_period() for p in self.periods]
print ', '.join('{}:{}'.format(i, p) for i, p in enumerate(self.periods))
p = Plotter(scale=4)
p.init()
phase = 1
# N = 100
# times = [0]*N
while True:
# t = time.time()
p.iterate(phase)
phase += 1
# times[phase % N] = time.time() - t
# if not phase % N:
# print "avg frame time", sum(times) / N
turtle.exitonclick()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment