Exkursion mit interaktiver Schildkröte

Hier wird die Turtle noch interaktiver! #

Der erste Befehl #

Wäre es nicht schön, wenn unsere Turtle auch auf Tastendruck reagieren würde, und du nicht jeden Befehl mühsam eintippen müsstest?

Das lässt sich machen! Das Python-Modul turtle beruht selbst auf dem tkinter-Modul, also der Standard-Python-Grafikanbindung. Das Fenster mit der Zeichenfläche, auf der die Turtle zu sehen ist, kann hier Tastendrücke und Maus-Aktionen verarbeiten. Programmierer_innen stellen sich vor, dass das Fenster auf solche Ereignisse hört, und sprechen deshalb von listenern (übersetzt etwa »Zuhöreren«).

Um also eine Turtle-Steuerung zu bekommen, benötigen wir eine eigene Variable für die Zeichenfläche – diese wird dann auf Tastaturbefehle »hören«, die du ihr gibst.

Im Code sieht das so aus:

import turtle

zeichenfläche = turtle.Screen()

Wenn du diese beiden Zeilen in eine Datei schreibst und sie startest, wird sich schon ein Fenster öffnen. Erster Schritt erledigt!

Als nächstes erzeugen wir eine Turtle. Da du die Zeichenfläche bereits hast, können wir eine Turtle verwenden, die keine eigene Zeichenfläche hat. Eine solche heißt RawTurtle. Beim Erstellen übergeben wir dieser Turtle unsere Zeichenfläche. Außerdem wollen wir gleich eine richtige Schildkröte haben…

import turtle

zeichenfläche = turtle.Screen()
turti = turtle.RawTurtle(zeichenfläche)
turti.shape('turtle')

Um die Turtle nun auf Tastendrücke reagieren zu lassen, brauchst du eine Funktion. Als kleines Beispiel ergänzen wir den Code um eine Funktion, die ein Dreieck zeichnet:

def dreieck():
    for i in range(3):
        turti.forward(100)
        turti.left(120)

Die Funktion allein macht noch nichts. Doch wir können sie nun als Ziel für einen listener der Zeichenfläche angeben. Dabei müssen wir auch die Taste angeben. Das sieht dann zusammen so aus:

import turtle

zeichenfläche = turtle.Screen()
turti = turtle.RawTurtle(zeichenfläche)
turti.shape('turtle')

def dreieck():
    for i in range(3):
        turti.forward(100)
        turti.left(120)

zeichenfläche.onkeypress(dreieck, 'd')

zeichenfläche.listen()
zeichenfläche.mainloop()

Die letzten beiden Zeilen sorgen dafür, dass die Zeichenfläche nun auf die eingestellten Tastaturereignisse hört, und dies auch immer wieder macht.

Sondertasten #

Nicht schlecht, oder? Damit du die Turtle nun richtig steuern kannst, schreiben wir vier kleine Funktionen, die jeweils nur eine einzige Sache erledigen. Füge diese vier Funktionen der Datei hinzu, genau unter der Zeile turti.shape('turtle') (die Werte für Pixel und Winkel kannst du auch deinen eigenen Vorstellungen anpassen):

def vorwärts():
    turti.forward(5)

def rückwärts():
    turti.back(5)

def links():
    turti.left(10)

def rechts():
    turti.right(10)

Nun brauchen wir für jede Funktion, die wir aufrufen möchten, einen Listener und eine Taste. Die Sondertasten mit den Pfeilen lassen sich mit 'Up', 'Down', 'Left' und 'Right' übergeben. Füge also diese Zeilen nach den Funktionsdefinitionen in die Datei ein:

zeichenfläche.onkeypress(vorwärts, 'Up')
zeichenfläche.onkeypress(rückwärts, 'Down')
zeichenfläche.onkeypress(links, 'Left')
zeichenfläche.onkeypress(rechts, 'Right')

Lass das Programm laufen, und steure die Turtle mit den Pfeiltasten über die Zeichenfläche. Gut, oder? Jetzt lassen sich coole One-Line-Bilder im Picasso-Stil zeichnen…

Nur eine Linie…

Die Turtle befragen #

Damit wir auch Bilder malen können mit mehr als einer Linie, wäre eine Taste gut, mit der du den Stift heben und senken könntest. Zwar ließe sich das einfach mit zwei Tasten machen, doch ein Umschalter wäre doch wirklich besser…

Dazu musst du wissen, in welchem Zustand die Turtle gerade ist. Zum Glück kann die Turtle dir Auskunft geben, und zwar mit der Methode isdown(). Wenn du help(turtle.isdown) in der Konsole eingibst, solltest du folgende Auskunft bekommen:

>>> help(turtle.isdown)
Help on function isdown in module turtle:

isdown()
    Return True if pen is down, False if it's up.
    
    No argument.
    
    Example:
    >>> penup()
    >>> isdown()
    False
    >>> pendown()
    >>> isdown()
    True

Ist der Stift also gerade zum Zeichnen unten, gibt isdown() True zurück, und andernfalls False. Das ist sehr praktisch, denn damit kannst du eine einfache Fallunterscheidung schreiben, die je nach Zustand umschaltet. Schreibe diese Funktion nach der rechts-Funktion auf:

def stift_umschalten():
    if turti.isdown():
        turti.penup()
    else:
        turti.pendown()

Fehlt nur noch diese Zeile, um die Funktion mit der Taste p zu verbinden:

zeichenfläche.onkeypress(stift_umschalten, 'p')

Jetzt solltest du alles mögliche zeichnen können, z.B. auch einen Fisch, wie Seymour Papert ihn mit seiner Turtle gezeichnet hat:

Eine Schildkröte und ihr Fisch

Hier noch der komplette Code unserer interaktiven Turtle:

import turtle

zeichenfläche = turtle.Screen()
turti = turtle.RawTurtle(zeichenfläche)
turti.shape('turtle')

def vorwärts():
    turti.forward(5)

def rückwärts():
    turti.back(5)

def links():
    turti.left(10)

def rechts():
    turti.right(10)

def stift_umschalten():
    if turti.isdown():
        turti.penup()
    else:
        turti.pendown()

def dreieck():
    for i in range(3):
        turti.forward(100)
        turti.left(120)

zeichenfläche.onkeypress(vorwärts, 'Up')
zeichenfläche.onkeypress(rückwärts, 'Down')
zeichenfläche.onkeypress(links, 'Left')
zeichenfläche.onkeypress(rechts, 'Right')
zeichenfläche.onkeypress(stift_umschalten, 'p')
zeichenfläche.onkeypress(dreieck, 'd')

zeichenfläche.listen()
zeichenfläche.mainloop()

Übung: #

Erweitere die interaktive Turtle um was du möchtest. Ideen gefällig?

  • eine Taste, die zwischen schwarz und blau als Zeichenfarbe umschaltet.
  • eine Tast, die die nächste Farbe aus einer Liste von Farben auswählt.
  • eine Taste, die einen Kreis zeichnet
  • eine Taste, die die Form (shape) der Turtle verändert.
  • eine Taste, die den Umriss der Turtle auf die Zeichenfläche stempelt.
  • und was dir sonst noch so einfällt… viel Vergnügen dabei!

Zurück Weiter