diff options
Diffstat (limited to 'turtleprocess.py')
-rw-r--r-- | turtleprocess.py | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/turtleprocess.py b/turtleprocess.py new file mode 100644 index 0000000..e4af0f8 --- /dev/null +++ b/turtleprocess.py @@ -0,0 +1,254 @@ +import sys +import multiprocessing +import copy +import math +import time + +import smartsleep +import misc.angles as angles +import pyshell +import console +from my_turtle import * +from vector import Vector + +def log(x): + print(x) + sys.stdout.flush() + +class TurtleProcess(multiprocessing.Process): + """ + A TurtleProcess is a subclass of multiprocessing.Process. + It is the process from which the user of PythonTurtle works; + It defines all the turtle commands (i.e. go, turn, width, etc.). + Then it runs a shelltoprocess.Console which connects to the shell + in the main application window, allowing the user to control + this process. + """ + def __init__(self,*args,**kwargs): + multiprocessing.Process.__init__(self,*args,**kwargs) + + self.daemon=True + + + self.turtle_queue=multiprocessing.Queue() + self.queue_pack= [multiprocessing.Queue() for i in range(4)] + + + """ + Constants: + """ + self.FPS=25 + self.FRAME_TIME=1/float(self.FPS) + + + + def send_report(self): + """ + Sends a "turtle report" to the TurtleWidget. + By sending turtle reports every time the turtle does anything, + the TurtleWidget can always know where the turtle is going + and draw graphics accordingly. + """ + #self.turtle.fingerprint = random.randint(0,10000) + self.turtle_queue.put(self.turtle) + #log(self.turtle.__dict__) + + def run(self): + + self.turtle=Turtle() + + def go(distance): + """ + Makes the turtle walk the specified distance. Use a negative number + to walk backwards. + """ + if distance==0: return + sign=1 if distance>0 else -1 + distance=copy.copy(abs(distance)) + distance_gone=0 + distance_per_frame=self.FRAME_TIME*self.turtle.SPEED + steps=int(math.ceil(distance/float(distance_per_frame))) + angle=from_my_angle(self.turtle.orientation) + unit_vector=Vector((math.sin(angle),math.cos(angle)))*sign + step=distance_per_frame*unit_vector + for i in range(steps-1): + with smartsleep.Sleeper(self.FRAME_TIME): + self.turtle.pos+=step + self.send_report() + distance_gone+=distance_per_frame + + last_distance=distance-distance_gone + last_sleep=last_distance/float(self.turtle.SPEED) + with smartsleep.Sleeper(last_sleep): + last_step=unit_vector*last_distance + self.turtle.pos+=last_step + self.send_report() + + def turn(angle): + """ + Makes the turtle turn. Specify angle in degrees. A positive + number turns clockwise, a negative number turns counter-clockwise. + """ + if angle==0: return + sign=1 if angle>0 else -1 + angle=copy.copy(abs(angle)) + angle_gone=0 + angle_per_frame=self.FRAME_TIME*self.turtle.ANGULAR_SPEED + steps=int(math.ceil(angle/float(angle_per_frame))) + step=angle_per_frame*sign + for i in range(steps-1): + with smartsleep.Sleeper(self.FRAME_TIME): + self.turtle.orientation+=step + self.send_report() + angle_gone+=angle_per_frame + + last_angle=angle-angle_gone + last_sleep=last_angle/float(self.turtle.ANGULAR_SPEED) + with smartsleep.Sleeper(last_sleep): + last_step=last_angle*sign + self.turtle.orientation+=last_step + self.send_report() + + def color(color): + """ + Sets the color of the turtle's pen. Specify a color as a string. + + Examples: + color("white") + color("green") + color("#00FFCC") + """ + #if not valid_color(color): + # raise StandardError(color+" is not a valid color.") + self.turtle.color=color + self.send_report() + + def width(width): + """ + Sets the width of the turtle's pen. Width must be a positive number. + """ + #assert 0 < width + self.turtle.width = width + self.send_report() + + def visible(visible=True): + """ + By default, makes the turtle visible. You may specify a boolean + value, e.g. visible(False) will make the turtle invisible. + """ + self.turtle.visible = visible + self.send_report() + + def invisible(): + """ + Makes the turtle invisible. + """ + self.turtle.visible=False + self.send_report() + + def pen_down(pen_down=True): + """ + By default, puts the pen in the "down" position, making the turtle + leave a trail when walking. You may specify a boolean value, e.g. + pen_down(False) will put the pen in the "up" position. + """ + self.turtle.pen_down = pen_down + self.send_report() + + def pen_up(): + """ + Puts the pen in the "up" position, making the turtle not leave a + trail when walking. + """ + self.turtle.pen_down = False + self.send_report() + + def is_visible(): + """ + Returns whether the turtle is visible. + """ + return self.turtle.visible + + def is_pen_down(): + """ + Returns whether the pen is in the "down" position. + """ + return self.turtle.pen_down + + def sin(angle): + """ + Calculates sine, with the angle specified in degrees. + """ + return math.sin(angles.deg_to_rad(angle)) + + def cos(angle): + """ + Calculates cosine, with the angle specified in degrees. + """ + return math.cos(angles.deg_to_rad(angle)) + + def clear(): + """ + Clears the screen, making it all black again. + """ + self.turtle.clear=True + self.send_report() + time.sleep(0.1) + self.turtle.clear=False + self.send_report() + + """ + Had trouble implementing `home`. + I couldn't control when the turtle would actually draw a line home. + + def home(): + #\""" + Places the turtle at the center of the screen, facing upwards. + #\""" + old_pen_down = self.turtle.pen_down + pen_up() # Sends a report as well + self.send_report() + self.turtle.pos = Vector((0, 0)) + self.turtle.orientation = 180 + self.send_report() + time.sleep(3) + pen_down(old_pen_down) + """ + + def reset(): + """ + Resets all the turtle's properties and clears the screen. + """ + self.turtle = Turtle() + clear() + + #go(200) + #turn(90) + #go(200) + #turn(90) + #go(200) + #turn(90) + #go(200) + #turn(90) + + locals_for_console={"go": go, "turn": turn, "color": color, + "width": width, "visible": visible, + "invisible": invisible, "pen_down": pen_down, + "pen_up": pen_up, "is_visible": is_visible, + "is_pen_down": is_pen_down, "sin": sin, "cos": cos, + "turtle": self.turtle, "clear": clear, + "reset": reset} + + + """ + A little thing I tried doing for checking if a color is + valid before setting it to the turtle. Didn't work. + import wx; app=wx.App(); + def valid_color(color): + return not wx.Pen(color).GetColour()==wx.Pen("malformed").GetColour() + """ + + self.console = console.Console(queue_pack=self.queue_pack,locals=locals_for_console) + #import cProfile; cProfile.runctx("console.interact()", globals(), locals()) + self.console.interact() + #sys.stdout.flush() |