Update Resources.java

Joker Bilder sind jetzt auch in resources
This commit is contained in:
Dennis Weinberger 2019-03-25 16:36:44 +00:00
parent b2e00366f2
commit 34e634a05d

View file

@ -1,334 +1,343 @@
package gui;
import game.ScoreEntry;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.List;
/**
* Diese Klasse verwaltet die Resourcen des Spiels, darunter beispielsweise Bilder, Icons und Schriftarten.
*/
public class Resources {
private static final int NUM_CASTLES = 6;
private static Resources instance;
private Map<Color, BufferedImage[]> castlesColored;
private BufferedImage dices[];
private BufferedImage check;
private BufferedImage unit;
private BufferedImage arrow, arrowDeactivated, plus, plusDeactivated, swords;
private BufferedImage soldiers[];
private List<String> castleNames;
private Font celticFont;
private List<ScoreEntry> scoreEntries;
private boolean resourcesLoaded;
/**
* Privater Konstruktor, dieser wird normalerweise nur einmal aufgerufen
*/
private Resources() {
this.resourcesLoaded = false;
this.scoreEntries = new LinkedList<>();
}
/**
* Gibt die Instanz des Resourcen Managers zurück oder erzeugt eine neue
* @return Resourcen Manager
*/
public static Resources getInstance() {
if(instance == null) {
instance = new Resources();
instance.load();
}
return instance;
}
/**
* Lädt ein Bild aus den Resourcen
* @param name der Name der Datei
* @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
*/
private BufferedImage loadImage(String name) throws IOException {
URL res = Resources.class.getClassLoader().getResource(name);
if(res == null)
throw new IOException("Resource not found: " + name);
return ImageIO.read(res);
}
/**
* Lädt alle Resourcen
* @return true, wenn alle Resourcen erfolgreich geladen wurden
*/
public boolean load() {
if(resourcesLoaded)
return true;
try {
// Load Castle
castlesColored = new HashMap<>();
BufferedImage castles[] = new BufferedImage[NUM_CASTLES];
for(int i = 0; i < NUM_CASTLES; i++)
castles[i] = loadImage("castle" + (i + 1) + ".png");
castlesColored.put(Color.WHITE, castles);
// Load Dices
dices = loadDices();
// Load Icons
soldiers = new BufferedImage[] { loadImage("soldier1.png"), loadImage("soldier2.png") };
check = loadImage("check.png");
unit = loadImage("unit.png");
arrow = loadImage("arrow.png");
swords = loadImage("swords.png");
plus = loadImage("plus.png");
plusDeactivated = loadImage("plus_deactivated.png");
arrowDeactivated = loadImage("arrow_deactivated.png");
// Load Castle names
castleNames = loadRegionNames();
// Load font
celticFont = loadFont("celtic.ttf");
// Load score entries
loadScoreEntries();
resourcesLoaded = true;
return true;
} catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Konnte Resourcen nicht laden: " + ex.getMessage(), "Fehler beim Laden der Resourcen", JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
return false;
}
}
/**
* Speichert bestimmte Resourcen, zurzeit nur den Highscore-Table
* @return gibt true zurück, wenn erfolgreich gespeichert wurde
*/
public boolean save() {
try {
saveScoreEntries();
return true;
} catch(IOException ex) {
ex.printStackTrace();
return false;
}
}
/**
* 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.
* Die Einträge sind in der Liste {@link #scoreEntries} zu finden.
* @see ScoreEntry#write(PrintWriter)
* @throws IOException Eine IOException wird geworfen, wenn Probleme beim Schreiben auftreten.
*/
private void saveScoreEntries() throws IOException {
// TODO: Resources#saveScoreEntries()
}
/**
* Lädt den Highscore-Table aus der Datei "highscores.txt".
* 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.
* 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()}).
* @see ScoreEntry#read(String)
* @see #addScoreEntry(ScoreEntry)
*/
private void loadScoreEntries() {
List<ScoreEntry> regionNames = new LinkedList<>();
InputStream is = Resources.class.getClassLoader().getResourceAsStream("highscores.txt");
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
scoreEntries = new LinkedList<>();
String line;
try {
while((line = br.readLine()) != null) {
line = line.trim();
if(line.length() > 0 && !line.startsWith("#")) {
addScoreEntry(ScoreEntry.read(line));
}
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 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.
* @param scoreEntry Der einzufügende Eintrag
* @see ScoreEntry#compareTo(ScoreEntry)
*/
public void addScoreEntry(ScoreEntry scoreEntry) {
int i = scoreEntries.size() - 1;
for(; i >= 0; i--) {
if(scoreEntry.compareTo(scoreEntries.get(i)) < 0) {
break;
}
}
scoreEntries.add(i + 1, scoreEntry);
}
public List<ScoreEntry> getScoreEntries() {
return scoreEntries;
}
private Font loadFont(String name) throws IOException, FontFormatException {
InputStream is = Resources.class.getClassLoader().getResourceAsStream(name);
Font f = Font.createFont(Font.TRUETYPE_FONT, is);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(f);
return f.deriveFont(20f);
}
private BufferedImage[] loadDices() throws IOException {
BufferedImage[] dices = new BufferedImage[6];
BufferedImage diceImage = loadImage("dices.png");
int diceSizeW = diceImage.getWidth() / 3;
int diceSizeH = diceImage.getHeight() / 2;
if(diceSizeW != diceSizeH)
System.out.println("Invalid dice dimensions for resource: dice.png. Expected 3x2 dices, got dimensions: " + diceImage.getWidth() + "x" + diceImage.getHeight());
int diceSize = diceSizeH;
int num = 0;
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());
// 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);
gr.dispose();
}
}
return dices;
}
private List<String> loadRegionNames() throws IOException {
List<String> regionNames = new LinkedList<>();
InputStream is = Resources.class.getClassLoader().getResourceAsStream("castles.txt");
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
String line;
while((line = br.readLine()) != null) {
line = line.trim();
if(line.length() > 0 && !line.startsWith("#")) {
regionNames.add(line);
}
}
br.close();
return regionNames;
}
private BufferedImage colorImage(BufferedImage original, Color color) {
ColorModel cm = original.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = original.copyData(null);
BufferedImage newImage = new BufferedImage(cm, raster, isAlphaPremultiplied, null);
for(int x = 0; x < original.getWidth(); x++) {
for(int y = 0; y < original.getHeight(); y++) {
Color oldColor = new Color(original.getRGB(x, y), true);
if(oldColor.getRed() == 255 && oldColor.getGreen() == 255 && oldColor.getBlue() == 255 && oldColor.getAlpha() == 255) {
newImage.setRGB(x, y, color.getRGB());
}
}
}
return newImage;
}
public BufferedImage getCastle(Color color, int index) {
if(!resourcesLoaded)
return null;
index = index % NUM_CASTLES;
BufferedImage images[];
if(castlesColored.containsKey(color))
images = castlesColored.get(color);
else
images = new BufferedImage[NUM_CASTLES];
if(images[index] != null)
return images[index];
BufferedImage castleGeneric = castlesColored.get(Color.WHITE)[index];
images[index] = colorImage(castleGeneric, color);
castlesColored.put(color, images);
return images[index];
}
public BufferedImage getDice(int value) {
if(!resourcesLoaded)
return null;
return dices[value % dices.length];
}
public BufferedImage getCheckIcon() {
return this.check;
}
public BufferedImage getUnitIcon() {
return this.unit;
}
public BufferedImage getPlusIcon() {
return this.plus;
}
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;
}
}
package gui;
import game.ScoreEntry;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.List;
/**
* Diese Klasse verwaltet die Resourcen des Spiels, darunter beispielsweise Bilder, Icons und Schriftarten.
*/
public class Resources {
private static final int NUM_CASTLES = 6;
private static Resources instance;
private Map<Color, BufferedImage[]> castlesColored;
private BufferedImage jokers[];
private BufferedImage dices[];
private BufferedImage check;
private BufferedImage unit;
private BufferedImage arrow, arrowDeactivated, plus, plusDeactivated, swords;
private BufferedImage soldiers[];
private List<String> castleNames;
private Font celticFont;
private List<ScoreEntry> scoreEntries;
private boolean resourcesLoaded;
/**
* Privater Konstruktor, dieser wird normalerweise nur einmal aufgerufen
*/
private Resources() {
this.resourcesLoaded = false;
this.scoreEntries = new LinkedList<>();
}
/**
* Gibt die Instanz des Resourcen Managers zurück oder erzeugt eine neue
* @return Resourcen Manager
*/
public static Resources getInstance() {
if(instance == null) {
instance = new Resources();
instance.load();
}
return instance;
}
/**
* Lädt ein Bild aus den Resourcen
* @param name der Name der Datei
* @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
*/
private BufferedImage loadImage(String name) throws IOException {
URL res = Resources.class.getClassLoader().getResource(name);
if(res == null)
throw new IOException("Resource not found: " + name);
return ImageIO.read(res);
}
/**
* Lädt alle Resourcen
* @return true, wenn alle Resourcen erfolgreich geladen wurden
*/
public boolean load() {
if(resourcesLoaded)
return true;
try {
// Load Castle
castlesColored = new HashMap<>();
BufferedImage castles[] = new BufferedImage[NUM_CASTLES];
for(int i = 0; i < NUM_CASTLES; i++)
castles[i] = loadImage("castle" + (i + 1) + ".png");
castlesColored.put(Color.WHITE, castles);
// Load Dices
dices = loadDices();
// Load Jokers
jokers = new BufferedImage[] { loadImage("add_troops_joker.png"), loadImage("add_troops_joker_disabled.png"), loadImage("scare_troops.png"), loadImage("scare_troops_disabled.png") };
// Load Icons
soldiers = new BufferedImage[] { loadImage("soldier1.png"), loadImage("soldier2.png") };
check = loadImage("check.png");
unit = loadImage("unit.png");
arrow = loadImage("arrow.png");
swords = loadImage("swords.png");
plus = loadImage("plus.png");
plusDeactivated = loadImage("plus_deactivated.png");
arrowDeactivated = loadImage("arrow_deactivated.png");
// Load Castle names
castleNames = loadRegionNames();
// Load font
celticFont = loadFont("celtic.ttf");
// Load score entries
loadScoreEntries();
resourcesLoaded = true;
return true;
} catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Konnte Resourcen nicht laden: " + ex.getMessage(), "Fehler beim Laden der Resourcen", JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
return false;
}
}
/**
* Speichert bestimmte Resourcen, zurzeit nur den Highscore-Table
* @return gibt true zurück, wenn erfolgreich gespeichert wurde
*/
public boolean save() {
try {
saveScoreEntries();
return true;
} catch(IOException ex) {
ex.printStackTrace();
return false;
}
}
/**
* 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.
* Die Einträge sind in der Liste {@link #scoreEntries} zu finden.
* @see ScoreEntry#write(PrintWriter)
* @throws IOException Eine IOException wird geworfen, wenn Probleme beim Schreiben auftreten.
*/
private void saveScoreEntries() throws IOException {
// TODO: Resources#saveScoreEntries()
}
/**
* Lädt den Highscore-Table aus der Datei "highscores.txt".
* 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.
* 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()}).
* @see ScoreEntry#read(String)
* @see #addScoreEntry(ScoreEntry)
*/
private void loadScoreEntries() {
List<ScoreEntry> regionNames = new LinkedList<>();
InputStream is = Resources.class.getClassLoader().getResourceAsStream("highscores.txt");
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
scoreEntries = new LinkedList<>();
String line;
try {
while((line = br.readLine()) != null) {
line = line.trim();
if(line.length() > 0 && !line.startsWith("#")) {
addScoreEntry(ScoreEntry.read(line));
}
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 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.
* @param scoreEntry Der einzufügende Eintrag
* @see ScoreEntry#compareTo(ScoreEntry)
*/
public void addScoreEntry(ScoreEntry scoreEntry) {
int i = scoreEntries.size() - 1;
for(; i >= 0; i--) {
if(scoreEntry.compareTo(scoreEntries.get(i)) < 0) {
break;
}
}
scoreEntries.add(i + 1, scoreEntry);
}
public List<ScoreEntry> getScoreEntries() {
return scoreEntries;
}
private Font loadFont(String name) throws IOException, FontFormatException {
InputStream is = Resources.class.getClassLoader().getResourceAsStream(name);
Font f = Font.createFont(Font.TRUETYPE_FONT, is);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(f);
return f.deriveFont(20f);
}
private BufferedImage[] loadDices() throws IOException {
BufferedImage[] dices = new BufferedImage[6];
BufferedImage diceImage = loadImage("dices.png");
int diceSizeW = diceImage.getWidth() / 3;
int diceSizeH = diceImage.getHeight() / 2;
if(diceSizeW != diceSizeH)
System.out.println("Invalid dice dimensions for resource: dice.png. Expected 3x2 dices, got dimensions: " + diceImage.getWidth() + "x" + diceImage.getHeight());
int diceSize = diceSizeH;
int num = 0;
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());
// 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);
gr.dispose();
}
}
return dices;
}
private List<String> loadRegionNames() throws IOException {
List<String> regionNames = new LinkedList<>();
InputStream is = Resources.class.getClassLoader().getResourceAsStream("castles.txt");
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
String line;
while((line = br.readLine()) != null) {
line = line.trim();
if(line.length() > 0 && !line.startsWith("#")) {
regionNames.add(line);
}
}
br.close();
return regionNames;
}
private BufferedImage colorImage(BufferedImage original, Color color) {
ColorModel cm = original.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = original.copyData(null);
BufferedImage newImage = new BufferedImage(cm, raster, isAlphaPremultiplied, null);
for(int x = 0; x < original.getWidth(); x++) {
for(int y = 0; y < original.getHeight(); y++) {
Color oldColor = new Color(original.getRGB(x, y), true);
if(oldColor.getRed() == 255 && oldColor.getGreen() == 255 && oldColor.getBlue() == 255 && oldColor.getAlpha() == 255) {
newImage.setRGB(x, y, color.getRGB());
}
}
}
return newImage;
}
public BufferedImage getCastle(Color color, int index) {
if(!resourcesLoaded)
return null;
index = index % NUM_CASTLES;
BufferedImage images[];
if(castlesColored.containsKey(color))
images = castlesColored.get(color);
else
images = new BufferedImage[NUM_CASTLES];
if(images[index] != null)
return images[index];
BufferedImage castleGeneric = castlesColored.get(Color.WHITE)[index];
images[index] = colorImage(castleGeneric, color);
castlesColored.put(color, images);
return images[index];
}
public BufferedImage getDice(int value) {
if(!resourcesLoaded)
return null;
return dices[value % dices.length];
}
public BufferedImage getCheckIcon() {
return this.check;
}
public BufferedImage getUnitIcon() {
return this.unit;
}
public BufferedImage getPlusIcon() {
return this.plus;
}
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[] getJokers() {
return this.jokers;
}
public BufferedImage getPlusIconDeactivated() {
return this.plusDeactivated;
}
public Font getCelticFont() {
return this.celticFont;
}
}