Teaching Kids Python with Tracy the Turtle
Impressing kids can be a good strategy.
At CentralSquare, we regularly host an Hour of Code where middle-school students learn programming and share their creations with their classmates. Code.org has a lot of lessons available, but Tracy the Turtle allows some freedom and teaches an actual language using Python and Turtle graphics.
When we get to the part where the kids can make whatever they want, we found that giving the kids some inspiration and a starting point helped them to show off their code more. Having something to show off speaks more to the power of code than simply solving pre-made problems; like the difference between something made in art class vs. an equation solved in math class.
So we kick off the creativity by demonstrating some simple code effects which the students can remix. (The following programs were written by a colleague.)
colors=["red","orange","yellow","green","blue","purple"] speed(0) bgcolor("black") for x in range(300): color(colors[x % 6]) forward(x * .5) left(100) forward(x * .5) right(160)
colors=["red","orange","yellow","green","blue","purple"] speed(0) bgcolor("black") for x in range(1200): color(colors[x%6]) forward(x*.5) left(149)
speed(0) bgcolor('black') colors=['red','purple','blue','green','orange','yellow'] def drawCircles(size): for i in range (10): circle(size) size=size-4 color(colors[i%6]) def drawSpecial(size,repeat): for i in range (repeat): drawCircles(size) right(360/repeat) drawSpecial(100,10)
colors=["red","white","blue"] def draw_edge(s): forward(s) right(90) def draw_square(s): begin_fill() for i in range(4): draw_edge(s) end_fill() speed(0) penup() setposition(-200,200) pendown() color("black") begin_fill() draw_square(400) end_fill() penup() setposition(0,0) pendown() for x in range(100): circle(x) color(colors[x%3]) left(60)
You can do anything you like with a Python program running on your PC. But there's something that seems more legitimate about showing the code running on the actual Code.org site. Showing how the sausage is made shows the kids… you can also make your own sausage.
You can use
speed() to make things render faster, to a certain point.
# Actions run faster speed(10) # Actions run with no animation. Instant... right? Not exactly. speed(0)
But complex or dynamic drawings take too long. Using
tracer() skips rendering between a certain number of actions.
# 40 actions are performed before the next draw import turtle turtle.tracer(40, 0) # Note that nothing is drawn until 40 actions are performed. # You can manually draw at any point. turtle.update()
I made a fork of Spiral Betty by Shalanah Dawson to output a python-compatible array of coordinates which draws a spiral. This would take too long to draw normally.
import turtle # It seems almost like cheating, but there is about 300kb of data drawing the Fortnite image. # This is only part of the spiral data. Click on the images above. spiral = [[0.3,0.1,1.8],[0.5,0.2,1.81],[0.6,0.5,1.81], ...] turtle.tracer(40, 0) bgcolor((1, 252, 255)) color((5, 64, 122)) penup() for point in spiral: pensize(point) setposition(point * 0.5, point * 0.5) pendown()
Games, Keyboard Interaction, and Multiple Turtles
screen.onkey(func, "Up")runs a function on keyboard interaction.
screen.ontimer(func, intervalMs)runs a function on a fixed game loop.
turtle.Turtle()creates additional turtles which can be independently controlled.
import turtle import random turtle.tracer(1000, 0) # ultra speed screen = turtle.Screen() # we want a snake! snake = screen.turtles() snake.color("green") snake.penup() # and a fruit fruit = turtle.Turtle() fruit.color("red") fruit.shape("circle") fruit.penup() segments = 1 # how many segments is our snake, and how fast? trail =  # where have we been? def game_loop(): global segments snake.forward(20) # move forward # if we hit ourselves, game over! if (any(snake.distance(p) < 1 for p in trail)): segments = 1 snake.setposition(0, 0) bgcolor((random.random()*128+127, random.random()*128+127, random.random()*128+127)) # remember the trail trail.append((snake.pos(), snake.heading())) while (len(trail) > segments): trail.pop(0) # draw the snake snake.clear() for location in trail: snake.setposition(location) snake.setheading(location) snake.stamp() # eat the fruit if we hit it if (snake.distance(fruit.pos()) < 20): fruit.setposition(random.randint(-9, 9) * 20, random.randint(-9, 9) * 20) segments += 2 turtle.update() screen.ontimer(game_loop, 1000 / (segments / 10 + 5)) # controls def up(): snake.setheading(90) def right(): snake.setheading(0) def down(): snake.setheading(270) def left(): snake.setheading(180) screen.onkey(up, "Up") screen.onkey(right, "Right") screen.onkey(down, "Down") screen.onkey(left, "Left") screen.listen() game_loop()