TigerJython xx
für Gymnasien

9a.Tastatursteuerung


Der Benutzer kann den Programmablauf durch Drücken von Tastaturtasten beeinflussen. Im GPanel können Tastatur-Betätigungen entweder mit der Abfragefunktion getKeyCodeWait() oder ähnlich wie bei den Maus-Events mit Hilfe von Callbackfunktionen erfasst werden. Diese werden nicht vom Programm aufgerufen, sondern vom System.

Beispiel 1: Mit Tastaturtasten r, b, g die Farbe des Kreises ändern
Jede Tastaturtaste hat einen nummerischen Code. Der numerische Code der Taste r ist 82, der Taste b 66 und der Taste g 71. Mit dem Befehl getKeyCodeWait() wird das Programm angehalten, bis eine Taste gedrückt wird. Dann liefert die Funktion den Tastaturcode der Taste zurück. Mit einem einfachen Testprogramm kann man den Code selbst herausfinden.

from gpanel import *
makeGPanel()
while True:
    key = getKeyCodeWait()
    print(key)
  

Die Tastaturcodes kann man auch im Internet finden (z.B. Key Code Table).

Im Beispiel 1 verwendet man die Tasten r (Code 82), b (Code 66) und g (Code 71).

#Gp 9-2.py

from gpanel import *

makeGPanel(-10, 10, -10, 10)

text(-9, -9, "Press the key r, b or g.")

while True:
    key = getKeyCodeWait()
    print(key)
    if key == 82:
        setColor("red")
    elif key == 66:
        setColor("blue")
    elif key == 71:
        setColor("green")    
    fillCircle(3)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

getKeyCodeWait() : wartet, bis eine Taste gedrückt wird und gibt den Tastaturcode zurück

print(key) : zeigt den Tastaturcode der gedrückten Taste unten im TigerJython-Fenster an

 

Beispiel 2: Zeichnen mit den Cursortaste UP, DOWN, LEFT und RIGHT

#Gp 9-2a.py

from gpanel import *

makeGPanel(-10, 10, -10, 10)

text(-9, -9, "Press the cursor keys!")
x = y = 0

while True:
    key = getKeyCodeWait()
    if key == 38:
        y += 1 
    elif key == 40:
        y -= 1
    elif key == 37:
        x -= 1
    elif key == 39:
        x += 1      
    draw(x, y)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

key = getKeyCodeWait() : speichert den Tastaturcode der gedrückten Taste in der Variablen key

if key == 38 : wenn die Cursortaste UP gedrückt wurde, wird die y-Koordinate um 1 kleiner

 

Beispiel 3: Drücken der Cursortasten mit einer Callbackfunktion erfassen

Die Callbackfunktion onKeyPressed(key) liefert den numerischen Code der gedrückten Taste. Bei den Cursortasten sind es die Codes 37, 38, 39 und 40 und beschreibt, was geschehen soll, wenn eine der Tasten gedrückt wird. An der neuen Position wird jeweils ein rot gefüllter Kreis mit einem schwarzen Rand gezeichnet. Da der Wert der Variablen x und y in der Funktion onKeyPressed(key) geändert wird, müssen sie als global deklariert werden. Die Callbackfunktion wird beim Erzeugen makeGPanel() mit keyPressed = onKeyPressed registriert.

Die Callbackfunktion muss beim Erzeugen des GPanels registriert werden.

#Gp 9-2b.py

from gpanel import *

def drawCircle():
    setColor("red")
    fillCircle(4)
    setColor("black")
    circle(4)
    move(x, y)
    
def onKeyPressed(key):
    global x, y
    if key == 38:
        y += 2 
    elif key == 40:
        y -= 2
    elif key == 37:
        x -= 2
    elif key == 39:
        x += 2      
    drawCircle()

makeGPanel(-100, 100, -100, 100, keyPressed = onKeyPressed)
text(-95, -95, "Press the cursor keys!")
x = 0
y = 0
► In Zwischenablage kopieren
 

 

Erklärungen zum Programmcode:

def onKeyPressed(key) : Callbackfunktion, legt fest was geschehen soll, wenn eine Taste gedrückt wird
global x, y : Variablen x, y ändern ihr Wert in der Funktion onKeyPressed(key). Müssen deshalb als global deklariert werden
makeGPanel(keyPressed = onKeyPressed) : registriert die Callbackfunktion onKeyPressed (teilt dem System mit, wie die Callbackfunktion heisst)

 

Beispiel 4: Nichtblockierende Tastaturabfrage

Bei den Computergames wird die Tastatur oft zur Steuerung des Spielablaufs verwendet. Hier kann man meistens die blockierende Funktion getKeyWait() nicht verwenden, da sonst das Game anhalten würde. Da brauch man eine Funktion, die Information, ob und welche Taste gedrückt wurde liefert und dann sofort zurückkehrt. Wenn eine Taste gedrück wurde, wird dieses Ereignis verarbeitet, sonst läuft das Spiel weiter.

Unser Beispiel ist eine erste Version eines Snake-Games. Beim ersten Drück einer der Cursortasten UD, DOWN, LEFT oder RIGHT beginnt sich der Snake zu bewegen. Mir erneutem Drücken einer dieser Tasten kann man die Richtung ändern.

Das Beispiel eignet sich gut für eine sogenannte Zustandsprogrammierung. Mit Drücken der ersten Cursortaste wird der Snake in einen Zustand versetzt und bleibt in diesem Zustand so lange, bis ihn das Drücken einer anderen Cursor Taste in einen neuen Zustand versetzt. In der Funktion setState() definieren wir die einzelnen Zustände.

In der Eventloop wird mit der Funktion kbhit() abgefragt, ob eine Taste gedrückt wurde. Wenn es der Fall ist, liefert sie True zurück und dann liefert die Funktion getkeyCode() den Tastencode der gedrückten Taste. Wenn keine Taste gedrückt wurde bleibt der Snake im alten Zustand, die Bewegungsrichtung bleibt unverändert. Mit dem Befehl delay(30) wird die Geschwindigkeit der Bewegung bestimmt. Das Programm wird jewils 50 Millisekunden angehalten. Mit delay(50) bewegt sich der Snake langsamer.

 

#Gp9-2c.py

from gpanel import *

def setState():
    global x, y
    if state =="UP":
        y += 1
    elif state == "DOWN":
        y -= 1 
    elif state == "LEFT":
        x -= 1  
    elif state == "RIGHT":
        x += 1      

makeGPanel(-60, 60, -60, 60)
text(-58, -58, "Press the cursor keys!")
x = y = 0
setColor("green")  
oldState = ""

while True:
    if kbhit():
        key = getKeyCode()
        if key == 38:
            state = "UP"          
        elif key == 40:
            state = "DOWN"
        elif key == 37:
            state = "LEFT"  
        elif key == 39:
            state = "RIGHT"
        oldState = state  
    else:
        state = oldState        
    
    setState()
    move(x, y)
    fillCircle(1)
    delay(30)    
► In Zwischenablage kopieren
 

 

Erklärungen zum Programmcode:

def setState() : Legt die neue Koordinaten, je nach Zustand fest. Da die Variablen x, y in der Funktion verändert werden, müssen Sie als global definiert werden
kbHit() : Nicht blockierende, periodische Tastaturabfrage. Liefert True, falls ein Tastendruck noch nicht mit getKey() oder getKeyCode() abgeholt wurde
getKeyCode() : gibt den Tastencode zurück
oldState = state : speichert den aktuellen Zustand.

 


Aufgaben Serie 9a

1.

Der Kreis hat zu Beginn den Radis 5. Bei jedem Drücken der Taste UP soll der Kreis vergrössert, beim Drücken der Taste DOWN verkleinert werden. Damit die Verkleinerung des Kreises sichtbar ist, muss du den vorher gezeichneten grösseren Kreis löschen (mit weissen Farbe übermalen).

 

       
2.

Zeichne eine Verkehrsampel. Mit den Tasten r, y bzw. g wird eine rote, gelbe oder grüne Lampe gezeichnet. Die übrigen zwei Lampen sind dabei im Zustand "off" und werden dunkel grau dargestellt

       
3.

Ergänze das Programm im Beispiel 4 so, dass das Spiel beendet wird, wenn der Snake den Fensterrand berührt. In der Mitte des Fensters soll dann der Text "Game Over" erscheinen.

Um einen grösseren Text anzuzeigen, definierst du zuerst den Font:
font = Font("Arial", Font.BOLD, 36)
wobei 36 die Schriftgrösse ist. Die Funktion Text zeigt den Text an:
text(x, y, "text", font, "fontColor", "backgroundColor")

 

 
4.

Du kannst das Snake-Spiel noch weiter entwickeln. Im richtigen Snake-Spiel darf der Snake die bereits gezeichnete Spur nicht kreuzen. dazu kannst du die Funktion getPixelColorStr(x, y) verwenden, diese gibt die Farbe im Punkt (x,y) diese darf natürlich nicht grün sein.