1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
| import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Arrays;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
public class BarreDeVieExample1 {
public static final long TIME = 1000; // la durée de l'animation
public static final long RATE = 15; // le temps entre deux rafraîchissements lors de l'animation
public final static int LIFE = 200; // la durée de vie initiale
public final static int BARHEIGHT = 75; // la hauteur de la barre de vie (on part sur une barre horizontale qui
// s'étend dans le composant)
public final static int SPACE = 5; // une taille de goutière pour les grilles
public final static int[] POWER = { 20, 50, 100 }; // les puissances d'attaques possibles
public static void main(String[] args) {
// on créer la fenêtre
JFrame frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// le panneau de la barre de vie
LifeBarPanel lifeBarPanel = new LifeBarPanel();
lifeBarPanel.setForeground(Color.ORANGE); // la couleur de la barre de vie
lifeBarPanel.setBorder(BorderFactory.createEmptyBorder(SPACE, SPACE, SPACE, SPACE));
// le panneau des boutons
JPanel buttonpanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = GridBagConstraints.RELATIVE;
gbc.insets = new Insets(SPACE, SPACE, SPACE, SPACE);
JButton[] buttons = new JButton[POWER.length + 1]; // un bouton pour chaque attaque plus un reset
for (int i = 0; i < POWER.length; i++) {
int power = POWER[i];
JButton button = new JButton(String.valueOf(power));
// l'action du bouton d'attaque
// - désactiver les actions sur tous les boutonsn
// - lancer l'animation d'attaque (barre de vie qui baisse)
// - à la fin on réactive tous les boutons
button.addActionListener(e -> {
Arrays.stream(buttons).forEach(b -> b.setEnabled(false));
lifeBarPanel.attack(power, () -> Arrays.stream(buttons).forEach(b -> b.setEnabled(true)));
});
buttonpanel.add(button, gbc);
buttons[i] = button;
}
// bouton de resett
JButton resetbutton = new JButton("Reset");
resetbutton.addActionListener(e -> lifeBarPanel.reset());
buttons[buttons.length - 1] = resetbutton;
buttonpanel.add(resetbutton, gbc);
// on compose la fenêtre
frame.add(buttonpanel, BorderLayout.WEST);
frame.add(lifeBarPanel);
// on affiche la fenêtre
frame.setSize(600, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static class LifeBarPanel extends JPanel {
private int life; // la vie actuelle
private int currentlife; // la dernière vie avant début d'animation (pour gérer un effet)
public LifeBarPanel() {
reset();
}
/**
* RAZ le montant de vie
*/
public void reset() {
life = LIFE;
currentlife = life;
repaint();
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (life>0 && currentlife>0 ) {
Insets insets = getInsets(); // pour éliminer les bordures
int y = (getHeight() - insets.top - insets.bottom - BARHEIGHT) / 2; // centrage vertical
int width = getWidth() - insets.left - insets.right; // largeur totale dispo
// la valeur courrante au début de l'anim pour faire un petit effet
int currentrectwidth = (int) (((double) currentlife / LIFE) * width);
g.setColor(getCurrentBarColor());
g.fillRect(0, y, currentrectwidth, BARHEIGHT);
// la valeur de la vie = la longueur de la barre remise à l'échelle du composant
int rectwidth = (int) (((double) life / LIFE) * width);
g.setColor(getBarColor());
g.fillRect(0, y, rectwidth, BARHEIGHT);
// une bordure pour la barre
g.setColor(getBarBorderColor());
g.drawRect(0, y, rectwidth, BARHEIGHT);
}
}
private Color getBarColor() {
return getForeground();
}
private Color getBarBorderColor() {
return Color.BLACK;
}
private Color getCurrentBarColor() {
return getForeground().darker();
}
public void attack(int power, Runnable done) {
// ici thread EDT
int oldlife = life;
// on calcule la nouvelle vie
int newlife = Math.max(0, life - power);
// si pas de changement, on arrête là
if (newlife == oldlife) {
return;
}
// la différence entre avant et après
int diff = oldlife - newlife;
// la vie au début de l'animation
// création du worker
SwingWorker<Integer, Integer> worker = new SwingWorker<Integer, Integer>() {
@Override
protected Integer doInBackground() throws Exception {
// ici thread pas EDT
// le temps au début de l'anim
long starttime = System.currentTimeMillis();
// le temps passé depuis le début
long timeelapsed;
// tant qu'on a pas atteint le temps d'anim
while ((timeelapsed = System.currentTimeMillis() - starttime) < TIME) {
// on calcule la taille de la vie au moment qu'on est
publish(oldlife - (int) ((diff * timeelapsed) / TIME));
// on dort ce qu'il faut
Thread.sleep(RATE);
}
// à la fin, le résultat final
return newlife;
}
@Override
protected void process(List<Integer> chunks) {
// ici thread EDT
// ici on traite et affiche les résultats
life = chunks.get(chunks.size() - 1); // on ne prend pas les résultats intermédiaire
repaint(); // on redessin
}
@Override
protected void done() {
// ici thread pas EDT
life = newlife; // valeur final (on utilise ça au lieu de get, pas d'exception à traiter et on a
// le résultat final sans le calculer
currentlife = life; // on retombe sur un état stable et cohérent
repaint(); // on redessine pour que ça soit clean
done.run(); // on finalise
}
};
worker.execute(); // on exécute le timer
}
}
} |
Partager