Compare commits
2 Commits
d10313ea76
...
dfba8b397e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfba8b397e | ||
|
|
ec1841a592 |
@@ -1,6 +1,7 @@
|
||||
package eu.midnightdust.yaytris;
|
||||
|
||||
import eu.midnightdust.yaytris.util.Difficulty;
|
||||
import eu.midnightdust.yaytris.util.Language;
|
||||
import eu.midnightdust.yaytris.util.NightJson;
|
||||
|
||||
public class Settings {
|
||||
@@ -11,6 +12,7 @@ public class Settings {
|
||||
public static float guiScale = 3.f;
|
||||
public static boolean shouldScaleSpeed = true;
|
||||
public static Difficulty difficulty = Difficulty.NORMAL;
|
||||
public static Language language = Language.ENGLISH;
|
||||
|
||||
public static void load() {
|
||||
json.readJson();
|
||||
|
||||
@@ -25,6 +25,7 @@ public class Tetris {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Exception | Error e) { System.out.printf("%s: %s\n", "Error setting system look and feel", e); }
|
||||
Settings.load();
|
||||
Translation.load(Settings.language.locale);
|
||||
HighScores.load();
|
||||
timer = new Timer("Tetris falling pieces");
|
||||
space = new Space();
|
||||
|
||||
19
src/main/java/eu/midnightdust/yaytris/Translation.java
Normal file
19
src/main/java/eu/midnightdust/yaytris/Translation.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package eu.midnightdust.yaytris;
|
||||
|
||||
import eu.midnightdust.yaytris.util.NightJson;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Translation {
|
||||
public static Map<String, String> translationMap = new HashMap<>();
|
||||
|
||||
public static void load(String locale) {
|
||||
NightJson json = new NightJson(translationMap, String.format("translation/%s.json5", locale));
|
||||
json.readJson();
|
||||
}
|
||||
|
||||
public static String t(String key, Object... args) {
|
||||
return String.format(translationMap.getOrDefault(key, key), args);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
package eu.midnightdust.yaytris.ui;
|
||||
|
||||
import eu.midnightdust.yaytris.HighScores;
|
||||
import eu.midnightdust.yaytris.util.CatppuccinColor;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.LineBorder;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static eu.midnightdust.yaytris.Translation.t;
|
||||
import static eu.midnightdust.yaytris.ui.TetrisUI.scale;
|
||||
|
||||
public class HighScoreMenu extends JPanel {
|
||||
@@ -17,7 +20,7 @@ public class HighScoreMenu extends JPanel {
|
||||
this.setBounds(x, y, width, height);
|
||||
this.setLayout(null);
|
||||
|
||||
this.add(new JLabel("Highscores:"));
|
||||
this.add(new JLabel(t("highscores.title")));
|
||||
|
||||
List<String> highscores = new ArrayList<>();
|
||||
for (String key : HighScores.scores.keySet()) {
|
||||
@@ -25,11 +28,14 @@ public class HighScoreMenu extends JPanel {
|
||||
}
|
||||
highscores.sort((s1, s2) -> Integer.compare(Integer.parseInt(s2.split("–")[0].replace(" ", "")), Integer.parseInt(s1.split("–")[0].replace(" ", ""))));
|
||||
JList<String> highscoreList = new JList<>(highscores.toArray(String[]::new));
|
||||
highscoreList.setBackground(CatppuccinColor.BASE.getColor());
|
||||
highscoreList.setSelectionForeground(CatppuccinColor.CRUST.getColor());
|
||||
JScrollPane highscoreScrollPane = new JScrollPane(highscoreList);
|
||||
highscoreScrollPane.setBorder(new LineBorder(CatppuccinColor.SURFACE0.getColor(), 3, true));
|
||||
this.add(highscoreScrollPane);
|
||||
highscoreScrollPane.setBounds(scale(60), scale(43), scale(100), scale(80));
|
||||
|
||||
JButton backButton = new JButton("Zurück");
|
||||
JButton backButton = new JButton(t("ui.back"));
|
||||
backButton.addActionListener(ui::openMainMenu);
|
||||
backButton.setBounds(scale(60), scale(140), scale(100), scale(20));
|
||||
this.add(backButton);
|
||||
|
||||
@@ -2,6 +2,8 @@ package eu.midnightdust.yaytris.ui;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import static eu.midnightdust.yaytris.Translation.t;
|
||||
|
||||
public class MainMenu extends AbstractMenu {
|
||||
final TetrisUI ui;
|
||||
|
||||
@@ -10,19 +12,19 @@ public class MainMenu extends AbstractMenu {
|
||||
this.setBounds(x, y, width, height);
|
||||
this.setLayout(null);
|
||||
|
||||
JButton startButton = new JButton("Start");
|
||||
JButton startButton = new JButton(t("menu.start"));
|
||||
startButton.addActionListener(ui::startGame);
|
||||
this.add(startButton);
|
||||
|
||||
JButton settingsButton = new JButton("Einstellungen");
|
||||
JButton settingsButton = new JButton(t("menu.settings"));
|
||||
settingsButton.addActionListener(ui::openSettings);
|
||||
this.add(settingsButton);
|
||||
|
||||
JButton highscoreButton = new JButton("Highscores");
|
||||
JButton highscoreButton = new JButton(t("menu.highscores"));
|
||||
highscoreButton.addActionListener(ui::openHighscores);
|
||||
this.add(highscoreButton);
|
||||
|
||||
JButton leaveButton = new JButton("Spiel verlassen");
|
||||
JButton leaveButton = new JButton(t("menu.exit"));
|
||||
leaveButton.addActionListener(e -> System.exit(0));
|
||||
this.add(leaveButton);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.awt.*;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import static eu.midnightdust.yaytris.Translation.t;
|
||||
import static eu.midnightdust.yaytris.ui.TetrisUI.scale;
|
||||
|
||||
public class ScoreMenu extends AbstractMenu {
|
||||
@@ -32,22 +33,22 @@ public class ScoreMenu extends AbstractMenu {
|
||||
this.gameOverLabel = new JLabel();
|
||||
this.add(gameOverLabel);
|
||||
|
||||
this.currentScoreLabel = new JLabel("Score: 0");
|
||||
this.currentScoreLabel = new JLabel(t("game.score", "0"));
|
||||
this.add(currentScoreLabel);
|
||||
|
||||
this.currentLevelLabel = new JLabel("Level: 0");
|
||||
this.currentLevelLabel = new JLabel(t("game.level", "0"));
|
||||
this.add(currentLevelLabel);
|
||||
|
||||
this.currentTimeLabel = new JLabel("Zeit: 00:00");
|
||||
this.currentTimeLabel = new JLabel(t("game.time", "00:00"));
|
||||
this.add(currentTimeLabel);
|
||||
|
||||
JButton backButton = new JButton("Zurück");
|
||||
JButton backButton = new JButton(t("ui.back"));
|
||||
backButton.addActionListener(ui::openMainMenu);
|
||||
this.add(backButton);
|
||||
}
|
||||
|
||||
public void updateScore(int score) {
|
||||
this.currentScoreLabel.setText(String.format("Score: %s", score));
|
||||
this.currentScoreLabel.setText(t("game.score", score));
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
@@ -55,16 +56,16 @@ public class ScoreMenu extends AbstractMenu {
|
||||
LocalTime timeElapsed = LocalTime.ofNanoOfDay(LocalTime.now().toNanoOfDay() - startingTime.toNanoOfDay());
|
||||
|
||||
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(timeElapsed.getHour() > 0 ? "HH:mm:ss" : "mm:ss");
|
||||
this.currentTimeLabel.setText(String.format("Zeit: %s", timeFormatter.format(timeElapsed)));
|
||||
this.currentTimeLabel.setText(t("game.time", timeFormatter.format(timeElapsed)));
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
public void gameOver() {
|
||||
this.gameOverLabel.setText("Game over :(");
|
||||
this.gameOverLabel.setText(t("game.over"));
|
||||
}
|
||||
|
||||
public void updateLevel(int level) {
|
||||
this.currentLevelLabel.setText(String.format("Level: %s", level));
|
||||
this.currentLevelLabel.setText(t("game.level", level));
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package eu.midnightdust.yaytris.ui;
|
||||
|
||||
import eu.midnightdust.yaytris.Settings;
|
||||
import eu.midnightdust.yaytris.Translation;
|
||||
import eu.midnightdust.yaytris.util.Difficulty;
|
||||
import eu.midnightdust.yaytris.util.Language;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
import static eu.midnightdust.yaytris.Translation.t;
|
||||
import static eu.midnightdust.yaytris.ui.TetrisUI.scale;
|
||||
import static eu.midnightdust.yaytris.ui.TetrisUI.setFontScale;
|
||||
|
||||
@@ -17,7 +20,7 @@ public class SettingsMenu extends JPanel {
|
||||
this.setBounds(x, y, width, height);
|
||||
this.setLayout(null);
|
||||
|
||||
this.add(new JLabel("Musik-Lautstärke:"));
|
||||
this.add(new JLabel(t("settings.volume.music")));
|
||||
JSlider musicVolumeSlider = new JSlider(0, 100, Settings.musicVolume);
|
||||
musicVolumeSlider.addChangeListener(change -> {
|
||||
Settings.musicVolume = musicVolumeSlider.getValue();
|
||||
@@ -25,7 +28,7 @@ public class SettingsMenu extends JPanel {
|
||||
});
|
||||
this.add(musicVolumeSlider);
|
||||
|
||||
this.add(new JLabel("Effekt-Lautstärke:"));
|
||||
this.add(new JLabel(t("settings.volume.sound")));
|
||||
JSlider soundVolumeSlider = new JSlider(0, 100, Settings.soundVolume);
|
||||
soundVolumeSlider.addChangeListener(change -> {
|
||||
Settings.soundVolume = soundVolumeSlider.getValue();
|
||||
@@ -33,7 +36,7 @@ public class SettingsMenu extends JPanel {
|
||||
});
|
||||
this.add(soundVolumeSlider);
|
||||
|
||||
this.add(new JLabel("Fenster-Skalierung:"));
|
||||
this.add(new JLabel(t("settings.window_scaling")));
|
||||
JSlider scaleSlider = new JSlider(100, 600, (int) (Settings.guiScale * 100));
|
||||
scaleSlider.addChangeListener(change -> {
|
||||
Settings.guiScale = scaleSlider.getValue() / 100f;
|
||||
@@ -41,7 +44,7 @@ public class SettingsMenu extends JPanel {
|
||||
});
|
||||
this.add(scaleSlider);
|
||||
|
||||
this.add(new JLabel("Geschwindigkeitszunahme:"));
|
||||
this.add(new JLabel(t("settings.scale_speed")));
|
||||
JCheckBox speedCheckbox = new JCheckBox("Aktiviert", Settings.shouldScaleSpeed);
|
||||
speedCheckbox.addChangeListener(change -> {
|
||||
Settings.shouldScaleSpeed = speedCheckbox.isSelected();
|
||||
@@ -49,7 +52,7 @@ public class SettingsMenu extends JPanel {
|
||||
});
|
||||
this.add(speedCheckbox);
|
||||
|
||||
this.add(new JLabel("Schwierigkeit:"));
|
||||
this.add(new JLabel(t("settings.difficulty")));
|
||||
JComboBox<Difficulty> difficultySelector = new JComboBox<>(Difficulty.values());
|
||||
difficultySelector.setSelectedItem(Settings.difficulty);
|
||||
|
||||
@@ -60,7 +63,20 @@ public class SettingsMenu extends JPanel {
|
||||
this.add(difficultySelector);
|
||||
difficultySelector.setSize(difficultySelector.getBounds().width,scale(10));
|
||||
|
||||
JButton backButton = new JButton("Zurück");
|
||||
this.add(new JLabel(t("settings.language")));
|
||||
JComboBox<Language> languageSelector = new JComboBox<>(Language.values());
|
||||
languageSelector.setSelectedItem(Settings.language);
|
||||
|
||||
languageSelector.addActionListener(action -> {
|
||||
Settings.language = (Language) languageSelector.getSelectedItem();
|
||||
Settings.write();
|
||||
Translation.load(Settings.language.locale);
|
||||
ui.openSettings(action);
|
||||
});
|
||||
this.add(languageSelector);
|
||||
languageSelector.setSize(languageSelector.getBounds().width,scale(10));
|
||||
|
||||
JButton backButton = new JButton(t("ui.back"));
|
||||
backButton.addActionListener(ui::openMainMenu);
|
||||
this.add(backButton);
|
||||
}
|
||||
@@ -68,9 +84,9 @@ public class SettingsMenu extends JPanel {
|
||||
|
||||
@Override
|
||||
public Component add(Component comp) {
|
||||
comp.setBounds(scale(60), scale(20+23*this.getComponentCount()-labelAmount*10), scale(100), scale(20));
|
||||
comp.setBounds(scale(60), scale(20+17*this.getComponentCount()-labelAmount*10), scale(100), scale(20));
|
||||
if (comp instanceof JLabel) {
|
||||
comp.setBounds(scale(60), scale(50+23*(this.getComponentCount()-1)-labelAmount*10), scale(100), scale(7));
|
||||
comp.setBounds(scale(60), scale(20+17*(this.getComponentCount())-labelAmount*10), scale(100), scale(7));
|
||||
labelAmount++;
|
||||
}
|
||||
if (comp instanceof JComponent) setFontScale((JComponent) comp);
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.awt.event.KeyListener;
|
||||
import java.io.IOException;
|
||||
|
||||
import static eu.midnightdust.yaytris.Settings.guiScale;
|
||||
import static eu.midnightdust.yaytris.Translation.t;
|
||||
|
||||
public class TetrisUI extends JFrame implements KeyListener {
|
||||
JLabel titleLabel;
|
||||
@@ -125,7 +126,7 @@ public class TetrisUI extends JFrame implements KeyListener {
|
||||
}
|
||||
|
||||
public void showHighscoreDialog(int score) {
|
||||
String playerName = JOptionPane.showInputDialog(null, "Gib deinen Namen ein:", "Neuer Highscore!", JOptionPane.PLAIN_MESSAGE);
|
||||
String playerName = JOptionPane.showInputDialog(null, t("dialog.highscore.action"), t("dialog.highscore.title"), JOptionPane.PLAIN_MESSAGE);
|
||||
HighScores.addScore(playerName, score);
|
||||
}
|
||||
|
||||
|
||||
17
src/main/java/eu/midnightdust/yaytris/util/Language.java
Normal file
17
src/main/java/eu/midnightdust/yaytris/util/Language.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package eu.midnightdust.yaytris.util;
|
||||
|
||||
public enum Language {
|
||||
ENGLISH("en_gb"), DEUTSCH("de_de");
|
||||
public final String locale;
|
||||
private final String name;
|
||||
|
||||
Language(String locale) {
|
||||
this.locale = locale;
|
||||
this.name = this.name().charAt(0) + this.name().substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
@@ -9,19 +9,24 @@ import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/*
|
||||
NightJson v0.1 by Martin Prokoph
|
||||
NightJson v0.2 by Martin Prokoph
|
||||
Extremely lightweight (and incomplete) JSON library
|
||||
Concept inspired by GSON
|
||||
*/
|
||||
public class NightJson {
|
||||
private static final String KEY_PATTERN = "\"(-?[0-9a-zA-Z]*)\":";
|
||||
private static final String KEY_PATTERN = "\"(-?.*)\":";
|
||||
Class<?> jsonClass;
|
||||
Map<String, ?> jsonMap;
|
||||
String fileLocation;
|
||||
|
||||
public NightJson(Class<?> jsonClass, String fileLocation) {
|
||||
this.jsonClass = jsonClass;
|
||||
this.fileLocation = fileLocation;
|
||||
}
|
||||
public NightJson(Map<String, ?> jsonMap, String fileLocation) {
|
||||
this.jsonMap = jsonMap;
|
||||
this.fileLocation = fileLocation;
|
||||
}
|
||||
|
||||
public void writeJson() {
|
||||
if (fileLocation == null) return;
|
||||
@@ -29,17 +34,22 @@ public class NightJson {
|
||||
FileWriter jsonFile = new FileWriter(fileLocation);
|
||||
|
||||
jsonFile.write("{\n");
|
||||
Iterator<Field> it = Arrays.stream(jsonClass.getFields()).iterator();
|
||||
while (it.hasNext()) {
|
||||
Field field = it.next();
|
||||
jsonFile.write("\t");
|
||||
if (field.getType() == Comment.class) {
|
||||
jsonFile.write(String.format("// %s\n", ((Comment) field.get(null)).commentString));
|
||||
continue;
|
||||
if (jsonClass != null) {
|
||||
Iterator<Field> it = Arrays.stream(jsonClass.getFields()).iterator();
|
||||
while (it.hasNext()) {
|
||||
Field field = it.next();
|
||||
writeElement(jsonFile, field.get(null), field.getType(), field.getName());
|
||||
jsonFile.write(it.hasNext() ? ",\n" : "\n");
|
||||
}
|
||||
}
|
||||
else if (jsonMap != null) {
|
||||
Iterator<String> it = jsonMap.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
String key = it.next();
|
||||
Object value = jsonMap.get(key);
|
||||
writeElement(jsonFile, jsonMap.get(key), value.getClass(), key);
|
||||
jsonFile.write(it.hasNext() ? ",\n" : "\n");
|
||||
}
|
||||
jsonFile.write(String.format("\"%s\": ", field.getName()));
|
||||
jsonFile.write(objToString(field.get(null), field.getType()));
|
||||
jsonFile.write(it.hasNext() ? ",\n" : "\n");
|
||||
}
|
||||
jsonFile.write("}");
|
||||
jsonFile.close();
|
||||
@@ -49,6 +59,16 @@ public class NightJson {
|
||||
}
|
||||
}
|
||||
|
||||
private void writeElement(FileWriter jsonFile, Object value, Class<?> type, String name) throws IOException, IllegalAccessException {
|
||||
jsonFile.write("\t");
|
||||
if (type == Comment.class) {
|
||||
jsonFile.write(String.format("// %s\n", ((Comment) value).commentString));
|
||||
return;
|
||||
}
|
||||
jsonFile.write(String.format("\"%s\": ", name));
|
||||
jsonFile.write(objToString(value, type));
|
||||
}
|
||||
|
||||
public void readJson() {
|
||||
if (fileLocation == null) return;
|
||||
try {
|
||||
@@ -80,11 +100,20 @@ public class NightJson {
|
||||
for (String key : jsonKeyValuePairs.keySet()) {
|
||||
String currentString = jsonKeyValuePairs.get(key);
|
||||
//System.out.printf("Key: %s Value: %s%n", key, currentString);
|
||||
Field field;
|
||||
try { field = jsonClass.getField(key);
|
||||
} catch (NoSuchFieldException e) {continue;}
|
||||
if (jsonClass != null) {
|
||||
Field field;
|
||||
try {
|
||||
field = jsonClass.getField(key);
|
||||
} catch (NoSuchFieldException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
field.set(field, stringToFieldObj(currentString, field));
|
||||
field.set(field, stringToFieldObj(currentString, field));
|
||||
}
|
||||
else if (jsonMap != null) {
|
||||
//noinspection unchecked
|
||||
((Map<String, Object>)jsonMap).put(key, stringToObj(currentString, String.class)); // TODO: Un-hardcode string type
|
||||
}
|
||||
}
|
||||
jsonFile.close();
|
||||
} catch (IOException | IllegalAccessException | NoSuchElementException e) {
|
||||
@@ -93,7 +122,7 @@ public class NightJson {
|
||||
}
|
||||
}
|
||||
|
||||
private String objToString(Object value, Class<?> type) throws IllegalAccessException {
|
||||
private String objToString(Object value, Class<?> type) {
|
||||
if (type == Map.class) {
|
||||
StringBuilder mapPairs = new StringBuilder();
|
||||
Map<?, ?> map = (Map<?, ?>) value;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"scores": {"Martin": 5703}
|
||||
"scores": {"Martin": 6401}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"musicVolume": 19,
|
||||
"musicVolume": 100,
|
||||
"soundVolume": 100,
|
||||
"guiScale": 6.0,
|
||||
"shouldScaleSpeed": true,
|
||||
"difficulty": "Normal"
|
||||
"difficulty": "Normal",
|
||||
"language": "Deutsch"
|
||||
}
|
||||
20
translation/de_de.json5
Normal file
20
translation/de_de.json5
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"dialog.highscore.action": "Gib deinen Namen ein:",
|
||||
"dialog.highscore.title": "Neuer Highscore!",
|
||||
"game.level": "Level: %s",
|
||||
"game.over": "Game over :(",
|
||||
"game.score": "Score: %s",
|
||||
"game.time": "Zeit: %s",
|
||||
"highscores.title": "Highscores:",
|
||||
"menu.exit": "Spiel verlassen",
|
||||
"menu.highscores": "Highscores",
|
||||
"menu.settings": "Einstellungen",
|
||||
"menu.start": "Start",
|
||||
"settings.difficulty": "Schwierigkeit:",
|
||||
"settings.language": "Sprache:",
|
||||
"settings.scale_speed": "Geschwindigkeitszunahme:",
|
||||
"settings.volume.music": "Musik-Lautstärke:",
|
||||
"settings.volume.sound": "Effekt-Lautstärke:",
|
||||
"settings.window_scaling": "Fenster-Skalierung:",
|
||||
"ui.back": "Zurück"
|
||||
}
|
||||
20
translation/en_gb.json5
Normal file
20
translation/en_gb.json5
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"dialog.highscore.action": "Enter your name:",
|
||||
"dialog.highscore.title": "New Highscore!",
|
||||
"game.level": "Level: %s",
|
||||
"game.over": "Game over :(",
|
||||
"game.score": "Score: %s",
|
||||
"game.time": "Time: %s",
|
||||
"highscores.title": "Highscores:",
|
||||
"menu.exit": "Exit Game",
|
||||
"menu.highscores": "Highscores",
|
||||
"menu.settings": "Settings",
|
||||
"menu.start": "Start",
|
||||
"settings.difficulty": "Difficulty:",
|
||||
"settings.language": "Language:",
|
||||
"settings.scale_speed": "Speed Increase:",
|
||||
"settings.volume.music": "Music Volume:",
|
||||
"settings.volume.sound": "Sound Volume:",
|
||||
"settings.window_scaling": "Window Scaling:",
|
||||
"ui.back": "Back"
|
||||
}
|
||||
Reference in New Issue
Block a user