2.11 OBJETS TORTUES

 

 

INTRODUCTION

 

Dans la nature, une tortue est un individu ayant sa propre identité spécifique. Lors d'une exposition au zoo, on pourrait donner à chaque tortue son propre nom, par exemple, Pepe ou Maya. Cependant, les tortues ont également des caractéristiques communes: elles sont des reptiles appartenant à la classe animale des tortues. Cette notion de classes et d’individus a eu tant de succès qu’elle a été introduite en informatique comme une notion fondamentale, appelée programmation orientée objets (POO). Il vous sera facile d'apprendre les principes fondamentaux de la programmation orientée objet à l'aide des graphiques de tortue.

CONCEPTS DE PROGRAMMATION: Classe, objet, programmation orientée objets, constructeur, clones.

 

 

CRÉER UN OBJET TORTUE

 

La tortue était jusqu’à présent utilisée comme un objet anonyme auquel ne se référait aucune variable. Pour utiliser plusieurs tortues en même temps, il faut par contre donner à chaque tortue une identité propre en la nommant et en s’y référant à l’aide d’une variable.

L’instruction maya = Turtle() crée une nouvelle tortue nommée maya.
L’instruction pepe = Turtle()crée une nouvelle tortue nommée pepe.

Vous pouvez contrôler ces tortues nommées à l’aide des commandes que vous connaissez déjà, mais il faut toujours préciser explicitement la tortue à laquelle on s’adresse. Pour ce faire, on écrit le nom de la tortue cible tout d'abord, suivi d’un point et enfin la commande, par exemple maya.forward(100).

Dans l’exemple suivant, maya dessine une échelle. Il n’est pas nécessaire d’écrire la ligne makeTurtle() plus puisque chaque tortue est crée ensuite à la main.

 


from gturtle import *

maya = Turtle()
maya.setColor("red")
maya.setPenColor("green")
maya.setPos(0, -200)

repeat 7:
    repeat 4:
        maya.forward(50)
        maya.right(90)
    maya.forward(50)
Sélectionner tout le code (Ctrl+C pour copier, Ctrl+V pour coller)

 

 

MEMENTO

 

Les objets similaires sont groupés par classes. Les objets d’une certaine classe sont fabriqués (on dit aussi instanciés) en utilisant le nom de la classe suivi de parenthèses. On parle alors du constructeur de la classe.

Dans la suite, nous appellerons les fonctions rattachées à une certaine classe de méthodes.

 

 

CRÉER DAVANTAGE DE TORTUES

 

Nous savons maintenant qu’il est possible d’utiliser plusieurs tortues dans le même programme  comme précédemment décrit. Pour créer maya et pepe, il faut simplement
maya = Turtle() et pepe = Turtle()

Ces deux tortues apparaissent cependant chacune dans une fenêtre séparée. Pour qu’elles apparaissent dans la même fenêtre, il faut d’abord leur créer un enclos commun en tant qu’objet de la classe TurtleFrame:
tf = TurtleFrame()
Cet objet doit ensuite être transmis au constructeur de la classe Turtle lors de la création des tortues. Dans le programme suivant, maya construit la même échelle que dans le programme précédent mais pepe construit une échelle noire horizontale.

 
from gturtle import *

tf = TurtleFrame()

maya = Turtle(tf)
maya.setColor("red")
maya.setPenColor("red")
maya.setPos(0, -200)

pepe = Turtle(tf)
pepe.setColor("black")
pepe.setPenColor("black")
pepe.setPos(200, 0)
pepe.left(90)

repeat 7:
    repeat 4:
        maya.forward(50)
        maya.right(90)
        pepe.forward(50)
        pepe.left(90)
    maya.forward(50)    
    pepe.forward(50)
Sélectionner tout le code (Ctrl+C pour copier, Ctrl+V pour coller)

 

 

MEMENTO

 

Pour placer plusieurs tortues dans la même fenêtre, il faut d’abord créer une instance de la classe TurtleFrame et passer cette dernière aux constructeurs de tortues. Lorsque deux tortues se trouvent au même point, il n’y a pas de collision car elles se superposent dans l’ordre de création. La dernière arrivée se trouve donc toujours au-dessus des précédentes.

 

 

DES PARAMÈTRES POUR LA TORTUE

 

Les objets tortues peuvent également être passés en paramètre lors des appels de fonctions. Puisque le même code est utilisé pour dessiner les échelles quelle quoi soit la tortue, il est indiqué de définir la fonction step() où t est le paramètre formel qui permet de spécifier la tortue qui devra obéir aux instructions dessinant une marche de l’échelle.  Ensuite, on appelle deux fois cette fonction step(), une première fois en lui passant maya en tant que tortue à qui donner les ordres et une seconde fois en lui passant pepe.

 
from gturtle import *

def step(t):
    repeat 4:
        t.forward(50)
        t.right(90)
    t.forward(50)
    
tf = TurtleFrame()

maya = Turtle(tf, "sprites/beetle.gif")
maya.setPenColor("green")
maya.setPos(0, -150)
pepe = Turtle(tf, "sprites/cuteturtle.gif")
pepe.setPos(200, 0)
pepe.left(90)

repeat 7:
    step(maya)
    step(pepe)
Sélectionner tout le code (Ctrl+C pour copier, Ctrl+V pour coller)

 

 

MEMENTO

 

On peut personnaliser l’image utilisée pour chacune des tortues en spécifiant le chemin vers le fichier image lors de la création de la tortue. L’exemple précédent fait usage de deux fichiers images beetle.gif et cuteturtle.gif qui se trouvent dans la distribution de TigerJython.

 

 

PROBLÈME DES SOURIS AVEC DES CLONES DE TORTUES

 

Dans le fameux problème des souris [plus... Les trajectoires des souris sont des spirales logarithmiques dont le pôle est le centre du polygone d’après le mathématicien Brocard], n souris sont placées initialement aux sommets d’un polygone régulier de n côtés et se poursuivent les unes les autres à vitesse constante. La position des souris est fixée à intervalles de temps réguliers et chacune est alors tournée pour pointer la position de la souris qu’elle pourchasse. Une fois qu’elles ont toutes été orientées, elles avancent toutes d’une petite distance fixée.

On peut facilement résoudre ce problème par simulation en dessinant d’abord le polygone régulier à l’aide de la tortue globale puis en plaçant une nouvelle tortue à chaque sommet du polygone par clonage. Dans l’exemple suivant, on a posé n = 4, ce qui correspond à un carré et placé les tortues nommées t1, t2, t3 et t4 au sommets du polygone avec la fonction clone(). Un clone est un nouvel objet avec des propriétés identiques à l’objet cloné.

Ensuite, à l’intérieur d’une boucle, on ajuste leur position avec setHeading() et on les fait avancer d’un petit pas de cinq. La figure est particulièrement intéressante si l’on dessine les lignes « de visée » de chaque souris.

Le plus simple pour réaliser ces lignes est de définir une fonction drawLine(a, b), qui fait aller la souris se trouvant en a jusqu’à la souris b et retour à l’aide de moveTo().

 
from gturtle import *

s = 360

makeTurtle()
setPos(-s/2, -s/2)

def drawLine(a, b):
    ax = a.getX()
    ay = a.getY()
    ah = a.heading()
    a.moveTo(b.getX(), b.getY())
    a.setPos(ax, ay)
    a.heading(ah)
    
# generate Turtle clone
t1 = clone() 
t1.speed(-1)
forward(s)
right(90)
t2 = clone()
t2.speed(-1)
forward(s)
right(90)
t3 = clone()
t3.speed(-1)
forward(s)
right(90)
t4 = clone()
t4.speed(-1)
forward(s)
right(90)
hideTurtle()

while True:
    t1.setHeading(t1.towards(t2))
    t2.setHeading(t2.towards(t3))
    t3.setHeading(t3.towards(t4))
    t4.setHeading(t4.towards(t1))
   
    drawLine(t1, t2)
    drawLine(t2, t3)
    drawLine(t3, t4)
    drawLine(t4, t1)

    t1.forward(5)
    t2.forward(5)
    t3.forward(5)
    t4.forward(5)
Sélectionner tout le code (Ctrl+C pour copier, Ctrl+V pour coller)

 

 

MEMENTO

 

La fonction clone() permet de créer une nouvelle tortue à partir de la tortue globale de sorte qu’elle ait la même position, la même orientation et la même couleur. Dans le cas où la tortue originale est représentée à l’écran par une image personnalisée, le clone sera représenté par la même image. [plus... L’usage du clonage correspond à un paradigme de programmation moderne appelé programmation orientée prototype].

La fonction drawLine() peut être simplifiée en sauvegardant la position et l’orientation de la tortue avec pushState() et en les restaurant avec popState():

def drawLine(a, b):
    a.pushState()
    a.moveTo(b.getX(), b.getY())
    a.popState()

On peut déterminer analytiquement les courbes des trajectoires engendrées (Voir cet article).

 

 

EXERCICES

 

1.


Trois tortues doivent dessiner des étoiles à cinq branches simultanément. Chacune doit tracer un segment à tour de rôle. Elles doivent être de couleur cyan (la couleur par défaut), rouge et verte respectivement. La couleur sera spécifiée dans un paramètre additionnel du constructeur.




2.


Une maman tortue verte tourne en rond à vitesse constante. Au début, la position du bébé tortue rouge est éloignée de la maman. Au fil du temps, le bébé tortue avance par petits pas en direction de sa maman.

Le bébé tortue, nommé child peut déterminer la direction pointant vers sa maman avec direction = child.towards(mother)

 

3.
 


Laura dessine des carrés non vides. Après que chaque carré est terminé, une seconde tortue saute à l’intérieur et le remplit de vert.

Utiliser une image différente pour chacune des tortues. Les images disponibles dans tigerjython.jar sont beetle.gif, beetle1.gif, beetle2.gif et spider.png. Vous pouvez également utiliser vos propres images qui doivent impérativement se trouver dans un dossier sprites situé dans le même dossier que votre script Python.

4.

Représenter le graphique du « problème des souris » pour n = 6. Chacune des six souris débute donc sa trajectoire sur l’un des sommets de l’hexagone régulier.


 

 

 

MATÉRIEL BONUS


 

CRÉER DES TORTUES PAR DES CLICS DE SOURIS

 

Le programme ci-dessous dessine, lors de chaque clic de souris, une nouvelle tortue qui va tracer une étoile à partir du point situé aux coordonnées du clic, indépendamment des autres tortues. Ce programme permet de se rendre compte de la beauté et de la puissance de la programmation orienté objets de la programmation événementielle.

Pour gérer le clic de la souris, on définit la fonction drawStar(). Pour que cette fonction soit appelée par le système en réponse aux clics de la souris, il faut renseigner le paramètre mouseHitdu constructeur de TurtleFrame avec le nom du gestionnaire d’événements drawStar().

 
from gturtle import *

def drawStar(x, y):
    t = Turtle(tf)
    t.setPos(x, y)
    t.fillToPoint(x, y)
    for i in range(6):
        t.forward(40)
        t.right(140)
        t.forward(40)
        t.left(80)

tf = TurtleFrame(mouseHit = drawStar)
Ctrl+C pour copier, Ctrl+V pour coller (Ctrl+C pour copier, Ctrl+V pour coller)

 

 

MEMENTO

 

Les objets qui ont les mêmes fonctionnalités et des propriétés similaires sont définis comme des classes dans le paradigme de la programmation orientée objets (OOP = Object Oriented Programming). Pour créer des objets particuliers, on utilise le constructeur (Instanzen).

Pour traiter un clic de la souris, il faut écrire une fonction nommée de manière arbitraire mais pertinente qui comprend comme paramètres les coordonnées x  et y du clic. Il faut ensuite enregistrer ce gestionnaire d’événements auprès du système en passant le nom de la fonction (gestionnaire d’événements) comme paramètre au constructeur de la classe TurtleFrame.