package hexenschach.gui.graphic;
import hexenschach.figures.Figure;
import hexenschach.gameplay.Gameplay;
import hexenschach.gui.FieldHighlightStatus;
import hexenschach.gui.graphic.animation.AnimationFunction;
import hexenschach.gui.graphic.animation.Cadencer;
import hexenschach.gui.graphic.animation.ElasticFunction;
import hexenschach.gui.graphic.animation.ExpFunction;
import hexenschach.gui.graphic.animation.LineareFunction;
import hexenschach.gui.graphic.animation.MoveAnimation;
import hexenschach.gui.graphic.animation.SmoothFunction;
import hexenschach.gui.graphic.figures.FigureLoader;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Zeichenflaeche auf die das Spielbrett gezeichnet wird
*
* @author Bjoern R. Salgert
* @date 26.04.2010
*/
public class HexenschachPanel extends SwingDrawPanel {
///region Static
public static final String[] FIELD_NAMES = new String[] {
"D1", "F1", "H1", "J1", "L1", "N1", "P1", "R1",
"C2", "E2", "G2", "I2", "K2", "M2", "O2", "Q2", "S2",
"B3", "D3", "F3", "H3", "J3", "L3", "N3", "P3", "R3", "T3",
"A4", "C4", "E4", "G4", "I4", "K4", "M4", "O4", "Q4", "S4", "U4",
"B5", "D5", "F5", "H5", "J5", "L5", "N5", "P5", "R5", "T5",
"C6", "E6", "G6", "I6", "K6", "M6", "O6", "Q6", "S6",
"D7", "F7", "H7", "J7", "L7", "N7", "P7", "R7",
"E8", "G8", "I8", "K8", "M8", "O8", "Q8",
"F9", "H9", "J9", "L9", "N9", "P9",
"G10","I10","K10","M10","O10",
"H11","J11","L11","N11"
};
public static final String[] WHITE_COLS = new String[] {
"A", "D", "G", "J", "M", "P", "S"
};
public static final String[] BROWN_COLS = new String[] {
"C", "F", "I", "L", "O", "R", "U"
};
private static final long serialVersionUID = -7298572880150160745L;
///endregion
public HexenschachPanel() {
setPreferredSize(new Dimension(462, 398));
initFields();
for (Hexagon item : fields.values()) {
getRoot().add(item);
}
this.addMouseListener(new MouseListener() {
@Override public void mouseReleased(MouseEvent e) {}
@Override public void mousePressed(MouseEvent e) {}
@Override public void mouseExited(MouseEvent e) {}
@Override public void mouseEntered(MouseEvent e) {}
@Override
public void mouseClicked(MouseEvent e) {
handleClick(e.getX(), e.getY());
}
});
initAnimations();
}
///region Privat
private Map<String, Hexagon> fields = new HashMap<String, Hexagon>();
private int offsetX = 41;
private int offsetY = 35;
private int offsetFigureX = 7;
private int offsetFigureY = 7;
public void setFieldColor(String fieldName, Color c) {
fields.get(fieldName).fillColor = c;
}
private void setFigurePosition(BoundedDrawing item, String fieldName) {
item.x = getFigurePositionX(fieldName);
item.y = getFigurePositionY(fieldName);
}
private int getFigurePositionX(String fieldName) {
return getLetterOffset(fieldName.charAt(0)) + offsetFigureX;
}
private int getFigurePositionY(String fieldName) {
return getDigitOffset(Integer.parseInt(fieldName.substring(1))) + offsetFigureY;
}
private int getLetterOffset(char letter) {
int i = ((int) letter) - ((int)'A');
int res = 0;
if (i % 2 == 1) {
res += offsetX/2;
}
res += (i/2)*offsetX;
return res;
}
private int getDigitOffset(int i) {
return (i-1)*offsetY;
}
private void initFields() {
for (String fieldName : FIELD_NAMES) {
int x = getLetterOffset(fieldName.charAt(0));
int y = getDigitOffset(Integer.parseInt(fieldName.substring(1)));
Hexagon hexa = new Hexagon(x, y);
if (Arrays.binarySearch(WHITE_COLS, fieldName.substring(0, 1))>=0) {
hexa.setFill(Color.WHITE);
}
if (Arrays.binarySearch(BROWN_COLS, fieldName.substring(0, 1))>=0) {
hexa.setFill(new Color(194, 130, 0));
}
fields.put(fieldName, hexa);
}
}
///endregion
///region Gameplay Interaktion
private void handleClick(int x, int y) {
for (String key : fields.keySet()) {
Hexagon hexa = fields.get(key);
if (hexa.contains(x, y)) {
//JOptionPane.showMessageDialog(null, key , "Mouse", 0);
if (game != null) {
game.processFieldInput(key);
}
break;
}
}
}
private Gameplay game = null;
/**
* Setzt das Gameplay an das die Klicks weitergeleitet werden,
* Ist bereits ein Gameplay gesetzt, wird das bereits gesetzte �berschrieben
*
* @param value Gameplay Instanz an die die Klicks weiter geleitet werden.
*/
public void setGameplay(Gameplay value) {
game = value;
}
///endregion
///region Highlighting
/**
* Hebt ein Feld hervor
*
* @param field Feld das hervorgehoben werden soll
* @param status Status, wie das Feld hervorgehoben werden soll
* @return True, wenn das Feld erfolgreich hervorgehoben wurde; False sonst
*/
public boolean highlightField(String field, FieldHighlightStatus status) {
switch (status) {
case NONE: /* Feld ist nicht hervorgehen */
resetFieldHighlight(field);
break;
case SELECT: /* Das Feld wurde ausgewaehlt, mit der Figur auf dem Feld soll geschlagen werden */
setFieldColor(field, Color.BLUE);
break;
case POSSIBLE: /* Die Ausgewaehlte Figur kann auf das Feld gehen */
setFieldColor(field, Color.YELLOW);
break;
case CAPTURE: /* Die Ausgewaehlte Figur kann auf das Feld gehen und dort eine Figur schalgen */
setFieldColor(field, Color.RED);
break;
}
this.repaint();
return true;
}
/**
* Entfert saemtliche Highlights von allen Feldern
*/
public void resetHighlight() {
for (String fieldName : FIELD_NAMES) {
resetFieldHighlight(fieldName);
}
this.repaint();
}
private void resetFieldHighlight(String fieldName) {
Hexagon hexa = fields.get(fieldName);
if (Arrays.binarySearch(WHITE_COLS, fieldName.substring(0, 1))>=0) {
hexa.setFill(Color.WHITE);
} else if (Arrays.binarySearch(BROWN_COLS, fieldName.substring(0, 1))>=0) {
hexa.setFill(new Color(194, 130, 0));
} else {
hexa.setFill(Color.BLACK);
}
}
///endregion
///region Figurensetzen
Map<String, Image> figures = new HashMap<String, Image>();
/**
* Bewegt eine Figur vom Feld $from zum Feld $to
*
* Sonderfaelle:
* $from oder $to ist ungueltiges Feld: Es passiert nichts und False wird zur�ckgegeben
* Auf $from steht keine Figur Es passiert nichts und False wird zur�ckgegeben
* $to ist null Figur wird vom Feld entfernt, True wird zur�ck gegeben.
*
* Beispiel: moveFigure("H3", "K4")
*
* @param from Feld von dem eine Figur bewegt werden soll
* @param to Feld zu dem die Figur bewegt werden soll
* @return True, wenn eine Figur bewegt wurde; False sonst
*/
public boolean moveFigure(String from, String to) {
if (to == null) {
return removeFigure(to);
}
if (figures.containsKey(from) && isFieldNameValid(to)) {
Image img = figures.get(from);
/* Statisch */ //setFigurePosition(img, to);
figures.remove(from);
removeFigure(to); // Zielfigur entfernen
figures.put(to, img);
/* Statisch */ //this.repaint();
cadencer.add(new MoveAnimation(
(AnimationFunction) img.tag,
img,
getFigurePositionX(to),
getFigurePositionY(to)
));
return true;
} else {
return false;
}
}
public static boolean isFieldNameValid(String fieldName) {
for (String s : FIELD_NAMES) {
if (s.equals(fieldName)) {
return true;
}
}
return false;
}
/**
* Setzt eine neue Figur auf das Spielfeld
*
* @param field Feld auf das die Figur gesetzt werden soll
* @param figure Figur, die aufs Feld gesetzt werden soll
* @return True, wenn die Figur erfolgreich auf das Feld gesetzt wurde; False, sonst
*/
public boolean setFigure(String field, Figure figure) {
if (figure == null) {
return removeFigure(field);
}
Image img = new Image(FigureLoader.loadFigure(figure));
setAnimationFunction(img, figure);
setFigurePosition(img, field);
getRoot().add(img);
removeFigure(field);
figures.put(field, img);
this.repaint();
return true;
}
/**
* Entfernt eine Figur vom Spielfeld
*
* @param field Feld von dem eine Figur entfernt werden soll
* @return True, wenn tats�chlich eine Figur entfernt wurde
*/
private boolean removeFigure(String field) {
if (figures.containsKey(field)) {
getRoot().items.remove(figures.get(field));
figures.remove(figures.get(field));
this.repaint();
return true;
} else {
return false;
}
}
///endregion
///region Animation
private Cadencer cadencer = new Cadencer(20);
private void initAnimations() {
cadencer.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
repaint();
}
});
cadencer.start();
}
private void setAnimationFunction(Image img, Figure figure) {
if (figure.getType().equals("bishop")) {
img.tag = new ElasticFunction();
} else if (figure.getType().equals("king")) {
img.tag = new ElasticFunction();
} else if (figure.getType().equals("knight")) {
img.tag = new SmoothFunction();
} else if (figure.getType().equals("pawn")) {
img.tag = new ElasticFunction();
} else if (figure.getType().equals("queen")) {
img.tag = new ExpFunction(4);
} else if (figure.getType().equals("rook")) {
img.tag = new LineareFunction();
} else {
img.tag = new ElasticFunction();
}
}
///endregion
}