956 lines · 26.0 KB · Python
RawDownload
# LogoMation-like turtle graphics """Turtle graphics is a popular way for introducing programming tokids. It was part of the original Logo programming language developedby Wally Feurzeig and Seymour Papert in 1966. Imagine a robotic turtle starting at (0, 0) in the x-y plane. Give itthe command turtle.forward(15), and it moves (on-screen!) 15 pixels inthe direction it is facing, drawing a line as it moves. Give it thecommand turtle.left(25), and it rotates in-place 25 degrees clockwise. By combining together these and similar commands, intricate shapes andpictures can easily be drawn.""" from math import * # Also for exportimport Tkinter speeds = ['fastest', 'fast', 'normal', 'slow', 'slowest'] class Error(Exception):    pass class RawPen:     def __init__(self, canvas):        self._canvas = canvas        self._items = []        self._tracing = 1        self._arrow = 0        self._delay = 10     # default delay for drawing        self._angle = 0.0        self.degrees()        self.reset()     def degrees(self, fullcircle=360.0):        """ Set angle measurement units to degrees.         Example:        >>> turtle.degrees()        """        # Don't try to change _angle if it is 0, because        # _fullcircle might not be set, yet        if self._angle:            self._angle = (self._angle / self._fullcircle) * fullcircle        self._fullcircle = fullcircle        self._invradian = pi / (fullcircle * 0.5)     def radians(self):        """ Set the angle measurement units to radians.         Example:        >>> turtle.radians()        """        self.degrees(2.0*pi)     def reset(self):        """ Clear the screen, re-center the pen, and set variables to        the default values.         Example:        >>> turtle.position()        [0.0, -22.0]        >>> turtle.heading()        100.0        >>> turtle.reset()        >>> turtle.position()        [0.0, 0.0]        >>> turtle.heading()        0.0        """        canvas = self._canvas        self._canvas.update()        width = canvas.winfo_width()        height = canvas.winfo_height()        if width <= 1:            width = canvas['width']        if height <= 1:            height = canvas['height']        self._origin = float(width)/2.0, float(height)/2.0        self._position = self._origin        self._angle = 0.0        self._drawing = 1        self._width = 1        self._color = "black"        self._filling = 0        self._path = []        self.clear()        canvas._root().tkraise()     def clear(self):        """ Clear the screen. The turtle does not move.         Example:        >>> turtle.clear()        """        self.fill(0)        canvas = self._canvas        items = self._items        self._items = []        for item in items:            canvas.delete(item)        self._delete_turtle()        self._draw_turtle()     def tracer(self, flag):        """ Set tracing on if flag is True, and off if it is False.        Tracing means line are drawn more slowly, with an        animation of an arrow along the line.         Example:        >>> turtle.tracer(False)   # turns off Tracer        """        self._tracing = flag        if not self._tracing:            self._delete_turtle()        self._draw_turtle()     def forward(self, distance):        """ Go forward distance steps.         Example:        >>> turtle.position()        [0.0, 0.0]        >>> turtle.forward(25)        >>> turtle.position()        [25.0, 0.0]        >>> turtle.forward(-75)        >>> turtle.position()        [-50.0, 0.0]        """        x0, y0 = start = self._position        x1 = x0 + distance * cos(self._angle*self._invradian)        y1 = y0 - distance * sin(self._angle*self._invradian)        self._goto(x1, y1)     def backward(self, distance):        """ Go backwards distance steps.         The turtle's heading does not change.         Example:        >>> turtle.position()        [0.0, 0.0]        >>> turtle.backward(30)        >>> turtle.position()        [-30.0, 0.0]        """        self.forward(-distance)     def left(self, angle):        """ Turn left angle units (units are by default degrees,        but can be set via the degrees() and radians() functions.)         When viewed from above, the turning happens in-place around        its front tip.         Example:        >>> turtle.heading()        22        >>> turtle.left(45)        >>> turtle.heading()        67.0        """        self._angle = (self._angle + angle) % self._fullcircle        self._draw_turtle()     def right(self, angle):        """ Turn right angle units (units are by default degrees,        but can be set via the degrees() and radians() functions.)         When viewed from above, the turning happens in-place around        its front tip.         Example:        >>> turtle.heading()        22        >>> turtle.right(45)        >>> turtle.heading()        337.0        """        self.left(-angle)     def up(self):        """ Pull the pen up -- no drawing when moving.         Example:        >>> turtle.up()        """        self._drawing = 0     def down(self):        """ Put the pen down -- draw when moving.         Example:        >>> turtle.down()        """        self._drawing = 1     def width(self, width):        """ Set the line to thickness to width.         Example:        >>> turtle.width(10)        """        self._width = float(width)     def color(self, *args):        """ Set the pen color.         Three input formats are allowed:             color(s)            s is a Tk specification string, such as "red" or "yellow"             color((r, g, b))            *a tuple* of r, g, and b, which represent, an RGB color,            and each of r, g, and b are in the range [0..1]             color(r, g, b)            r, g, and b represent an RGB color, and each of r, g, and b            are in the range [0..1]         Example:         >>> turtle.color('brown')        >>> tup = (0.2, 0.8, 0.55)        >>> turtle.color(tup)        >>> turtle.color(0, .5, 0)        """        if not args:            raise Error, "no color arguments"        if len(args) == 1:            color = args[0]            if type(color) == type(""):                # Test the color first                try:                    id = self._canvas.create_line(0, 0, 0, 0, fill=color)                except Tkinter.TclError:                    raise Error, "bad color string: %r" % (color,)                self._set_color(color)                return            try:                r, g, b = color            except:                raise Error, "bad color sequence: %r" % (color,)        else:            try:                r, g, b = args            except:                raise Error, "bad color arguments: %r" % (args,)        assert 0 <= r <= 1        assert 0 <= g <= 1        assert 0 <= b <= 1        x = 255.0        y = 0.5        self._set_color("#%02x%02x%02x" % (int(r*x+y), int(g*x+y), int(b*x+y)))     def _set_color(self,color):        self._color = color        self._draw_turtle()     def write(self, text, move=False):        """ Write text at the current pen position.         If move is true, the pen is moved to the bottom-right corner        of the text. By default, move is False.         Example:        >>> turtle.write('The race is on!')        >>> turtle.write('Home = (0, 0)', True)        """        x, y  = self._position        x = x-1 # correction -- calibrated for Windows        item = self._canvas.create_text(x, y,                                        text=str(text), anchor="sw",                                        fill=self._color)        self._items.append(item)        if move:            x0, y0, x1, y1 = self._canvas.bbox(item)            self._goto(x1, y1)        self._draw_turtle()     def fill(self, flag):        """ Call fill(1) before drawing the shape you         want to fill, and fill(0) when done.         Example:        >>> turtle.fill(1)        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.fill(0)        """        if self._filling:            path = tuple(self._path)            smooth = self._filling < 0            if len(path) > 2:                item = self._canvas._create('polygon', path,                                            {'fill': self._color,                                             'smooth': smooth})                self._items.append(item)        self._path = []        self._filling = flag        if flag:            self._path.append(self._position)     def begin_fill(self):        """ Called just before drawing a shape to be filled.            Must eventually be followed by a corresponding end_fill() call.            Otherwise it will be ignored.         Example:        >>> turtle.begin_fill()        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.end_fill()        """        self._path = [self._position]        self._filling = 1     def end_fill(self):        """ Called after drawing a shape to be filled.         Example:        >>> turtle.begin_fill()        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.left(90)        >>> turtle.forward(100)        >>> turtle.end_fill()        """        self.fill(0)     def circle(self, radius, extent = None):        """ Draw a circle with given radius.        The center is radius units left of the turtle; extent        determines which part of the circle is drawn. If not given,        the entire circle is drawn.         If extent is not a full circle, one endpoint of the arc is the        current pen position. The arc is drawn in a counter clockwise        direction if radius is positive, otherwise in a clockwise        direction. In the process, the direction of the turtle is        changed by the amount of the extent.         >>> turtle.circle(50)        >>> turtle.circle(120, 180)  # half a circle        """        if extent is None:            extent = self._fullcircle        frac = abs(extent)/self._fullcircle        steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac)        w = 1.0 * extent / steps        w2 = 0.5 * w        l = 2.0 * radius * sin(w2*self._invradian)        if radius < 0:            l, w, w2 = -l, -w, -w2        self.left(w2)        for i in range(steps):            self.forward(l)            self.left(w)        self.right(w2)     def heading(self):        """ Return the turtle's current heading.         Example:        >>> turtle.heading()        67.0        """        return self._angle     def setheading(self, angle):        """ Set the turtle facing the given angle.         Here are some common directions in degrees:            0 - east          90 - north         180 - west         270 - south         Example:        >>> turtle.setheading(90)        >>> turtle.heading()        90        >>> turtle.setheading(128)        >>> turtle.heading()        128        """        self._angle = angle        self._draw_turtle()     def window_width(self):        """ Returns the width of the turtle window.         Example:        >>> turtle.window_width()        640        """        width = self._canvas.winfo_width()        if width <= 1:  # the window isn't managed by a geometry manager            width = self._canvas['width']        return width     def window_height(self):        """ Return the height of the turtle window.         Example:        >>> turtle.window_height()        768        """        height = self._canvas.winfo_height()        if height <= 1: # the window isn't managed by a geometry manager            height = self._canvas['height']        return height     def position(self):        """ Return the current (x, y) location of the turtle.         Example:        >>> turtle.position()        [0.0, 240.0]        """        x0, y0 = self._origin        x1, y1 = self._position        return [x1-x0, -y1+y0]     def setx(self, xpos):        """ Set the turtle's x coordinate to be xpos.         Example:        >>> turtle.position()        [10.0, 240.0]        >>> turtle.setx(10)        >>> turtle.position()        [10.0, 240.0]        """        x0, y0 = self._origin        x1, y1 = self._position        self._goto(x0+xpos, y1)     def sety(self, ypos):        """ Set the turtle's y coordinate to be ypos.         Example:        >>> turtle.position()        [0.0, 0.0]        >>> turtle.sety(-22)        >>> turtle.position()        [0.0, -22.0]        """        x0, y0 = self._origin        x1, y1 = self._position        self._goto(x1, y0-ypos)     def towards(self, *args):        """Returs the angle, which corresponds to the line        from turtle-position to point (x,y).         Argument can be two coordinates or one pair of coordinates        or a RawPen/Pen instance.         Example:        >>> turtle.position()        [10.0, 10.0]        >>> turtle.towards(0,0)        225.0        """        if len(args) == 2:            x, y = args        else:            arg = args[0]            if isinstance(arg, RawPen):                x, y = arg.position()            else:                x, y = arg        x0, y0 = self.position()        dx = x - x0        dy = y - y0        return (atan2(dy,dx) / self._invradian) % self._fullcircle     def goto(self, *args):        """ Go to the given point.         If the pen is down, then a line will be drawn. The turtle's

Lines 1–500 of 956.