feat: preview of next shape

This commit is contained in:
Martin Prokoph
2025-07-09 13:00:48 +02:00
parent 7671bdec04
commit 7ef6e246ff
9 changed files with 99 additions and 13 deletions

View File

@@ -16,23 +16,27 @@ public class Space {
public Space() {
gameMap = new Color[14][8];
nextShape = getNextShape();
nextShape = generateNextShape();
score = 0;
}
public void spawnTetromino() {
currentTetromino = new Tetromino(nextShape);
nextShape = getNextShape();
nextShape = generateNextShape();
}
public Tetromino getCurrentTetromino() {
return currentTetromino;
}
public TetrominoShape getNextShape() {
public TetrominoShape generateNextShape() {
return TetrominoShape.values()[random.nextInt(TetrominoShape.values().length)];
}
public TetrominoShape getNextShape() {
return nextShape;
}
public int getMapWidth() {
return gameMap[0].length;
}

View File

@@ -41,8 +41,17 @@ public enum TetrominoShape {
final int[][] boundary;
final Color color;
TetrominoShape(int[][] boundary, Color color) {
this.boundary = boundary;
this.color = color;
}
public int[][] getBoundary() {
return boundary;
}
public Color getColor() {
return color;
}
}

View File

@@ -0,0 +1,44 @@
package eu.midnightdust.yaytris.ui;
import eu.midnightdust.yaytris.Tetris;
import eu.midnightdust.yaytris.game.Tetromino;
import eu.midnightdust.yaytris.game.TetrominoShape;
import eu.midnightdust.yaytris.util.FileUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import static eu.midnightdust.yaytris.game.TetrominoShape.T;
public class PreviewCanvas extends JPanel {
final TetrisUI ui;
final BufferedImage texture;
PreviewCanvas(TetrisUI ui) {
this.ui = ui;
this.texture = FileUtil.loadImage("/textures/tetromino.png");
}
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
if (graphics == null) return;
TetrominoShape nextShape = Tetris.getSpace().getNextShape();
for (int y = 0; y < nextShape.getBoundary().length; y++) {
for (int x = 0; x < nextShape.getBoundary()[0].length; x++) {
Color color = nextShape.getBoundary()[y][x] == 0 ? null : nextShape.getColor(); // Get the color of the blob at these coordinates
if (color == null) continue; // Ignore empty cells
int blockSize = (int) Math.ceil((float) (this.getWidth() - this.getInsets().left - this.getInsets().right) / 4);
int startX = x * blockSize + getInsets().left + ((blockSize / 2) * (4 - nextShape.getBoundary()[0].length));
graphics.drawImage(texture, startX, y*blockSize + getInsets().top, blockSize, blockSize, color, this); // Draw out (grayscale) texture
graphics.setColor(withAlpha(color, 120)); // Overlay the texture with the blobs color
graphics.fillRect(startX, y*blockSize + getInsets().top, blockSize, blockSize);
}
}
}
public static Color withAlpha(Color color, int alpha) {
return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
}
}

View File

@@ -1,11 +1,18 @@
package eu.midnightdust.yaytris.ui;
import eu.midnightdust.yaytris.util.CatppuccinColor;
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static eu.midnightdust.yaytris.ui.TetrisUI.scale;
public class ScoreMenu extends AbstractMenu {
final TetrisUI ui;
final PreviewCanvas previewCanvas;
final JLabel gameOverLabel;
final JLabel currentScoreLabel;
final JLabel currentTimeLabel;
@@ -15,6 +22,12 @@ public class ScoreMenu extends AbstractMenu {
this.setBounds(x, y, width, height);
this.setLayout(null);
this.previewCanvas = new PreviewCanvas(ui);
this.previewCanvas.setBounds(scale(92), scale(4), scale(40), scale(40));
this.previewCanvas.setBackground(Color.BLACK);
this.previewCanvas.setBorder(new LineBorder(CatppuccinColor.SURFACE0.getColor()));
this.add(previewCanvas, 0);
this.gameOverLabel = new JLabel();
this.add(gameOverLabel);

View File

@@ -25,7 +25,7 @@ public class SettingsMenu extends JPanel {
});
this.add(musicVolumeSlider);
this.add(new JLabel("Sound-Lautstärke:"));
this.add(new JLabel("Effekt-Lautstärke:"));
JSlider soundVolumeSlider = new JSlider(0, 100, Settings.soundVolume);
soundVolumeSlider.addChangeListener(change -> {
Settings.soundVolume = soundVolumeSlider.getValue();
@@ -33,8 +33,8 @@ public class SettingsMenu extends JPanel {
});
this.add(soundVolumeSlider);
this.add(new JLabel("Skalierung:"));
JSlider scaleSlider = new JSlider(100, 500, (int) (Settings.guiScale * 100));
this.add(new JLabel("Fenster-Skalierung:"));
JSlider scaleSlider = new JSlider(100, 600, (int) (Settings.guiScale * 100));
scaleSlider.addChangeListener(change -> {
Settings.guiScale = scaleSlider.getValue() / 100f;
Settings.write();

View File

@@ -21,7 +21,6 @@ public class TetrisUI extends JFrame implements KeyListener {
JPanel menuPanel;
public TetrisUI() {
Space space = new Space();
this.setLayout(null);
this.setTitle("Tetris");
this.setSize((int) (400 * guiScale), (int) (300 * guiScale));

View File

@@ -1,14 +1,26 @@
package eu.midnightdust.yaytris.util;
public enum Difficulty {
NOOB(2000), EASY(1200), NORMAL(1000), HARD(500), EXTREME(100), WTF(30);
NOOB(2000), EASY(1200), NORMAL(1000), HARD(500), EXTREME(100), WTF(30, "WTF");
private final int timerPeriod;
private final String name;
Difficulty(int timerPeriod) {
this.timerPeriod = timerPeriod;
this.name = this.name().charAt(0) + this.name().substring(1).toLowerCase();
}
Difficulty(int timerPeriod, String name) {
this.timerPeriod = timerPeriod;
this.name = name;
}
public int getTimerPeriod() {
return timerPeriod;
}
@Override
public String toString() {
return this.name;
}
}

View File

@@ -4,6 +4,7 @@ import eu.midnightdust.yaytris.Settings;
import javax.sound.sampled.*;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
@@ -23,7 +24,7 @@ public class SoundUtil {
// Adapted from: https://www.baeldung.com/java-play-sound
public static void playSoundClip(String fileLocation) {
try (AudioInputStream stream = AudioSystem.getAudioInputStream(SoundUtil.class.getResource(fileLocation))) { // FIXME: Support audio files from JAR. File streams won't work here for some reason.
try (AudioInputStream stream = AudioSystem.getAudioInputStream(getResource(fileLocation))) { // FIXME: Support audio files from JAR. File streams won't work here for some reason.
AudioFormat format = stream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
@@ -37,6 +38,10 @@ public class SoundUtil {
}
}
private static URL getResource(String fileLocation) {
return SoundUtil.class.getResource(fileLocation);
}
// Adapted from: https://stackoverflow.com/a/40698149
private static void setVolume(Line line, int volume) {
if (volume < 0 || volume > 100)
@@ -68,7 +73,7 @@ public class SoundUtil {
// Adapted from: https://www.baeldung.com/java-play-sound
private void playMusic(String fileLocation) {
try (AudioInputStream stream = AudioSystem.getAudioInputStream(SoundUtil.class.getResource(fileLocation))) {
try (AudioInputStream stream = AudioSystem.getAudioInputStream(getResource(fileLocation))) {
AudioFormat format = stream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

View File

@@ -1,6 +1,6 @@
{
"musicVolume": 50,
"musicVolume": 100,
"soundVolume": 100,
"guiScale": 5.0,
"difficulty": "NORMAL"
"guiScale": 6.0,
"difficulty": "Normal"
}