Created
January 14, 2010 17:04
-
-
Save bebraw/277317 to your computer and use it in GitHub Desktop.
This file contains 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 threading | |
import visual | |
# FIXME: closing VPython window directly kills the whole app! | |
# TODO: check if it's possible to catch "tab" for autocompletion | |
class Poller: | |
def __init__(self, thread_class, interpreter): | |
assert hasattr(interpreter, '__call__') | |
self.thread_class = thread_class | |
self.interpreter = interpreter | |
def poll(self): | |
self._set_up_thread() | |
while True: | |
while not self.thread.data_ready.isSet(): | |
pass | |
try: | |
self.interpreter(self.thread.data) | |
except SystemExit: | |
break | |
else: | |
self._set_up_thread() | |
def _set_up_thread(self): | |
self.thread = self.thread_class() | |
self.thread.start() | |
class KeyboardThread(threading.Thread): | |
def __init__(self): | |
self.data_ready = threading.Event() | |
super(KeyboardThread, self).__init__() | |
def run(self): | |
self.data = self.get_data() | |
self.data_ready.set() | |
class KeyboardInput(KeyboardThread): | |
def get_data(self): | |
return raw_input('>>> ') | |
class RepeatingTimer: | |
def __init__(self, interval, callback): | |
def repeat_callback(): | |
callback() | |
if self.running: | |
self._timer = self._create_timer() | |
self._timer.start() | |
self.interval = interval | |
self.repeat_callback = repeat_callback | |
def start(self): | |
self._timer = self._create_timer() | |
self.running = True | |
self._timer.start() | |
def _create_timer(self): | |
timer = threading.Timer(self.interval, self.repeat_callback) | |
# make sure thread gets killed on app quit | |
timer.daemon = True | |
return timer | |
def cancel(self): | |
self.running = False | |
class Bounce: | |
def __init__(self): | |
self.timer = RepeatingTimer(0.01, self._update) | |
self._init_done = False | |
def _update(self): | |
delta = 0.01 | |
self.ball.pos += self.ball.velocity * delta | |
if self.ball.y < 1: | |
self.ball.velocity.y *= -1 | |
else: | |
self.ball.velocity.y -= 9.8 * delta | |
def start(self): | |
if not self._init_done: | |
self._init() | |
self.timer.start() | |
def _init(self): | |
self.floor = visual.box(length=4, height=0.5, width=4, | |
color=visual.color.blue) | |
self.ball = visual.sphere(pos=(0,4,0), color=visual.color.red) | |
self.ball.velocity = visual.vector(0,-1,0) | |
self._init_done = True | |
def cancel(self): | |
self.timer.cancel() | |
def main(): | |
def interpreter(user_input): | |
def bounce(): | |
visual.scene.visible = True | |
v_bounce.start() | |
def kill_bounce(): | |
visual.scene.visible = False | |
v_bounce.cancel() | |
def hello(): | |
print 'Hello dude!' | |
def quit(): | |
print 'Bye bye!' | |
# kill VPython window | |
visual.scene.visible = False | |
raise SystemExit | |
handlers = {} | |
for k, v in locals().items(): | |
if hasattr(v, '__call__'): | |
command = k.replace('_', ' ') | |
handlers[command] = v | |
if user_input in handlers: | |
handlers[user_input]() | |
else: | |
print 'Invalid input!' | |
v_bounce = Bounce() | |
poller = Poller(KeyboardInput, interpreter) | |
poller.poll() | |
if __name__ == "__main__" : | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment