Magic-The-Gathering-Tactics-6151

MtgDb – Fait peau neuve

Bonjour à tous,

Promis je ne suis pas mort, mais je travail sur d’autre projet en ce moment. Dernièrement j’ai entièrement refait ma base de donnée sur le jeu de carte Magic the Gathering.

  • Interface un peu plus simple
  • Possibilité d’ouvrir un compte et d’enregistrer ces Decks.
  • Plus d’éditions
  • Moteur de recherche toujours plus complet.

Je doit encore nettoyer un peu le code avant de le poussé sur github mais il le sera bientôt.

http://mtg.shionn.org

Il n’est pas encore fini, je pense qu’il manque des choses comme la gestion des limitations par format.

Slick2d, leçon 20 :: Les combats aux tour par tour (5/X)

Aujourd’hui on va voir comment ajouter un hud à notre combat par l’intermédiaire de bouton cliquable et une fenêtre de texte qui contiendra les logs du combat.

Préparation :: un bouton.

Comme pour la leçon 13 j’ai utilisé la ressource Golden UI sur OpenGameArt pour faire un bouton que voici :

tuto-slick2d-099-buttons

Code :: BattleHud

Comme pour la leçon 13 créons une classe dédiée à l’affichage du hud BattleHud.

Classe :: BattleHud
public class BattleHud { 

  public void init(GameContainer container) throws SlickException { }
  
  public void render(GameContainer container, Graphics g) { }

}

Un bouton dans Slick c’est une « zone clickable » avec une image à l’intérieur, ces zones sont représentés avec la classe MouseOverArea. On va utiliser le constructeur avec les arguments :

  • GameContainer : container du jeux
  • Image : image du bouton
  • int x, int y : coin supérieur gauche
  • ComponentListener : écouteur pour les évènements

Construisons nos boutons,  dans la méthode init() et comme d’habitude affichons les dans la méthode render(). Il y a 3 boutons qui correspondent au 3 actions possible dans notre combat.

Classe :: BattleHud
// espace entre les éléments de l'interface
private static final int SPACE = 5;
// pour le centrage du text dans les boutons
private static final int Y_PADDING = 3; 
private static final int X_PADDING = 13;

private MouseOverArea attackButton;
private MouseOverArea fleeButton;
private MouseOverArea defendButton;

public void init(GameContainer container) throws SlickException {
  Image buttonImage = new Image("hud/button.png");
  attackButton = new MouseOverArea(container, buttonImage, SPACE, container.getHeight() - (buttonImage.getHeight() + SPACE) * 3, this);
  defendButton = new MouseOverArea(container, buttonImage, SPACE, container.getHeight() - (buttonImage.getHeight() + SPACE) * 2, this);
  fleeButton = new MouseOverArea(container, buttonImage, SPACE, container.getHeight() - (buttonImage.getHeight() + SPACE) * 1, this);
}

public void render(GameContainer container, Graphics g) { 
  g.setColor(Color.black);
  attackButton.render(container, g);
  g.drawString("Attaquer", attackButton.getX() + X_PADDING, attackButton.getY() + Y_PADDING);
  defendButton.render(container, g);
  g.drawString("Defendre", defendButton.getX() + X_PADDING, defendButton.getY() + Y_PADDING);
  fleeButton.render(container, g);
  g.drawString("Fuire", fleeButton.getX() + X_PADDING, fleeButton.getY() + Y_PADDING);
}

Les calculs sont fait pour que les trois boutons soit placés l’un en dessous de l’autre dans le coin inférieur gauche. Pour que notre Hud puisse capter les évènements de notre souris il doit implémenter l’interface ComponentListener.

Classe :: BattleHud
public class BattleHud implements ComponentListener {
  // [...]

  @Override
  public void componentActivated(AbstractComponent source) {
  }
}

La méthode en argument la source, c’est à dire le bouton, qui est activé quand on clic dessus. Il faut encore compléter cette méthode en appelant notre BattleController pour activer les actions de combat qui correspondent au bouton.

Classe :: BattleHud
// [...]
private BattleController controller;

public BattleHud(BattleController controller) {
  this.controller = controller;
}
// [...]

@Override
public void componentActivated(AbstractComponent source) {
  if (source == attackButton) {
    controller.controlPressed(BattleCommand.ATTACK);
  } else if (source == defendButton) {
    controller.controlPressed(BattleCommand.DEFEND);
  } else if (source == fleeButton) {
    controller.controlPressed(BattleCommand.FLEE);
  }
}
// [...]

Il faut intégrer tous cela dans notre la boucle de combat, cela commence à devenir routinier.

Classe :: BattleGameState
// [...]
private BattleHud hud;

@Override
public void init(GameContainer container, StateBasedGame game) throws SlickException {
  // initialisation, vu dans les leçons précédentes
  BattleController controller = new BattleController(player, ennemy, game);
  provider.addListener(controller);
  this.hud = new BattleHud(controller);
  this.hud.init(container);
}

@Override
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
  // affichage, vu dans les leçons précédentes
  this.hud.render(container, g);
}
// [...]

Et voici le résultat :

tuto-slick2d-100-battle-buttons

Un log de combat

Pour la suite il vous faut importer SlickUtils dans sa version 1.3, pour utiliser ma dernière version du TextArea, qui support des polices par défaut. Ajoutons notre log à l’initialisation et au rendu :

Classe :: BattleHud
// [...]
private TextArea log;

public void init(GameContainer container) throws SlickException {
  log = new TextArea(SPACE + attackButton.getWidth() + SPACE, attackButton.getY(), container.getWidth() - attackButton.getWidth() - SPACE * 3, buttonImage.getHeight() * 3 + SPACE * 2);
  // affichage de bas en haut
  log.setBottomUp(true); 
  log.setDefaultFont(container.getDefaultFont());
}
// [...]

public void render(GameContainer container, Graphics g) { 
  // [...]
  g.drawString("Fuire", fleeButton.getX() + X_PADDING, fleeButton.getY() + Y_PADDING);
  log.render();
}
// [...]

public void addLog(String text) {
  log.addFirstText(text, VerticalAlignement.LEFT);
}
// [...]

Maintenant il faut passer notre instance du hud au contrôleur pour que celui-ci puisse écrire dans le log.

Classe :: BattleHud
  // [...]
  public BattleHud(BattleController controller) {
    this.controller = controller;
    this.controller.setHud(this);
  }
  // [...]

Et dans le contrôleur :

Classe :: BattleControllerpublic class BattleController implements InputProviderListener {
  // [...]
  private BattleHud hud;

  // [...]

  public void setHud(BattleHud hud) {
    this.hud = hud;
  }
  // [...]

Pour finir il reste à appeler la méthode addLog de notre hud depuis la classe BattleController, pour afficher les messages qu’on souhaite lors des différentes étape du combat. C’est trivial aussi je passe cette partie sous silence. Mais voici le résultat :

The video cannot be shown at the moment. Please try again later.

Pour aller plus loin

Le combat avance bien, la prochaine fois on verra comment changer la musique et comment ajouter une pause a la fin du combat avant de retourner à la carte.

Ressources