diff --git a/src/main/java/eu/midnightdust/yaytris/Settings.java b/src/main/java/eu/midnightdust/yaytris/Settings.java index 3f795ea..5a2a370 100644 --- a/src/main/java/eu/midnightdust/yaytris/Settings.java +++ b/src/main/java/eu/midnightdust/yaytris/Settings.java @@ -3,9 +3,6 @@ package eu.midnightdust.yaytris; import eu.midnightdust.yaytris.util.Difficulty; import eu.midnightdust.yaytris.util.NightJson; -import java.util.HashMap; -import java.util.Map; - public class Settings { private static final NightJson json = new NightJson(Settings.class, "tetris_settings.json5"); @@ -13,7 +10,6 @@ public class Settings { public static int soundVolume = 100; public static float guiScale = 3.f; public static Difficulty difficulty = Difficulty.NORMAL; - //public static Map highScores = new HashMap<>(); public static void load() { json.readJson(); diff --git a/src/main/java/eu/midnightdust/yaytris/Tetris.java b/src/main/java/eu/midnightdust/yaytris/Tetris.java index 09185e6..c442c10 100644 --- a/src/main/java/eu/midnightdust/yaytris/Tetris.java +++ b/src/main/java/eu/midnightdust/yaytris/Tetris.java @@ -6,6 +6,7 @@ import eu.midnightdust.yaytris.ui.TetrisUI; import eu.midnightdust.yaytris.util.SoundUtil; import javax.swing.*; +import java.time.LocalTime; import java.util.Random; import java.util.Timer; import java.util.TimerTask; @@ -16,6 +17,7 @@ public class Tetris { private static Timer timer; private static TetrisUI ui; private static TimerTask gravityTask; + private static LocalTime startTime; public static void main(String[] args) { try { @@ -42,10 +44,12 @@ public class Tetris { public static void startGame() { SoundUtil.playMusic("/music/theme.wav", true); space.spawnTetromino(); + startTime = LocalTime.now(); gravityTask = new TimerTask() { @Override public void run() { if (space.getCurrentTetromino() != null) { + updateTime(); space.getCurrentTetromino().fall(); ui.getGamePanel().repaint(); } @@ -65,4 +69,7 @@ public class Tetris { public static void updateScore(int score) { if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).updateScore(score); } + public static void updateTime() { + if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).updateTime(startTime); + } } diff --git a/src/main/java/eu/midnightdust/yaytris/game/Space.java b/src/main/java/eu/midnightdust/yaytris/game/Space.java index 7da5f09..665a18d 100644 --- a/src/main/java/eu/midnightdust/yaytris/game/Space.java +++ b/src/main/java/eu/midnightdust/yaytris/game/Space.java @@ -66,6 +66,10 @@ public class Space { Set completedLines = new TreeSet<>(); for (int line : lines) { if (line >= getMapHeight()) continue; + if (line < 0) { + Tetris.stopGame(); + return; + } Color[] newBlobs = tetromino.getLine(line); for (int i = 0; i < newBlobs.length; i++) { if (newBlobs[i] == null) continue; @@ -85,6 +89,7 @@ public class Space { } } increaseScore(combo); + this.spawnTetromino(); } public void increaseScore(int amount) { diff --git a/src/main/java/eu/midnightdust/yaytris/game/Tetromino.java b/src/main/java/eu/midnightdust/yaytris/game/Tetromino.java index 8e8607c..e29f8b8 100644 --- a/src/main/java/eu/midnightdust/yaytris/game/Tetromino.java +++ b/src/main/java/eu/midnightdust/yaytris/game/Tetromino.java @@ -15,7 +15,7 @@ public class Tetromino { public Tetromino(TetrominoShape shape) { this.shape = shape; this.collision = shape.boundary; - this.centerPos = Vec2i.of(2, 0); + this.centerPos = Vec2i.of(Tetris.getSpace().getMapWidth()/2-1, -1); } public boolean fall() { @@ -30,8 +30,6 @@ public class Tetromino { } Tetris.getSpace().onLinesChanged(this, affectedLines); Tetris.getSpace().increaseScore(20-fallLength); - if (fallLength >= 1) Tetris.getSpace().spawnTetromino(); - else Tetris.stopGame(); return false; } fallLength += 1; @@ -57,7 +55,7 @@ public class Tetromino { int maxCollisionY = collision.length - 1; while (collision[maxCollisionY][i] == 0) maxCollisionY--; // Figure out the collision box's bounding - if (newPos.getY()+maxCollisionY >= Tetris.getSpace().getMapHeight() || newPos.getX() + i >= Tetris.getSpace().getMapWidth()) continue; + if (newPos.getY()+maxCollisionY < 0 || newPos.getY()+maxCollisionY >= Tetris.getSpace().getMapHeight() || newPos.getX() + i >= Tetris.getSpace().getMapWidth()) continue; collides |= Tetris.getSpace().getGameMap()[newPos.getY() + maxCollisionY][newPos.getX() + i] != null; } } @@ -73,7 +71,7 @@ public class Tetromino { int maxCollisionX = xOffset >= 0 ? collision[i].length - 1 : 0; while (collision[i][maxCollisionX] == 0) maxCollisionX += xOffset >= 0 ? -1 : 1; // Figure out the collision box's bounding - if (newPos.getY()+maxCollisionX >= Tetris.getSpace().getMapHeight()) continue; + if (newPos.getY()+i < 0 || newPos.getY()+i >= Tetris.getSpace().getMapHeight()) continue; collides |= Tetris.getSpace().getGameMap()[newPos.getY() + i][newPos.getX() + maxCollisionX] != null; } } diff --git a/src/main/java/eu/midnightdust/yaytris/ui/ScoreMenu.java b/src/main/java/eu/midnightdust/yaytris/ui/ScoreMenu.java index f69b4cc..818d11a 100644 --- a/src/main/java/eu/midnightdust/yaytris/ui/ScoreMenu.java +++ b/src/main/java/eu/midnightdust/yaytris/ui/ScoreMenu.java @@ -1,11 +1,14 @@ package eu.midnightdust.yaytris.ui; import javax.swing.*; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; public class ScoreMenu extends AbstractMenu { final TetrisUI ui; final JLabel gameOverLabel; final JLabel currentScoreLabel; + final JLabel currentTimeLabel; ScoreMenu(int x, int y, int width, int height, TetrisUI ui) { this.ui = ui; @@ -18,6 +21,9 @@ public class ScoreMenu extends AbstractMenu { this.currentScoreLabel = new JLabel("Score: 0"); this.add(currentScoreLabel); + this.currentTimeLabel = new JLabel("Zeit: 00:00"); + this.add(currentTimeLabel); + JButton backButton = new JButton("Zurück"); backButton.addActionListener(ui::openMainMenu); this.add(backButton); @@ -28,6 +34,14 @@ public class ScoreMenu extends AbstractMenu { this.repaint(); } + public void updateTime(LocalTime startingTime) { + LocalTime timeElapsed = LocalTime.ofNanoOfDay(LocalTime.now().toNanoOfDay() - startingTime.toNanoOfDay()); + + DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(timeElapsed.getHour() > 0 ? "HH:mm:ss" : "mm:ss"); + this.currentTimeLabel.setText("Zeit: %s".formatted(timeFormatter.format(timeElapsed))); + this.repaint(); + } + public void gameOver() { this.gameOverLabel.setText("Game over :("); } diff --git a/src/main/java/eu/midnightdust/yaytris/ui/SettingsMenu.java b/src/main/java/eu/midnightdust/yaytris/ui/SettingsMenu.java index 8445556..cb9a4ef 100644 --- a/src/main/java/eu/midnightdust/yaytris/ui/SettingsMenu.java +++ b/src/main/java/eu/midnightdust/yaytris/ui/SettingsMenu.java @@ -1,6 +1,7 @@ package eu.midnightdust.yaytris.ui; import eu.midnightdust.yaytris.Settings; +import eu.midnightdust.yaytris.util.Difficulty; import javax.swing.*; import java.awt.*; @@ -8,7 +9,7 @@ import java.awt.*; import static eu.midnightdust.yaytris.ui.TetrisUI.scale; import static eu.midnightdust.yaytris.ui.TetrisUI.setFontScale; -public class SettingsMenu extends AbstractMenu { +public class SettingsMenu extends JPanel { final TetrisUI ui; SettingsMenu(int x, int y, int width, int height, TetrisUI ui) { @@ -40,15 +41,31 @@ public class SettingsMenu extends AbstractMenu { }); this.add(scaleSlider); + this.add(new JLabel("Schwierigkeit:")); + JComboBox difficultySelector = new JComboBox<>(Difficulty.values()); + difficultySelector.setSelectedItem(Settings.difficulty); + + difficultySelector.addActionListener(action -> { + Settings.difficulty = (Difficulty) difficultySelector.getSelectedItem(); + Settings.write(); + }); + this.add(difficultySelector); + difficultySelector.setSize(difficultySelector.getBounds().width,scale(10)); + JButton backButton = new JButton("Zurück"); backButton.addActionListener(ui::openMainMenu); this.add(backButton); } + int labelAmount = 0; @Override public Component add(Component comp) { - Component ret = super.add(comp); - if (comp instanceof JLabel) comp.setBounds(scale(60), scale(40+23*(this.getComponentCount()-1)), scale(100), scale(10)); - return ret; + comp.setBounds(scale(60), scale(20+23*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(5)); + labelAmount++; + } + if (comp instanceof JComponent) setFontScale((JComponent) comp); + return super.add(comp); } } diff --git a/src/main/java/eu/midnightdust/yaytris/ui/TetrisUI.java b/src/main/java/eu/midnightdust/yaytris/ui/TetrisUI.java index 84943a8..f762113 100644 --- a/src/main/java/eu/midnightdust/yaytris/ui/TetrisUI.java +++ b/src/main/java/eu/midnightdust/yaytris/ui/TetrisUI.java @@ -95,6 +95,8 @@ public class TetrisUI extends JFrame implements KeyListener { menuPanel.setBackground(CatppuccinColor.BASE.getColor()); menuPanel.setBorder(new LineBorder(CatppuccinColor.SURFACE0.getColor(), scale(2))); this.add(menuPanel); + menuPanel.requestFocus(); + this.transferFocus(); this.repaint(); } diff --git a/src/main/java/eu/midnightdust/yaytris/util/Difficulty.java b/src/main/java/eu/midnightdust/yaytris/util/Difficulty.java index 265d7c3..a145c09 100644 --- a/src/main/java/eu/midnightdust/yaytris/util/Difficulty.java +++ b/src/main/java/eu/midnightdust/yaytris/util/Difficulty.java @@ -1,7 +1,7 @@ package eu.midnightdust.yaytris.util; public enum Difficulty { - NOOB(2000), EASY(1200), NORMAL(1000), HARD(750), EXTREME(100), WTF(30); + NOOB(2000), EASY(1200), NORMAL(1000), HARD(500), EXTREME(100), WTF(30); private final int timerPeriod; Difficulty(int timerPeriod) { diff --git a/tetris_settings.json5 b/tetris_settings.json5 index 14c05c0..3303d9b 100644 --- a/tetris_settings.json5 +++ b/tetris_settings.json5 @@ -1,5 +1,5 @@ { - "musicVolume": 25, + "musicVolume": 50, "soundVolume": 100, "guiScale": 5.0, "difficulty": "NORMAL"