Solved 3.2.2

This commit is contained in:
stiv2804 2019-02-14 15:38:43 +01:00
parent b6ba4e7c3b
commit 97f592598b

View file

@ -1,315 +1,341 @@
package gui; package gui;
import game.ScoreEntry; import game.ScoreEntry;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.ColorModel; import java.awt.image.ColorModel;
import java.awt.image.WritableRaster; import java.awt.image.WritableRaster;
import java.io.*; import java.io.*;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
/** /**
* Diese Klasse verwaltet die Resourcen des Spiels, darunter beispielsweise Bilder, Icons und Schriftarten. * Diese Klasse verwaltet die Resourcen des Spiels, darunter beispielsweise Bilder, Icons und Schriftarten.
*/ */
public class Resources { public class Resources {
private static final int NUM_CASTLES = 6; private static final int NUM_CASTLES = 6;
private static Resources instance; private static Resources instance;
private Map<Color, BufferedImage[]> castlesColored; private Map<Color, BufferedImage[]> castlesColored;
private BufferedImage dices[]; private BufferedImage dices[];
private BufferedImage check; private BufferedImage check;
private BufferedImage unit; private BufferedImage unit;
private BufferedImage arrow, arrowDeactivated, plus, plusDeactivated, swords; private BufferedImage arrow, arrowDeactivated, plus, plusDeactivated, swords;
private BufferedImage soldiers[]; private BufferedImage soldiers[];
private List<String> castleNames; private List<String> castleNames;
private Font celticFont; private Font celticFont;
private List<ScoreEntry> scoreEntries; private List<ScoreEntry> scoreEntries;
private boolean resourcesLoaded; private boolean resourcesLoaded;
/** /**
* Privater Konstruktor, dieser wird normalerweise nur einmal aufgerufen * Privater Konstruktor, dieser wird normalerweise nur einmal aufgerufen
*/ */
private Resources() { private Resources() {
this.resourcesLoaded = false; this.resourcesLoaded = false;
this.scoreEntries = new LinkedList<>(); this.scoreEntries = new LinkedList<>();
} }
/** /**
* Gibt die Instanz des Resourcen Managers zurück oder erzeugt eine neue * Gibt die Instanz des Resourcen Managers zurück oder erzeugt eine neue
* @return Resourcen Manager * @return Resourcen Manager
*/ */
public static Resources getInstance() { public static Resources getInstance() {
if(instance == null) { if(instance == null) {
instance = new Resources(); instance = new Resources();
instance.load(); instance.load();
} }
return instance; return instance;
} }
/** /**
* Lädt ein Bild aus den Resourcen * Lädt ein Bild aus den Resourcen
* @param name der Name der Datei * @param name der Name der Datei
* @return das Bild als {@link BufferedImage}-Objekt * @return das Bild als {@link BufferedImage}-Objekt
* @throws IOException Eine IOException wird geworfen, falls das Bild nicht gefunden wurde oder andere Probleme beim Laden auftreten * @throws IOException Eine IOException wird geworfen, falls das Bild nicht gefunden wurde oder andere Probleme beim Laden auftreten
*/ */
private BufferedImage loadImage(String name) throws IOException { private BufferedImage loadImage(String name) throws IOException {
URL res = Resources.class.getClassLoader().getResource(name); URL res = Resources.class.getClassLoader().getResource(name);
if(res == null) if(res == null)
throw new IOException("Resource not found: " + name); throw new IOException("Resource not found: " + name);
return ImageIO.read(res); return ImageIO.read(res);
} }
/** /**
* Lädt alle Resourcen * Lädt alle Resourcen
* @return true, wenn alle Resourcen erfolgreich geladen wurden * @return true, wenn alle Resourcen erfolgreich geladen wurden
*/ */
public boolean load() { public boolean load() {
if(resourcesLoaded) if(resourcesLoaded)
return true; return true;
try { try {
// Load Castle // Load Castle
castlesColored = new HashMap<>(); castlesColored = new HashMap<>();
BufferedImage castles[] = new BufferedImage[NUM_CASTLES]; BufferedImage castles[] = new BufferedImage[NUM_CASTLES];
for(int i = 0; i < NUM_CASTLES; i++) for(int i = 0; i < NUM_CASTLES; i++)
castles[i] = loadImage("castle" + (i + 1) + ".png"); castles[i] = loadImage("castle" + (i + 1) + ".png");
castlesColored.put(Color.WHITE, castles); castlesColored.put(Color.WHITE, castles);
// Load Dices // Load Dices
dices = loadDices(); dices = loadDices();
// Load Icons // Load Icons
soldiers = new BufferedImage[] { loadImage("soldier1.png"), loadImage("soldier2.png") }; soldiers = new BufferedImage[] { loadImage("soldier1.png"), loadImage("soldier2.png") };
check = loadImage("check.png"); check = loadImage("check.png");
unit = loadImage("unit.png"); unit = loadImage("unit.png");
arrow = loadImage("arrow.png"); arrow = loadImage("arrow.png");
swords = loadImage("swords.png"); swords = loadImage("swords.png");
plus = loadImage("plus.png"); plus = loadImage("plus.png");
plusDeactivated = loadImage("plus_deactivated.png"); plusDeactivated = loadImage("plus_deactivated.png");
arrowDeactivated = loadImage("arrow_deactivated.png"); arrowDeactivated = loadImage("arrow_deactivated.png");
// Load Castle names // Load Castle names
castleNames = loadRegionNames(); castleNames = loadRegionNames();
// Load font // Load font
celticFont = loadFont("celtic.ttf"); celticFont = loadFont("celtic.ttf");
// Load score entries // Load score entries
loadScoreEntries(); loadScoreEntries();
resourcesLoaded = true; resourcesLoaded = true;
return true; return true;
} catch(Exception ex) { } catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Konnte Resourcen nicht laden: " + ex.getMessage(), "Fehler beim Laden der Resourcen", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(null, "Konnte Resourcen nicht laden: " + ex.getMessage(), "Fehler beim Laden der Resourcen", JOptionPane.ERROR_MESSAGE);
ex.printStackTrace(); ex.printStackTrace();
return false; return false;
} }
} }
/** /**
* Speichert bestimmte Resourcen, zurzeit nur den Highscore-Table * Speichert bestimmte Resourcen, zurzeit nur den Highscore-Table
* @return gibt true zurück, wenn erfolgreich gespeichert wurde * @return gibt true zurück, wenn erfolgreich gespeichert wurde
*/ */
public boolean save() { public boolean save() {
try { try {
saveScoreEntries(); saveScoreEntries();
return true; return true;
} catch(IOException ex) { } catch(IOException ex) {
ex.printStackTrace(); ex.printStackTrace();
return false; return false;
} }
} }
/** /**
* Diese Methode speichert alle Objekte des Typs {@link ScoreEntry} in der Textdatei "highscores.txt" * Diese Methode speichert alle Objekte des Typs {@link ScoreEntry} in der Textdatei "highscores.txt"
* Jede Zeile stellt dabei einen ScoreEntry dar. Sollten Probleme auftreten, muss eine {@link IOException} geworfen werden. * Jede Zeile stellt dabei einen ScoreEntry dar. Sollten Probleme auftreten, muss eine {@link IOException} geworfen werden.
* Die Einträge sind in der Liste {@link #scoreEntries} zu finden. * Die Einträge sind in der Liste {@link #scoreEntries} zu finden.
* @see ScoreEntry#write(PrintWriter) * @see ScoreEntry#write(PrintWriter)
* @throws IOException Eine IOException wird geworfen, wenn Probleme beim Schreiben auftreten. * @throws IOException Eine IOException wird geworfen, wenn Probleme beim Schreiben auftreten.
*/ */
private void saveScoreEntries() throws IOException { private void saveScoreEntries() throws IOException {
// TODO: Resources#saveScoreEntries() // TODO: Resources#saveScoreEntries()
} }
/** /**
* Lädt den Highscore-Table aus der Datei "highscores.txt". * Lädt den Highscore-Table aus der Datei "highscores.txt".
* Dabei wird die Liste {@link #scoreEntries} neu erzeugt und befüllt. * Dabei wird die Liste {@link #scoreEntries} neu erzeugt und befüllt.
* Beachte dabei, dass die Liste nach dem Einlen absteigend nach den Punktzahlen sortiert sein muss. * Beachte dabei, dass die Liste nach dem Einlen absteigend nach den Punktzahlen sortiert sein muss.
* Sollte eine Exception auftreten, kann diese ausgegeben werden, sie sollte aber nicht weitergegeben werden, * Sollte eine Exception auftreten, kann diese ausgegeben werden, sie sollte aber nicht weitergegeben werden,
* da sonst das Laden der restlichen Resourcen abgebrochen wird ({@link #load()}). * da sonst das Laden der restlichen Resourcen abgebrochen wird ({@link #load()}).
* @see ScoreEntry#read(String) * @see ScoreEntry#read(String)
* @see #addScoreEntry(ScoreEntry) * @see #addScoreEntry(ScoreEntry)
*/ */
private void loadScoreEntries() { private void loadScoreEntries() {
// TODO: Resources#loadScoreEntries()
} List<ScoreEntry> regionNames = new LinkedList<>();
InputStream is = Resources.class.getClassLoader().getResourceAsStream("highscores.txt");
/** InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
* Fügt ein {@link ScoreEntry}-Objekt der Liste von Einträgen hinzu. BufferedReader br = new BufferedReader(isr);
* Beachte: Nach dem Einfügen muss die Liste nach den Punktzahlen absteigend sortiert bleiben. ScoreEntry temp;
* @param scoreEntry Der einzufügende Eintrag scoreEntries = new LinkedList<>();
* @see ScoreEntry#compareTo(ScoreEntry) String line;
*/ try {
public void addScoreEntry(ScoreEntry scoreEntry) { while((line = br.readLine()) != null) {
int i = scoreEntries.size() - 1; line = line.trim();
for(; i >= 0; i--) { if(line.length() > 0 && !line.startsWith("#")) {
if(scoreEntry.compareTo(scoreEntries.get(i)) < 0) { temp = ScoreEntry.read(line);
break; scoreEntries.add(temp);
} }
} }
Collections.sort(scoreEntries, new Comparator<ScoreEntry>() {
scoreEntries.add(i + 1, scoreEntry); @Override
} public int compare(ScoreEntry s1, ScoreEntry s2) {
return s1.compareTo(s2);
public List<ScoreEntry> getScoreEntries() { } } );
return scoreEntries;
} br.close();
} catch (IOException e) {
private Font loadFont(String name) throws IOException, FontFormatException { // TODO Auto-generated catch block
InputStream is = Resources.class.getClassLoader().getResourceAsStream(name); e.printStackTrace();
Font f = Font.createFont(Font.TRUETYPE_FONT, is); }
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); }
ge.registerFont(f);
return f.deriveFont(20f); /**
} * Fügt ein {@link ScoreEntry}-Objekt der Liste von Einträgen hinzu.
* Beachte: Nach dem Einfügen muss die Liste nach den Punktzahlen absteigend sortiert bleiben.
private BufferedImage[] loadDices() throws IOException { * @param scoreEntry Der einzufügende Eintrag
BufferedImage[] dices = new BufferedImage[6]; * @see ScoreEntry#compareTo(ScoreEntry)
BufferedImage diceImage = loadImage("dices.png"); */
int diceSizeW = diceImage.getWidth() / 3; public void addScoreEntry(ScoreEntry scoreEntry) {
int diceSizeH = diceImage.getHeight() / 2; int i = scoreEntries.size() - 1;
if(diceSizeW != diceSizeH) for(; i >= 0; i--) {
System.out.println("Invalid dice dimensions for resource: dice.png. Expected 3x2 dices, got dimensions: " + diceImage.getWidth() + "x" + diceImage.getHeight()); if(scoreEntry.compareTo(scoreEntries.get(i)) < 0) {
break;
int diceSize = diceSizeH; }
int num = 0; }
for (int x = 0; x < 2; x++) { scoreEntries.add(i + 1, scoreEntry);
for (int y = 0; y < 3; y++) { }
//Initialize the image array with image chunks
dices[num] = new BufferedImage(diceSize, diceSize, diceImage.getType()); public List<ScoreEntry> getScoreEntries() {
return scoreEntries;
// draws the image chunk }
Graphics2D gr = dices[num++].createGraphics();
gr.drawImage(diceImage, 0, 0, diceSize, diceSize, diceSize * y, diceSize * x, diceSize * y + diceSize, diceSize * x + diceSize, null); private Font loadFont(String name) throws IOException, FontFormatException {
gr.dispose(); InputStream is = Resources.class.getClassLoader().getResourceAsStream(name);
} Font f = Font.createFont(Font.TRUETYPE_FONT, is);
} GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(f);
return dices; return f.deriveFont(20f);
} }
private List<String> loadRegionNames() throws IOException { private BufferedImage[] loadDices() throws IOException {
BufferedImage[] dices = new BufferedImage[6];
List<String> regionNames = new LinkedList<>(); BufferedImage diceImage = loadImage("dices.png");
InputStream is = Resources.class.getClassLoader().getResourceAsStream("castles.txt"); int diceSizeW = diceImage.getWidth() / 3;
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8); int diceSizeH = diceImage.getHeight() / 2;
BufferedReader br = new BufferedReader(isr); if(diceSizeW != diceSizeH)
System.out.println("Invalid dice dimensions for resource: dice.png. Expected 3x2 dices, got dimensions: " + diceImage.getWidth() + "x" + diceImage.getHeight());
String line;
while((line = br.readLine()) != null) { int diceSize = diceSizeH;
line = line.trim(); int num = 0;
if(line.length() > 0 && !line.startsWith("#")) {
regionNames.add(line); for (int x = 0; x < 2; x++) {
} for (int y = 0; y < 3; y++) {
} //Initialize the image array with image chunks
dices[num] = new BufferedImage(diceSize, diceSize, diceImage.getType());
br.close();
return regionNames; // draws the image chunk
} Graphics2D gr = dices[num++].createGraphics();
gr.drawImage(diceImage, 0, 0, diceSize, diceSize, diceSize * y, diceSize * x, diceSize * y + diceSize, diceSize * x + diceSize, null);
private BufferedImage colorImage(BufferedImage original, Color color) { gr.dispose();
ColorModel cm = original.getColorModel(); }
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); }
WritableRaster raster = original.copyData(null);
BufferedImage newImage = new BufferedImage(cm, raster, isAlphaPremultiplied, null); return dices;
}
for(int x = 0; x < original.getWidth(); x++) {
for(int y = 0; y < original.getHeight(); y++) { private List<String> loadRegionNames() throws IOException {
Color oldColor = new Color(original.getRGB(x, y), true);
if(oldColor.getRed() == 255 && oldColor.getGreen() == 255 && oldColor.getBlue() == 255 && oldColor.getAlpha() == 255) { List<String> regionNames = new LinkedList<>();
newImage.setRGB(x, y, color.getRGB()); InputStream is = Resources.class.getClassLoader().getResourceAsStream("castles.txt");
} InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
} BufferedReader br = new BufferedReader(isr);
}
String line;
return newImage; while((line = br.readLine()) != null) {
} line = line.trim();
if(line.length() > 0 && !line.startsWith("#")) {
public BufferedImage getCastle(Color color, int index) { regionNames.add(line);
if(!resourcesLoaded) }
return null; }
index = index % NUM_CASTLES; br.close();
BufferedImage images[]; return regionNames;
if(castlesColored.containsKey(color)) }
images = castlesColored.get(color);
else private BufferedImage colorImage(BufferedImage original, Color color) {
images = new BufferedImage[NUM_CASTLES]; ColorModel cm = original.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
if(images[index] != null) WritableRaster raster = original.copyData(null);
return images[index]; BufferedImage newImage = new BufferedImage(cm, raster, isAlphaPremultiplied, null);
BufferedImage castleGeneric = castlesColored.get(Color.WHITE)[index]; for(int x = 0; x < original.getWidth(); x++) {
images[index] = colorImage(castleGeneric, color); for(int y = 0; y < original.getHeight(); y++) {
castlesColored.put(color, images); Color oldColor = new Color(original.getRGB(x, y), true);
return images[index]; if(oldColor.getRed() == 255 && oldColor.getGreen() == 255 && oldColor.getBlue() == 255 && oldColor.getAlpha() == 255) {
} newImage.setRGB(x, y, color.getRGB());
}
public BufferedImage getDice(int value) { }
if(!resourcesLoaded) }
return null;
return newImage;
return dices[value % dices.length]; }
}
public BufferedImage getCastle(Color color, int index) {
public BufferedImage getCheckIcon() { if(!resourcesLoaded)
return this.check; return null;
}
index = index % NUM_CASTLES;
public BufferedImage getUnitIcon() { BufferedImage images[];
return this.unit; if(castlesColored.containsKey(color))
} images = castlesColored.get(color);
else
public BufferedImage getPlusIcon() { images = new BufferedImage[NUM_CASTLES];
return this.plus;
} if(images[index] != null)
return images[index];
public BufferedImage getArrowIcon() {
return this.arrow; BufferedImage castleGeneric = castlesColored.get(Color.WHITE)[index];
} images[index] = colorImage(castleGeneric, color);
castlesColored.put(color, images);
public BufferedImage getSwordsIcon() { return images[index];
return this.swords; }
}
public BufferedImage getDice(int value) {
public BufferedImage getArrowIconDeactivated() { if(!resourcesLoaded)
return this.arrowDeactivated; return null;
}
return dices[value % dices.length];
public BufferedImage[] getSoldiers() { }
return this.soldiers;
} public BufferedImage getCheckIcon() {
return this.check;
public List<String> getCastleNames() { }
return castleNames;
} public BufferedImage getUnitIcon() {
return this.unit;
public BufferedImage getPlusIconDeactivated() { }
return this.plusDeactivated;
} public BufferedImage getPlusIcon() {
return this.plus;
public Font getCelticFont() { }
return this.celticFont;
} public BufferedImage getArrowIcon() {
} return this.arrow;
}
public BufferedImage getSwordsIcon() {
return this.swords;
}
public BufferedImage getArrowIconDeactivated() {
return this.arrowDeactivated;
}
public BufferedImage[] getSoldiers() {
return this.soldiers;
}
public List<String> getCastleNames() {
return castleNames;
}
public BufferedImage getPlusIconDeactivated() {
return this.plusDeactivated;
}
public Font getCelticFont() {
return this.celticFont;
}
}