Index de l'article

 

Bouger un pion est une action de jeu. Pour exécuter réellement cette action de jeu, il faut appeler les méthodes de ContainerElement, par exemple addElement() ou moveElement(). La partie contrôle ayant accès au modèle, le développeur peut très bien appeler lui-même ces méthodes. Cependant, ce n'est pas la façon de procéder dans boardifier-console.

La procédure consiste à :

  • représenter l'action de jeu par une instance d'un des sous-classes de GameAction.

ATTENTION :  vu que les classes d'action & animation sont exactement les mêmes dans boardifier-console et son grand frère boardifier, il existe 2 constructeurs possibles dans les classes d'action, dont un qui prend en paramètre un nom d'animation. En mode console, il va de soi qu'il n'y a pas d'animation possible donc il faut uniquement utiliser le constructeur sans animation.

  • insérer cette action dans un objet ActionList.
  • créer une instance d'ActionPlayer qui va "jouer" la suite d'actions de l'ActionList.

En fait, l'ActionPlayer va appeler des méthodes précises des objets GameAction, qui elles-mêmes vont appeler les méthodes pour modifier le modèle (par ex, moveElement()).

 

Le problème de cette procédure est qu'elle nécessite de créer soi-même les actions nécessaires et l'ActionList. Mais pour que le résultat de ces actions soit correct, il faut respecter des contraintes imposées par boardifier-console. Par exemple, il est impossible de bouger directement un pion d'un conteneur à un autre. Il faut d'abord l'enlever du conteneur source pour ensuite l'ajouter au conteneur destination.

Pour éviter au programmeur de gérer ces contraintes, boardifier-console propose une classe ActionFactory, qui permet de générer directement des instances d'ActionList pour les 4 opérations courantes dans un jeu. Cette classe contient ainsi les méthodes :

  • generatePutInContainer() : pour créer une ActionList permettant de déplacer un élément d'un conteneur à un autre.
  • generateMoveWithinContainer() : pour créer une ActionList permettant de déplacer un élément d'une case à une autre dans un même conteneur.
  • generateRemoveFromContainer() : pour créer une ActionList permettant d'enlever un élément d'un conteneur.
  • generateRemoveFromStage() : pour créer une ActionList permettant d'enlever un élément du stage.

A noter que la classe ActionList contient une méthode addAll() afin de concaténer deux ActionList, si nécessaire. C'est la cas par exemple dans les Dames, lorsqu'un pion prend un autre pion : il faut générer une ActionList pour le déplacement du pion et la concaténer avec une ActionList pour enlever le pion pris du stage.

L'avantage d'utiliser ces méthodes est encore plus marquant avec la version graphique de boardifier quand on utilise des animations pour représenter les déplacements des éléments. Dans ce cas, il faut calculer la position de destination des éléments et ces méthodes le font automatiquement.

 

Cette façon de procéder peut paraître alambiquée mais en pratique, elle évite beaucoup de copier/coller de code et propose une façon universelle d'exécuter des actions de jeu, quel que soit le jeu et que le joueur soit humain ou ordinateur.

Malgré l'existence de ActionFactory, voici quelques explications sur les classes d'action, au cas où vous décidiez d'en créer de nouvelles.


La super classe (dans le modèle) représentant les actions est GameAction mais ce sont ses sous-classes qui sont réellement utilisables. Dans chaque sous-classe on retrouve 2 méthodes essentielles :

  • start() : contient le code qui va modifier le modèle,
  • createAnimation() : permet de créer un objet Animation qui va contenir les pas d'animation nécessaires pour représenter visuellement l'action de jeu. Cette méthode n'est utile que pour la version graphique de boardifier

boardifier-console et boardifier ne proposent que des d'actions centrées sur les jeux de plateaux à pion+dés. Il y a donc :

  • PutInContainerAction : pour représenter le fait de bouger un élément non affecté à un conteneur vers une case d'un conteneur.
  • RemoveFromContainerAction : pour représenter le fait d'enlever un élément d'un conteneur.
  • MoveWithinContainerAction : pour représenter le fait de bouger un élément dans un conteneur d'une case à une autre (dans le même conteneur).
  • RemoveFromStageAction : pour représenter le fait qu'un élément soit "sorti" de la partie. Aucune animation n'est possible : l'élément devient invisible et il est positionné en dehors de la scène.
  • DrawDiceAction : pour représenter un jet de dés (donc ne fonctionne qu'avec les élément de type "dice"). 

Si vous voulez créer d'autres types d'action, il faudra donc écrire une sous-classe de GameAction qui définit les 2 méthodes mentionnées.


Un objet Action n'est jamais directement utilisé par le développeur. Comme mentionné ci-dessus, une Action doit être mise dans une ActionList qui est ensuite utilisée par un ActionPlayer pour exécuter réellement les actions de jeu.

La classe ActionList est donc un simple conteneur d'objets Action. Sans trop rentrer dans les détails, la classe ActionList contient des méthodes permettant d'ajouter des Action, soit individuellement, soit en pack. Un pack n'est utile que lorsque plusieurs actions de jeu doivent avoir une animation simultanée, par exemple bouger 2 pions en même temps. Sinon, on peut se contenter d'utiliser la méthode addSingleAction().

ATTENTION : l'ordre dans lequel on ajoute les Action sera celui qui sera ensuite joué par l'ActionPlayer

ActionList contient également une méthode  setDoEndOfTurn. Si cet attribut vaut true, l'ActionPlayer qui joue l'ActionList donnera l'ordre à la partie contrôle de déclencher le passage au joueur suivant une fois que toutes les actions auront été jouées.


La classe ActionPlayer et sa méthode playActions() permet de "jouer" les actions d'une ActionList. Le comportement central de playActions() est :

  • pour chaque Action de l'ActionList devant se faire avant l'animation :
    • appelle la méthode start() de l'Action (ce qui va modifier le modèle).
  • pour chaque Action de l'ActionList :
    • récupère l'animation,
    • lance l'animation,
    • attend la fin de l'animation.
  • pour chaque Action de l'ActionList devant se faire après l'animation:
    • appelle la méthode start() de l'Action (ce qui va modifier le modèle).

 Remarque : dans le framework boardifier, la classe ActionPlayer n'est pas implémentée tout à fait de la même façon, mais s'utilise à l'identique.