Skip to content

Commit

Permalink
Add locales
Browse files Browse the repository at this point in the history
  • Loading branch information
salif committed Jul 21, 2024
1 parent b013de6 commit 90782e9
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 109 deletions.
8 changes: 7 additions & 1 deletion app/src/main/java/com/github/salif/tetris/App.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package com.github.salif.tetris;

import java.util.Locale;
import java.util.ResourceBundle;

import javax.swing.SwingUtilities;

public class App {

public static void main(String[] args) {
new GameWindow();
SwingUtilities.invokeLater(new GameWindow(ResourceBundle.getBundle("m", Locale.getDefault())));
}
}
132 changes: 59 additions & 73 deletions app/src/main/java/com/github/salif/tetris/GameBoardPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ResourceBundle;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;

import com.github.salif.tetris.Tetromino.Tetrominoes;

public class GameBoardPanel extends JPanel implements ActionListener {

private static final long serialVersionUID = 6802492405004738658L;
private static final int BoardWidth = 10; // game board x size
private static final int BoardHeight = 22; // game board y size
private final int BoardWidth = 10; // game board x size
private final int BoardHeight = 22; // game board y size

// game status & timer
private Timer timer;
Expand All @@ -43,27 +43,29 @@ public class GameBoardPanel extends JPanel implements ActionListener {
private String currentLevel;
private int currentTimerResolution;

public GameBoardPanel(GameWindow tetrisFrame, int timerResolution) {
private final ResourceBundle m;

public GameBoardPanel(GameWindow tetrisFrame, ResourceBundle m, int timerResolution) {
setFocusable(true);
setBackground(new Color(0, 30, 30));
curBlock = new Tetromino();
timer = new Timer(timerResolution, this);
timer.start(); // activate timer
currentTimerResolution = timerResolution;
this.m = m;

gameBoard = new Tetrominoes[BoardWidth * BoardHeight];

// colour of tetrominoes
colorTable = new Color[] {
new Color(0, 0, 0),
new Color(164, 135, 255),
new Color(255, 128, 0),
new Color(255, 0, 0),
new Color(32, 128, 255),
new Color(255, 0, 255),
new Color(255, 255, 0),
new Color(0, 255, 0)
colorTable = new Color[]{
new Color(0, 0, 0),
new Color(164, 135, 255),
new Color(255, 128, 0),
new Color(255, 0, 0),
new Color(32, 128, 255),
new Color(255, 0, 255),
new Color(255, 255, 0),
new Color(0, 255, 0)
};

// keyboard listener
Expand All @@ -85,34 +87,20 @@ public void keyPressed(KeyEvent e) {
return;
}

// Colemak
switch (keycode) {
case 'a':
case 'A':
case KeyEvent.VK_LEFT:
case 'a', 'A', KeyEvent.VK_LEFT ->
isMovable(curBlock, curX - 1, curY);
break;
case 'd':
case 'D':
case KeyEvent.VK_RIGHT:
case 's', 'S', KeyEvent.VK_RIGHT ->
isMovable(curBlock, curX + 1, curY);
break;
case 'w':
case 'W':
case KeyEvent.VK_UP:
case 'w', 'W', KeyEvent.VK_UP ->
isMovable(curBlock.rotateRight(), curX, curY);
break;
case 's':
case 'S':
case KeyEvent.VK_DOWN:
case 'r', 'R', KeyEvent.VK_DOWN ->
advanceOneLine();
break;
case KeyEvent.VK_SPACE:
case KeyEvent.VK_SPACE ->
advanceToEnd();
break;
case 'p':
case 'P':
case 'p', 'P' ->
pause();
break;
}

}
Expand All @@ -126,36 +114,26 @@ private void setResolution() {
// fix me later! it's lame :P"

switch (currentScore / 10) {
case 10:
case 10 ->
currentTimerResolution = 100;
break;
case 9:
currentTimerResolution = 130;
break;
case 8:
currentTimerResolution = 160;
break;
case 7:
currentTimerResolution = 190;
break;
case 6:
case 9 ->
currentTimerResolution = 140;
case 8 ->
currentTimerResolution = 180;
case 7 ->
currentTimerResolution = 220;
break;
case 5:
currentTimerResolution = 250;
break;
case 4:
currentTimerResolution = 280;
break;
case 3:
currentTimerResolution = 310;
break;
case 2:
case 6 ->
currentTimerResolution = 260;
case 5 ->
currentTimerResolution = 300;
case 4 ->
currentTimerResolution = 340;
break;
case 1:
currentTimerResolution = 370;
break;
case 3 ->
currentTimerResolution = 380;
case 2 ->
currentTimerResolution = 420;
case 1 ->
currentTimerResolution = 460;
}

timer.setDelay(currentTimerResolution);
Expand Down Expand Up @@ -229,10 +207,10 @@ public void paint(Graphics g) {
super.paint(g);

if (!isPaused) {
currentStatus = "Score: " + currentScore;
currentLevel = "Level: " + (currentScore / 10 + 1);
currentStatus = this.m.getString("score") + ": " + currentScore;
currentLevel = this.m.getString("level") + ": " + (currentScore / 10 + 1);
} else {
currentStatus = "PAUSED";
currentStatus = this.m.getString("paused");
currentLevel = "";
}

Expand All @@ -247,8 +225,9 @@ public void paint(Graphics g) {
// rendering - shadow of tetromino
int tempY = curY;
while (tempY > 0) {
if (!atomIsMovable(curBlock, curX, tempY - 1, false))
if (!atomIsMovable(curBlock, curX, tempY - 1, false)) {
break;
}
tempY--;
}
for (int i = 0; i < 4; i++) {
Expand All @@ -263,8 +242,9 @@ public void paint(Graphics g) {
for (int i = 0; i < BoardHeight; i++) {
for (int j = 0; j < BoardWidth; j++) {
Tetrominoes shape = curTetrominoPos(j, BoardHeight - i - 1);
if (shape != Tetrominoes.NO_BLOCK)
if (shape != Tetrominoes.NO_BLOCK) {
drawTetromino(g, 0 + j * blockWidth(), boardTop + i * blockHeight(), shape, false);
}
}
}

Expand Down Expand Up @@ -308,8 +288,9 @@ private void removeFullLines() {
if (isFull) {
++fullLines;
for (int k = i; k < BoardHeight - 1; k++) {
for (int l = 0; l < BoardWidth; ++l)
for (int l = 0; l < BoardWidth; ++l) {
gameBoard[(k * BoardWidth) + l] = curTetrominoPos(l, k + 1);
}
}
}
}
Expand All @@ -330,8 +311,9 @@ private boolean atomIsMovable(Tetromino chkBlock, int chkX, int chkY, boolean fl
for (int i = 0; i < 4; i++) {
int x = chkX + chkBlock.getX(i);
int y = chkY - chkBlock.getY(i);
if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight) {
return false;
}
if (curTetrominoPos(x, y) != Tetrominoes.NO_BLOCK) {
return false;
}
Expand Down Expand Up @@ -360,7 +342,7 @@ private void newTetromino() {
curBlock.setShape(Tetrominoes.NO_BLOCK);
timer.stop();
isStarted = false;
gameOver(currentScore);
gameOver();
}
}

Expand All @@ -387,15 +369,19 @@ private void advanceOneLine() {
private void advanceToEnd() {
int tempY = curY;
while (tempY > 0) {
if (!isMovable(curBlock, curX, tempY - 1))
if (!isMovable(curBlock, curX, tempY - 1)) {
break;
}
--tempY;
}
tetrominoFixed();
}

private void gameOver(int score) {
JOptionPane.showMessageDialog(null, "", "Game Over!", JOptionPane.OK_OPTION);
private void gameOver() {
int r = JOptionPane.showConfirmDialog(this, this.currentStatus + "\n" + this.currentLevel + "\n" + this.m.getString("restart"), this.m.getString("gameover"), JOptionPane.YES_NO_OPTION);
if (r == JOptionPane.YES_OPTION) {
start();
}
}

}
33 changes: 20 additions & 13 deletions app/src/main/java/com/github/salif/tetris/GameWindow.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
package com.github.salif.tetris;

import java.awt.GridLayout;
import java.util.ResourceBundle;

import javax.swing.JFrame;

public class GameWindow extends JFrame {
public class GameWindow implements Runnable {

private static final long serialVersionUID = 8737819995837542594L;
private final JFrame mainFrame;
private final GameBoardPanel gameBoard;

public GameWindow() {
setTitle("Tetris :D");
setSize(400, 814);
setResizable(false);
public GameWindow(ResourceBundle m) {
this.mainFrame = new JFrame();
this.mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.mainFrame.setTitle(m.getString("title"));
this.mainFrame.setSize(400, 814);
this.mainFrame.setResizable(false);

setLayout(new GridLayout(1, 2));
this.mainFrame.setLayout(new GridLayout(1, 2));

// you can adjust timer resolution here. but it's ideal value for this game.
GameBoardPanel gameBoard = new GameBoardPanel(this, 400);
add(gameBoard);
gameBoard.start();
this.gameBoard = new GameBoardPanel(this, m, 500);
this.mainFrame.add(gameBoard);
}

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
@Override
public void run() {
this.mainFrame.setLocationRelativeTo(null);
this.mainFrame.setVisible(true);
this.gameBoard.start();
}
}
39 changes: 17 additions & 22 deletions app/src/main/java/com/github/salif/tetris/Tetromino.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,32 @@
import java.util.Random;

public class Tetromino {
enum Tetrominoes {
NO_BLOCK, Z_SHAPE, S_SHAPE, I_SHAPE, T_SHAPE, O_SHAPE, L_SHAPE, J_SHAPE
};

private Tetrominoes tetrominoes;
private int coords[][]; // current shape of a tetromino
private int tetrominoTable[][][];
private final int coords[][]; // current shape of a tetromino
private final int tetrominoTable[][][];

public Tetromino() {
coords = new int[4][2];
tetrominoTable = new int[][][] {
{ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // NO_BLOCK
{ { 0, -1 }, { 0, 0 }, { -1, 0 }, { -1, 1 } }, // Z_SHAPE
{ { 0, -1 }, { 0, 0 }, { 1, 0 }, { 1, 1 } }, // S_SHAPE
{ { 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 } }, // I_SHAPE
{ { -1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 1 } }, // T_SHAPE
{ { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }, // O_SHAPE
{ { -1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } }, // L_SHAPE
{ { 1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } } // J_SHAPE
tetrominoTable = new int[][][]{
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, // NO_BLOCK
{{0, -1}, {0, 0}, {-1, 0}, {-1, 1}}, // Z_SHAPE
{{0, -1}, {0, 0}, {1, 0}, {1, 1}}, // S_SHAPE
{{0, -1}, {0, 0}, {0, 1}, {0, 2}}, // I_SHAPE
{{-1, 0}, {0, 0}, {1, 0}, {0, 1}}, // T_SHAPE
{{0, 0}, {1, 0}, {0, 1}, {1, 1}}, // O_SHAPE
{{-1, -1}, {0, -1}, {0, 0}, {0, 1}}, // L_SHAPE
{{1, -1}, {0, -1}, {0, 0}, {0, 1}} // J_SHAPE
};

setShape(Tetrominoes.NO_BLOCK);
}

// set tetromino shape
public void setShape(Tetrominoes tetromino) {
final void setShape(Tetrominoes tetromino) {

for (int i = 0; i < coords.length; i++) {
for (int j = 0; j < coords[i].length; j++) {
coords[i][j] = tetrominoTable[tetromino.ordinal()][i][j];
}
System.arraycopy(tetrominoTable[tetromino.ordinal()][i], 0, coords[i], 0, coords[i].length);
}

tetrominoes = tetromino;
Expand Down Expand Up @@ -68,16 +63,16 @@ public int getY(int idx) {

public int minX() {
int ret = 0;
for (int i = 0; i < coords.length; i++) {
ret = Math.min(ret, coords[i][0]);
for (int[] coord : coords) {
ret = Math.min(ret, coord[0]);
}
return ret;
}

public int minY() {
int ret = 0;
for (int i = 0; i < coords.length; i++) {
ret = Math.min(ret, coords[i][1]);
for (int[] coord : coords) {
ret = Math.min(ret, coord[1]);
}
return ret;
}
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/com/github/salif/tetris/Tetrominoes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.github.salif.tetris;

public enum Tetrominoes {
NO_BLOCK, Z_SHAPE, S_SHAPE, I_SHAPE, T_SHAPE, O_SHAPE, L_SHAPE, J_SHAPE
};
6 changes: 6 additions & 0 deletions app/src/main/resources/m.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
title=Tetris :D
score=Score
level=Level
paused=PAUSED
gameover=Game over!
restart=Play again?
Loading

0 comments on commit 90782e9

Please sign in to comment.