Just for fun I stole some of the turtle code, added docstrings, used complex as position format, and made a small (but not entirely minimal) turtle class. I figured this might do as a straw-man for Myrtle the Minimal Turtle. I do like Christian Mascher's idea of making a turtle with a contained Pen being how to control all of the "dir()" results.
--Scott David Daniels [EMAIL PROTECTED]
# $Id: myrtle.py 1.3 2006/03/04 22:54:25 daniels Exp daniels $ '''Myrtle the minimally complex turtle''' from math import sin, cos, tan, pi, atan2 import Tkinter __version__ = '0.3' __all__ = 'Turtle pi'.split() class Turtle(object): _root = None _canvas = None def destroy(self): '''Wipe out evidence of where the root and canvas are''' root = self.canvas._root() if root is self._root: self.__class__._root = None self.__class__._canvas = self.canvas = None root.destroy() def __init__(self, canvas=None, root=None): '''Make a turtle, and a canvas pen for it to play in (if necessary)''' # Make a canvas (and a root) if necessary, record root. if canvas is None: if root is None: if self.__class__._root is None: self.__class__._root = root = Tkinter.Tk() root.wm_protocol("WM_DELETE_WINDOW", self.destroy) root = self.__class__._root if self.__class__._canvas is None: canvas = Tkinter.Canvas(root, background="white") canvas.pack(expand=1, fill="both") self.__class__._canvas = canvas canvas = self.__class__._canvas elif self.__class__._root is None: if root is None: root = canvas._root() self.__class__._root = root self.canvas = canvas # The canvas playpen for our turtle self.items = [] # things showing on canvas self.tracing = True # moving in little increments self.arrow = 0 # The visible manifextation of the Turtle self.reset() # Set other things up def reset(self): '''Erase the canvas and place the turtle in the center''' self.canvas.update() # Make sure canvas is up-to-date # Find current window sizes, and set origin and position at center self.position = self.origin = self.window_dimension() * .5 # Set step-scaling and direction to right, 8 pixels self.heading = complex(8.) self.drawing = True # False for Pen-Up operation self.width = 1 # width of the line the turtle leaves behind self.ink = "black" # color of ink Turtle currently wielding self.filling = 0 # polygon (1), smooth (-1), or non-fill modes self.path = [] # Track of positions for use by fill modes self.clear() self.canvas._root().tkraise() # Pop turtle's canvas to top-o-screen def window_dimension(self): '''Get the width and height of the canvas''' width = self.canvas.winfo_width() if width <= 1: # the window isn't managed by a geometry manager width = self.canvas['width'] height = self.canvas.winfo_height() if height <= 1: # the window isn't managed by a geometry manager height = self.canvas['height'] return complex(width, height) def clear(self): '''Drop all known elements from the canvas''' self.fill(False) for item in self.items: self.canvas.delete(item) self.items = [] self.hide() self.show() def fill(self, flag): '''Fill path so far, then 0: no fill, 1: polygon fill, -1: smooth fill''' if self.filling: if len(self.path) > 2: # can't create filled anything with less than 2 points path = [(p.real, p.imag) for p in self.path] item = self.canvas._create('polygon', path, dict(fill=self.ink, smooth=self.filling < 0)) self.items.append(item) self.canvas.lower(item) self.path = [] self.filling = flag if flag: self.path.append(self.position) self.forward(0) def show(self, position=None): '''Make the turtle visible (if tracing)''' if self.tracing: if position is None: position = self.position back = position - 2 * self.heading self.hide() self.arrow = self.canvas.create_line(back.real, back.imag, position.real, position.imag, width=self.width, arrow="last", capstyle="round", fill=self.ink) self.canvas.update() def hide(self): '''Make the turtle invisible''' if self.arrow: self.canvas.delete(self.arrow) self.arrow = 0 def forward(self, distance=1): '''Move forward''' self.goto(self.position + distance * self.heading) def left(self, angle=pi/2): '''Rotate left angle radians.''' dist = abs(self.heading) angle += atan2(self.heading.real, self.heading.imag) self.heading = abs(self.heading) * complex(sin(angle), cos(angle)) if self.tracing: self.show() def goto(self, destination): '''Move the turtle to the destination.''' start = self.position self.position = destination if self.filling: self.path.append(self.position) if self.drawing: if self.tracing: delta = destination - start hops = int(abs(delta)) item = self.canvas.create_line(start.real, start.imag, start.real, start.imag, width=self.width, capstyle="round", fill=self.ink) try: for i in range(1, hops): pos = start + delta * i / hops self.canvas.coords(item, start.real, start.imag, pos.real, pos.imag) self.show(pos) self.canvas.update() self.canvas.after(10) self.canvas.coords(item, start.real, start.imag, destination.real, destination.imag) self.canvas.itemconfigure(item, arrow="none") except Tkinter.TclError: # Probably the window was closed! return else: item = self.canvas.create_line(start.real, start.imag, destination.real, destination.imag, width=self.width, capstyle="round", fill=self.ink) self.items.append(item) self.show() def write(self, text, move=False): '''Write text at the current position. If move True, position past it.''' x = self.position.real - 1 # correction -- calibrated for Windows y = self.position.imag if not isinstance(text, basestring): text = str(text) item = self.canvas.create_text(x, y, text=text, anchor="sw", fill=self.ink) self.items.append(item) if move: x0, y0, x1, y1 = self.canvas.bbox(item) self.goto(complex(x1, y1)) self.show() def color(self, *args): '''Set my ink color (name or r,g,b where 1,1,1 is pure white)''' if not args: raise Error, "no color arguments" if len(args) == 1: color = args[0] if isinstance(color, basestring): # 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 and 0 <= g <= 1 and 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): '''Set ink color by name only (for internal use)''' self.ink = color self.show()
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig