Turtle Graphics

January 3, 2012

We had fun drawing a fractal snowflake last week. In today’s exercise, we will write a full library for turtle graphics. Our goal is to provide the commands described in Brian Harvey’s book about Logo. The turtle is a robotic device that moves and draws on a graphical output device (paper, screen) with a coordinate system that has x running west (negative) to east (positive) and y running south (negative) to north (positive); the ordinal compass points are 0 north, 90 east, 180 south and 270 west. Most commands ignore the global coordinate system in favor of commands from the turtle’s point of view, so instead of saying “turn to 135 degrees” a typical command is “turn right 45 degrees,” so that a shape can be drawn without knowledge of its global coordinates. The turtle commands are:

clearscreen — initialize the graphics system and place the turtle in the center of the graphical output pointing north

penup — remove the pen from the drawing surface

pendown — place the pen on the drawing surface

forward n — move the turtle forward n steps, drawing a line if the pen is down

back n — move the turtle back n steps, drawing a line if the pen is down

left n — rotate the turtle n degrees left from its current heading

right n — rotate the turtle n degrees right from its current heading

setpos x y — move the turtle from its current position to the indicated coordinates, drawing a line if the pen is down

setheading n — rotate the turtle from its current heading to the indicated heading

pos — report the current position by its x and y coordinates

heading — report the current heading in degrees

Your task is to write a turtle graphics library. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

2 Responses to “Turtle Graphics”

  1. A module in python 3 and an example tree rewritten. Uses pygame.

    
    # myturtle.py
    
    import pygame
    import math
    
    _center = (400, 300)
    _pos = (0, 0)
    _ang = 0
    _pen = False
    _surf = None
    _changed = True
    _color = (0, 0, 0)
    
    def init_turtle(surf):
        global _surf, _center
        _surf = surf
        _center = (_surf.get_width() // 2, _surf.get_height() // 2)
    
    def pendown():
        global _pen    
        _pen = True
    
    def penup():
        global _pen
        _pen = False
    
    def clearscreen():
        global _surf, _changed, _pos
        _surf.fill((255, 255, 255))
        _pos = (0, 0)
        _changed = True
    
    def _fwdbackutil(v):
        global _surf, _pos, _ang, _changed
        vr = _rot(v, _convert_angle(_ang))
        new_pos = _vsum(_pos, vr)
        if _pen:
            pygame.draw.aaline(_surf, _color, _convert_pos(_pos), _convert_pos(new_pos))
            _changed = True
        _pos = new_pos
    
    def forward(n):
        _fwdbackutil((n, 0))
    
    def back(n):
        _fwdbackutil((-n, 0))
        
    def right(a):
        global _ang
        _ang += a
        while _ang > 360.0:
            _ang -= 360.0
    
    def left(a):
        global _ang
        _ang -= a
        while _ang < 0.0:
            _ang += 360.0
    
    def setpos(new_pos):
        global _surf, _pos, _changed    
        if _pen:
            pygame.draw.aaline(_surf, _color, _convert_pos(_pos), _convert_pos(new_pos))
            _changed = True
        _pos = new_pos
    
    def setheading(a):
        global _ang
        _ang = a
    
    def pos():
        return _pos
    
    def heading():
        return _ang
    
    def changed():
        return _changed
    
    def _convert_angle(deg):
        return (90 - deg) / 360.0 * 2 * math.pi
    
    def _convert_pos(pos):
        return (pos[0] + _center[0], _center[1] - pos[1])
    
    def _rot(v, a):
        sa = math.sin(a)
        ca = math.cos(a)
        return (v[0] * ca - v[1] * sa, v[0] * sa + v[1] * ca)
    
    def _vsum(x, y):
        return (x[0] + y[0], x[1] + y[1])
    
    if __name__ == "__main__":
    	print("usage: import myturtle")
    
    
    # turtledemo.py
    
    import pygame
    import os
    import time
    import math
    from  myturtle import *
    
    def tree(r):
        if r < 5:
            forward(r)
            back(r)
        else:
            forward(r / 3)
            left(30)
            tree(r * 2 / 3)
            right(30)
            back(r / 3)
    
            forward(r / 2)
            right(25)
            tree(r / 2)
            left(25)
            back(r / 2)
            
            forward(r * 5 / 6)
            right(25)
            tree(r / 2)
            left(25)
            back(r * 5 / 6)
    
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    
    pygame.init()
    
    mysurf = pygame.Surface((800, 600), depth=32)
    
    init_turtle(mysurf)
    
    clock = pygame.time.Clock()
    running = True
    
    try:
        screen = pygame.display.set_mode((800, 600))
        pygame.display.flip()
        mysurf.fill((255, 255, 255))
    
        g_surf = mysurf
    
        setpos((0, -300))
        pendown()
        tree(400)
        
        while running:
    
            clock.tick(100)
    
            for evt in pygame.event.get():
                if evt.type == pygame.KEYDOWN and evt.key == pygame.K_ESCAPE or \
                   evt.type == pygame.QUIT:
                    running = False
                    break
                
            screen.blit(mysurf, (0, 0))
            pygame.display.flip()
    finally:
        pygame.quit()  
    
    
    
  2. […] you read books about Logo while you were a kid you remember all that fun with turtle graphics, using loops to draw circles and recursion to generate really complicated […]

Leave a comment