deutsch     english    français     Imprimer

 

3.6 CONTRÔLE DU PROGRAMME AU CLAVIER

 

 

INTRODUCTION

 

Les programmes gagnent en interactivité lorsque l’utilisateur peut contrôler son exécution avec les touches du clavier. Bien que les frappes sur les touches soient en fait des événements survenant indépendamment de l’exécution du programme, elles peuvent être capturées dans le GPanel à l’aide de fonctions de requêtes..

CONCEPTS DE PROGRAMMATION: Type booléen, État de jeu (game state), animation

 

 

CONTRÔLE DU CLAVIER

 

La commande getKeyCodeWait() suspend l’exécution du programme jusqu’à ce qu’une touche du clavier soit actionnée et retourne le code associé à la touche pressée. À l’exception de certaines touches spéciales (Ctrl, Alt, …), chaque touche dispose de son propre code numérique.

On peut déterminer le code associé à chaque touche en utilisant un simple programme de test. Les codes numériques sont écrits dans la fenêtre de la console.
from gpanel import *
makeGPanel(0, 10, 0, 10)

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


Sélectionner le code (Ctrl+C pour copier, Ctrl+V pour coller)

 

 

MEMENTO

 

On peut utiliser la fonction getKeyCodeWait() pour contrôler les saisies clavier. Celle-ci attend qu’une touche soit pressée et retourne le code associé.

Il faut se rappeler que la fenêtre GPanel doit être active pour pouvoir capturer les événements du clavier. En d’autres termes, la fenêtre du GPanel doit avec le focus. Si la fenêtre perd le focus, il est nécessaire de cliquer quelque part dans son intérieur pour la réactiver. Seule la fenêtre active peut recevoir les événements du clavier.

 

 

CONTRÔLER LES FIGURES

 

Il est possible de déplacer des objets graphiques à l’aide du clavier. Dans l’exemple ci-contre, le programme contrôle le disque vert à l’aide des touches directionnelles du clavier pour le déplacer vers le haut, le bas, la droite ou la gauche. Le programme attend une pression de touche à l’intérieur de la boucle d'événements

et gère le code de touche ainsi obtenu dans une structure if-else imbriquée dans la boucle.

Du fait que l’affichage du disque est utilisé à plusieurs reprises, il est indiqué d’encapsuler ce code dans une fonction dédiée drawCircle() qui peut être réutilisée à de nombreuses reprises, comme l’exige le paradigme de la programmation structurée (Structured Programming en anglais).
 
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()        
Sélectionner le code (Ctrl+C pour copier, Ctrl+V pour coller)

 

 

MEMENTO

 

Pour améliorer la lisibilité du programme, on peut introduire des constants pour représenter les codes des touches directionnelles. Pour qu’elles soient facilement distinguables des variables, on adopte en Python la convention de le les écrire en lettres capitales.

 

 

INTERROGER LE CLAVIER DE MANIÈRE NON BLOCANTE

 

Comme vous le savez certainement, le clavier est souvent utilisé pour contrôler le game play dans les jeux vidéo sur ordinateurs. Dans ce cas, il n’est pas possible de recourir à la fonction bloquante getKeyCodeWait() car elle mettrait le jeu en pause en attendant la pression d’une touche au clavier. Il faut au contraire utiliser une fonction qui fournit le code de la touche actionnée mais qui retourne directement, sans attendre la pression de la touche.

Dans le cas où une touche a effectivement été pressée, on gère l’événement associé et dans le cas contraire, on continue le jeu normalement. 
 

On veut augmenter ou diminuer la vitesse de la balle à l’aide des touches F pour « faster » respectivement S pour « slower », mais seulement jusqu’à une vitesse limite. Fixez à nouveau votre attention sur la boucle d’événements où toutes les choses intéressantes se produisent. Cette fonction interroge périodiquement le système pour savoir si une touche a été activée ou non. Si tel est le cas, la fonction kbhit() retourne True et l’on peut obtenir le code de la touche avec la fonction getKeyCode().

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)
Sélectionner le code (Ctrl+C pour copier, Ctrl+V pour coller)

 

 

MEMENTO

 

Puisque l’on désire créer une animation, il est nécessaire d’utiliser un animation timer pour que le parcours de la boucle soit le plus régulier possible. Le prochain état du jeu est créé dans la boucle et est affiché a posteriori dans la fenêtre avec repaint().

kbhit() retourne une valeur de vérité, à savoir une valeur booléenne. Si une touche a été enfoncée depuis le dernier appel, la fonction retourne True et elle renvoie False dans tous les autres cas.
Dans le but de déplacer la balle vers la droite (forward), sa coordonnée x doit augmenter de v (la vitesse) lors de chaque passage dans la boucle d’événements. Pour bouger vers la gauche, la coordonnée x doit diminuer. On résume un mouvement avant ou arrière dans un état de jeu que l’on stocke dans la variable isAhead.

En Python, on peut ajouter un mot à un second mot à l’aide de l’opérateur +. Ainsi, "Tiger" + "Jython" devient le mot  "TigerJython". Par contre, si l’on veut rajouter un nombre à une chaine de caractères, il est nécessaire de convertir le nombre en une chaine de caractères à l’aide de la fonction str().

 

 

EXERCICES

 

1.

En utilisant les touches UP, DOWN, LEFT et RIGHT, dessiner un serpent à l’aide de petits disques rouges très serrés.

 
2.

Étendre le programme de l’exercice précédent pour qu’il permette de modifier la couleur des prochains disques : la touche R sélectionne la couleur rouge « red », G la couleur verte « green » et B la couleur bleu « blue ».


3.

Étendre le programme du ballon se déplaçant de droite à gauche présenté plus haut pour que les touches directionnelles HAUT et BAS déplacent la balle vers le haut et vers le bas.