3.6 TASTATURSTEUERUNG

 

 

EINFÜHRUNG

 

Programme erhalten eine zusätzliche Interaktivität, wenn der Benutzer den Programmablauf durch Drücken von Tastaturtasten steuern kann. Obschon Tastaturbetätigungen eigentlich Ereignisse sind, die jederzeit unabhängig vom Programmablauf auftreten, werden sie im GPanel durch Abfragefunktionen erfasst.

PROGRAMMIERKONZEPTE: Boolescher Datentyp, Spielzustand, Animation

 

 

TASTATURSTEUERUNG

 

Mit dem Befehl getKeyCodeWait() wird das Programm angehalten, bis du eine Taste drückst. Dann liefert dir die Funktion als Rückgabewert den Tastaturcode der Taste zurück. Mit Ausnahme von einigen Spezialtasten hat jede Taste auf der Tastatur einen eigenen Zahlencode.

Du kannst mit einem einfachen Testprogramm die Tastencodes selbst herausfinden. Die Zahlencodes werden im Consolenfenster ausgeschrieben.

from gpanel import *
makeGPanel(0, 10, 0, 10)

text(1, 5, "Press any key.")
while True:
    key = getKeyCodeWait()
    print(key)
 


Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

MEMO

 

Für Tastatureingaben kannst du den Befehl getKeyCodeWait() verwenden. Der Computer wartet, bis du eine Taste drückst und gibt den Tastaturcode zurück.

Beachte aber, dass das GPanel-Fenster aktiv sein muss. Man sagt auch, dass es den Fokus besiten muss. Du musst in das Fenster hineinklicken, falls es den Fokus verloren hat. Nur das momentan aktive Fenster erhält die Tastaturereignisse.

 

 

FIGUREN STEUERN

 

Mit der Tastatur kannst du Grafikobjekte bewegen. Das Programm steuert den grünen Kreis mit Cursortasten nach links, rechts, oben oder nach unten. In einer sogenannten Event-Loop wartet das Programm auf einen Tastendruck und verarbeitet den erhaltenen Tastaturcode in einer verschachtelten if-else-Struktur.

Da das Zeichnen des Kreises immer wieder verwendet wird, ist es im Sinn der Strukturierten Programmierung klar, dass du dies in einer Funktion drawCircle(), die mehrmals aufgerufen wird, ausführst.

 

 

from gpanel import *

KEY_LEFT = 37
KEY_RIGHT = 39
KEY_UP = 38
KEY_DOWN = 40

def drawCircle():
    move(x, y)
    setColor("green")
    fillCircle(5)
    setColor("black")
    circle(5)
    
makeGPanel(0, 100, 0, 100)
text("Move the circle with the arrow keys.")
x = 50
y = 50
step = 2
drawCircle()
 
while True:
    key = getKeyCodeWait()
    if key == KEY_LEFT:
        x -= step
        drawCircle()
    elif key == KEY_RIGHT:
        x += step
        drawCircle()
    elif key == KEY_UP:
        y += step
        drawCircle()
    elif key == KEY_DOWN:
        y -= step
        drawCircle()        
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

MEMO

 

Damit das Programm besser lesbar ist, kannst du für die Tastaturcodes der Cursortasten Konstanten einführen. Um sie besonders herauszuheben, sind sie sogar im Programmkopf platziert und mit Grossbuchstaben bezeichnet.

 

 

NICHTBLOCKIERENDE TASTATURABFRAGE

 

Wie dir sicher bekannt ist, wird die Tastatur bei Computergames häufig zur Steuerung des Spielablaufs verwendet. Hier kannst du natürlich die blockierende Funktion getKeyCodeWait() nicht verwenden, da sonst ja das Game anhalten würde. Du brauchst vielmehr eine Funktion, welche dir die Information liefert, ob eine Taste gedrückt wurde, aber sofort zurückkehrt.

Hast du tatsächlich eine Taste bedient, so verarbeitest du dieses Ereignis, sonst wird das Game normal weitergeführt.

 

Du willst die Geschwindigkeit eines sich hin- und her bewegenden Balls mit der Buchstabentaste 's' (für slow) verkleinern und mit 'f' (für fast) vergrössern, allerdings nur bis zu einem maximalen Wert. Dein Augenmerk musst du wieder auf die Event-Loop richten, in der alles Wesentliche passiert. Dort wird mit kbhit() periodisch abgefragt, ob eine Taste gedrückt wurde. Ist dies der Fall, liefert kbhit() True zurück und du kannst mit getKeyCode() den Tastaturcode holen.

from gpanel import *
import time

KEY_S = 83
KEY_F = 70

makeGPanel(0, 600, 0, 600)
title("Key 'f': faster, 's': slower")

enableRepaint(False)
x = 300
y = 300
v = 10
vmax = 50
isAhead = True

while True:
    startTime = time.clock()

    if kbhit():
        key = getKeyCode()
        if key == KEY_F:
            if v < vmax:
              v += 1
        elif key == KEY_S:
            if v > 0:
              v -= 1
    
    clear()
    setColor("black")
    text(10, 10, "Speed: " + str(v))
    if isAhead:
        x = x + v
    else:
        x = x - v
    move(x, y)
    setColor("red")
    fillCircle(20)
    repaint()
    if x > 600 or x < 0:
        isAhead = not isAhead
    while (time.clock() - startTime)  < 0.010:
        delay(1)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

MEMO

 

Da es sich um eine Animation handelt, müssen wir wieder einen Animationstimer verwenden, um einen möglichst periodischen Durchlauf der Event-Loop zu erhalten. In der Schleife wird der nächst folgende Spielzustand erstellt und dann mit repaint() im Bildschirmfenster angezeigt.

kbhit() liefert einen Wahrheitswert zurück, den wir auch als boolean bezeichnen. Wurde seit dem letztem Aufruf eine Taste gedrückt, so wird True zurückgegeben, sonst False.

Um den Ball nach rechts (vorwärts) zu bewegen, wird seine x-Koordinate bei jedem Durchgang der Event-Loop um  v (Mass für die Geschwindigkeit)  erhöht. Für die Bewegung nach links muss die Koordinate um v verkleinert werden. Vorwärts- bzw. Rückwärtsbewegung fassen wir als Spielzustand auf, den wir in der Variablen isAhead speichern.

In Python kannst du einem Wort ein zweites Wort mit dem + Zeichen anfügen, also beispielsweise ergibt "Hans" + "Peter" das Wort "HansPeter". Wenn du aber einem Wort eine Zahl zufügen willst, so muss du die Zahl zuerst mit der str()-Funktion konvertieren.

 

 

AUFGABEN

 

1.

Mit den Cursortasten UP, DOWN, LEFT und RIGHT sollst du eine Schlangenlinie mit kleinen roten Kreisen zeichnen, die aneinander liegen.

 
2.

Als Erweiterung definierst du folgende Tasten für die Farbwahl: Wenn du die Buchstabentaste g drückst, sollen die Kreise anschliessend grün, bei b blau und bei r wieder rot sein.


3.

Erweitere dein Programm mit dem hin-und herlaufenden Ball so, dass mit den Cursor UP- und DOWN-Tasten der Ball nach oben bzw. nach unten verschoben wird.