/*
* Created on 30.09.2005
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Polygon;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* Zeigt einen Mech-Körper und ermöglicht es, den Schaden einzelner Körperteile
* mit verschiedenen Farben zu visualisieren.
*
* @author Manuel Alabor
* @version 1.0
*/
public class MechState extends JComponent {
private Hashtable stats;
private Image statImage;
public final static String LEFT_ARM = "leftarm";
public final static String RIGHT_ARM = "rightarm";
// Konstruktoren -----------------------------------------------------------
/**
* Initialisiert die Component.
*/
public MechState() {
loadImage();
initStats();;
setPreferredSize(new Dimension(165,137));
}
// Initialisierung ---------------------------------------------------------
/**
* Lädt das Bild des Mech-Körpers.
*/
private void loadImage() {
/* Bild holen: */
URL url = MechState.class.getResource("status1.jpg");
statImage = Toolkit.getDefaultToolkit().getImage(url);
/* Bild abwarten: */
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(statImage, 1);
try {
tracker.waitForAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Erstellt die Körperteil-Definitionen
*/
private void initStats() {
/* Vorbereiten: */
// Linker Arm:
Polygon polyLeftArm = new Polygon(new int[]{23,17,25,32,31,35,35,28,31},
new int[]{40,55,66,56,40,34,22,27,31},
9);
State leftArm = new State(polyLeftArm);
// Rechter Arm:
Polygon polyRightArm = new Polygon(new int[]{72,78,85,87,83,80,73,76,71,70,72},
new int[]{55,65,60,54,40,42,34,29,22,36,43},
11);
State rightArm = new State(polyRightArm);
/* Hinzufügen: */
stats = new Hashtable();
stats.put(LEFT_ARM, leftArm);
stats.put(RIGHT_ARM, rightArm);
}
// Grafikausgabe -----------------------------------------------------------
/**
* Zeichnet den Mech-Körper und visualisiert den Schaden der einzelnen
* Körperteile mit verschiedenen Farben.
*
* @param g
*/
protected void paintComponent(Graphics g) {
super.paintComponent(g);
/* Mech-Körper zeichnen: */
g.drawImage(statImage, 0,0, this);
/* Status der Körperteile zeichnen: */
for(Enumeration e = stats.elements(); e.hasMoreElements();) {
State state = (State)e.nextElement();
float value = state.getValue();
if(value <= 1 && value > 0.6) {
g.setColor(Color.GREEN);
} else if(value <= 0.6 && value > 0.4) {
g.setColor(Color.ORANGE);
} else if(value <= 0.4 && value > 0) {
g.setColor(Color.RED);
} else {
g.setColor(Color.BLACK);
}
g.fillPolygon(state.getPolygon());
}
}
// Zugriff -----------------------------------------------------------------
/**
* Fügt dem Körperteil mit dem ID <code>id</code> einen Schaden von
* <code>demage</code> hinzu.
*
* @param id
* @param demage
*/
public void makeDemage(Object id, float demage) {
State state = (State)stats.get(id);
float current = state.getValue();
float newValue = current - demage;
setState(id, newValue);
}
/**
* Setzt den Schaden auf <code>value</code> des Körperteils mit dem ID
* <code>id</code>
*
* @param id
* @param value
*/
public void setState(Object id, float value) {
State state = (State)stats.get(id);
state.setValue(value);
repaint();
}
// Hilfsklassen ------------------------------------------------------------
/**
* Einfaches Bean für das Speichern von Informationen zu einem Körperteil.
*/
private class State {
float value;
private Polygon polygon;
public State(Polygon polygon, float value) {
this.polygon = polygon;
this.value = value;
}
public State(Polygon polygon) {
this(polygon, 1);
}
public Polygon getPolygon() {
return polygon;
}
public void setPolygon(Polygon polygon) {
this.polygon = polygon;
}
public float getValue() {
return value;
}
public void setValue(float value) {
this.value = value;
}
}
// Testing-Code ------------------------------------------------------------
/**
* Zeigt ein JFrame mit der MechState-Component an.
* Über zwei JButtons kann jeweils ein Schaden von 0.2f dem rechten oder
* linken Arm zugefügt werden.
*/
public static void main(String[] args) {
/* Vorbereiten: */
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/* Components: */
final MechState mech = new MechState();
final JButton btnMakeLeftDemage = new JButton("Left");
final JButton btnMakeRightDemage = new JButton("Right");
/* Listeners: */
btnMakeLeftDemage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mech.makeDemage(MechState.LEFT_ARM, 0.2f);
}
});
btnMakeRightDemage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mech.makeDemage(MechState.RIGHT_ARM, 0.2f);
}
});
/* Zusammensetzen: */
JPanel contentPane = (JPanel)frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(mech, BorderLayout.CENTER);
JPanel buttons = new JPanel(new BorderLayout());
buttons.add(btnMakeLeftDemage, BorderLayout.WEST);
buttons.add(btnMakeRightDemage, BorderLayout.EAST);
contentPane.add(buttons, BorderLayout.SOUTH);
/* Anzeigen & co.: */
frame.pack();
frame.setLocation(200,200);
frame.show();
}
// Helper-Code -------------------------------------------------------------
// Folgender Code erleichtert das ermitteln der Körperteil-Polygone.
// Durch einfügen der Code-Teile an die entsprechenden Orte, können
// anschliessend die Eckpunkt eines Polygons mit der linken Maustaste fest-
// gelegt werden. Durch einen Rechtsklick werden alle Benötigten Informationen
// für den Polygon-Konstruktor in der Konsole ausgegeben.
// -> Benötigte Objekte in der Klasse:
// private ArrayList points = new ArrayList();
// -> Für Konstruktor:
// addMouseListener(new MouseAdapter() {
// public void mouseReleased(MouseEvent e) {
// if(!e.isPopupTrigger()) {
// points.add(e.getPoint());
// System.out.println("Added " + e.getX() + "/" + e.getY());
// } else {
// int[] xPoints = new int[points.size()];
// int[] yPoints = new int[points.size()];
//
// for (int i = 0, l = points.size(); i < l; i++) {
// Point point = (Point)points.get(i);
// xPoints[i] = (int)point.getX();
// yPoints[i] = (int)point.getY();
// }
//
// StringBuffer buffer = new StringBuffer();
// buffer.append("X: new int[]{");
// for (int i = 0, l = xPoints.length; i < l; i++) {
// buffer.append(xPoints[i]);
// if(i < l) buffer.append(",");
// }
// buffer.append("}\n");
//
// buffer.append("Y: new int[]{");
// for (int i = 0, l = yPoints.length; i < l; i++) {
// buffer.append(yPoints[i]);
// if(i < l) buffer.append(",");
// }
// buffer.append("}\n");
// buffer.append("nPoints: " + points.size());
// System.out.println(buffer.toString());
//
// points = new ArrayList();
// }
// repaint();
// }
//});
// -> Für paintComponent-Methode:
// g.setColor(Color.red);
// for (int i = 0, l = points.size(); i < l; i++) {
// Point point = (Point)points.get(i);
// g.drawOval((int)point.getX(),(int)point.getY(),1,1);
// }
}