Les types existentiels (2/2)
Par asmanur, le mardi 14 juillet 2009, à 17:15 | Catégorie : | Mots-clés : types existentiels et OCaml | Source
Maintenant que l'on sait comment implémenter des types existentiels en caml, je vais vous montrer les quelques usages que l'on en fait dans le code pour notre projet pour les novendiales.
Maintenant que l'on sait comment implémenter des types existentiels en caml, je vais vous montrer les quelques usages que l'on en fait dans le code pour notre projet pour les novendiales.
State, l'état du jeu à tout instant
Dans un jeu il y a principalement trois choses à faire :
-
dessiner le monde ;
-
réagir lors de l'appui d'une touche ;
-
prendre en compte l'influence du temps.
Supposons que notre type représentant l'état du monde soit 'a, cela nous donne le type suivant :
type 'a état = {
dessiner : 'a -> dessin list;
temps : float -> 'a -> 'a;
touche_appuyée : touche -> 'a -> 'a;
}
Quelques commentaires :
-
seul
tempsettouche_appuyéesont susceptibles de modifier le
monde, dessiner s'occupe juste de représenter le monde ;
-
dessinerretourne une liste dedessin, cela permet d'avoir tout
le code de dessin complètement pur et indépendant de la bibliothèque utilisée et une fonction dessiner_dessin : dessin -> unit qui varie selon la bibliothèque utilisée. Les avantages de cette méthode seront présentés dans un article ultérieur
-
il n'est pas dit qu'on ait qu'un seul type de monde tout au long de
notre programme, notamment avec les menus ce type peut varier.
Le problème de ce type c'est qu'il ne permet pas de changer d'état. Il faut donc changer le type de retour de temps et touche_appuyée. Cependant, remplacer 'a par quelque chose du genre de
Continuer of 'a | Changement_d_état of 'a état
ne résoud pas le problème — et si on veut changer de type d'état ? L'intérêt des types existentiels arrive ici, si on a un type état_quantifié on peut écrire simplement
type 'a retour = Continuer of 'a | Changement_d_état of 'a état_quantifié
type 'a état = {
dessiner : 'a -> dessin list;
temps : float -> 'a -> 'a retour;
touche_appuyée : touche -> 'a -> 'a retour;
}
Quelques exemples d'état actuellement implémenté (en plus de celui du jeu) :
-
un état pour les transition graphique entre deux états (l'état est un flottant compris entre 0 et 1) ;
-
un état pour récupérer une touche (désignant un objet) au joueur, l'état est ici le monde (mais ça n'est pas nécéssaire)
-
un état pour sélectionner un ennemi, l'état est ici l'index du monstre sélectionné (qui varie quand l'utilisateur change de monstre).
Des effets en pagaille !
Autre utilité des types existentiels : permettre d'avoir une grande variété d'effet.
En tant que roguelike, notre jeu est en tour par tour et ainsi un effet est grosso modo une fonction qui est appelé à chaque fin de tour pour agir sur le monde d'une façon ou d'une autre. Sauf qu'un effet peut maintenir un état — par exemple le nombre de tour avant qu'il disparaisse, ou plus élaboré si l'effet est moins conventionnel — et donc un type existentiel résoud ce problème.
Pour appliquer les effets, il suffit ensuite d'itérer sur les effets. En pratique ça pose quelques problèmes de récursivité car le monde dépend des effets et vice-versa or notre effet quantifié est construit via un module … Bref c'est pas la joie.