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,