Skip to content
Snippets Groups Projects
Commit b63aed0c authored by Brady James Garvin's avatar Brady James Garvin
Browse files

Initial commit.

parents
No related branches found
No related tags found
No related merge requests found
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.unl.cse.soft160.tetris</groupId>
<artifactId>tetris</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>tetris</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package edu.unl.cse.soft160.tetris;
import java.util.Collections;
import java.util.ArrayList;
import java.awt.Font;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Tetris extends JFrame {
private static final long serialVersionUID = -6851893161385783635L;
protected static int mod(int value, int modulus) {
int result = value % modulus;
return result < 0 ? result + modulus : result;
}
protected static final int DEFAULT_SQUARE_SIZE = 60; // pixels
protected static final Font TEXT_FONT = new Font(Font.SANS_SERIF, Font.BOLD, DEFAULT_SQUARE_SIZE / 2);
protected static final Color TEXT_COLOR = new Color(255, 255, 255, 127);
protected static final String ROWS_CLEARED = "Rows cleared";
protected static final String FINAL_SCORE = "Final score";
protected static final String SCORE_SEPARATOR = ": ";
protected static final int ROTATE_LEFT = KeyEvent.VK_DOWN;
protected static final int ROTATE_RIGHT = KeyEvent.VK_UP;
protected static final int SHIFT_LEFT = KeyEvent.VK_LEFT;
protected static final int SHIFT_RIGHT = KeyEvent.VK_RIGHT;
protected static final int DROP = KeyEvent.VK_SPACE;
protected static final int PAUSE = KeyEvent.VK_P;
protected static final int NEW_GAME = KeyEvent.VK_N;
protected static final int WIDTH = 7; // squares
protected static final int HEIGHT = 11; // squares
protected static final int START_Y = 1; // squares from top
protected static final Color EMPTY = new Color(0, 0, 0);
protected static final Color[] COLORS = { new Color(0, 0, 204), new Color(142, 0, 204), new Color(204, 204, 0),
new Color(204, 0, 204), new Color(0, 204, 204), new Color(0, 204, 0), new Color(204, 0, 0), };
protected static final int[] SHAPE_WIDTHS = { 2, 3, 3, 3, 3, 3, 4, };
protected static final int[][][][] SHAPES = {
{ // O
{ { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }, },
{ // L
{ { 0, 0 }, { 1, 0 }, { 2, 0 }, { 2, 1 } }, { { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, 1 } },
{ { 0, -1 }, { 0, 0 }, { 1, 0 }, { 2, 0 } }, { { 1, -1 }, { 2, -1 }, { 1, 0 }, { 1, 1 } }, },
{ // J
{ { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 } }, { { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } },
{ { 2, -1 }, { 0, 0 }, { 1, 0 }, { 2, 0 } }, { { 1, -1 }, { 1, 0 }, { 1, 1 }, { 2, 1 } }, },
{ // S
{ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 2, 1 } }, { { 1, 0 }, { 0, 1 }, { 1, 1 }, { 0, 2 } }, },
{ // Z
{ { 1, 0 }, { 2, 0 }, { 0, 1 }, { 1, 1 } }, { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 1, 2 } }, },
{ // T
{ { 1, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }, { { 1, 0 }, { 1, 1 }, { 2, 1 }, { 1, 2 } },
{ { 0, 1 }, { 1, 1 }, { 2, 1 }, { 1, 2 } }, { { 1, 0 }, { 0, 1 }, { 1, 1 }, { 1, 2 } }, },
{ // I
{ { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 } }, { { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 } }, }, };
protected Color[][] board;
protected int score;
protected boolean isOccupied(int x, int y) {
return x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT || board[x][y] != EMPTY;
}
protected void emptyBoard() {
board = new Color[WIDTH][HEIGHT];
for (int x = 0; x < WIDTH; ++x) {
for (int y = 0; y < HEIGHT; ++y) {
board[x][y] = EMPTY;
}
}
}
protected void clearRows() {
int fallTo = HEIGHT - 1;
for (int y = HEIGHT; y-- > 0;) {
boolean full = true;
for (int x = 0; x < WIDTH; ++x) {
if (board[x][y] == EMPTY) {
full = false;
break;
}
}
if (full) {
++score;
} else {
for (int x = 0; x < WIDTH; ++x) {
board[x][fallTo] = board[x][y];
}
--fallTo;
}
}
for (int x = 0; x < WIDTH; ++x) {
for (int y = fallTo; y >= 0; --y) {
board[x][y] = EMPTY;
}
}
}
protected long getDelay() {
return 20000 / (score + 50);
}
protected ArrayList<Integer> currentShuffle = new ArrayList<Integer>();
protected int currentShuffleIndex;
protected int nextShape() {
if (currentShuffleIndex >= currentShuffle.size()) {
currentShuffleIndex = 0;
currentShuffle.clear();
for (int i = 0; i < SHAPES.length; ++i) {
currentShuffle.add(i);
}
Collections.shuffle(currentShuffle);
}
return currentShuffle.get(currentShuffleIndex++);
}
protected int shape;
protected int orientation;
protected int x;
protected int y;
protected void createShape() {
shape = nextShape();
orientation = 0;
x = (WIDTH - SHAPE_WIDTHS[shape]) / 2;
y = START_Y;
}
protected int[][] getFallingSquares() {
int[][] result = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
int[][][] entry = SHAPES[shape];
int[][] offsets = entry[mod(orientation, entry.length)];
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 2; ++j) {
result[i][j] = (j == 0 ? x : y) + offsets[i][j];
}
}
return result;
}
protected boolean shapeCollides() {
for (int[] square : getFallingSquares()) {
if (isOccupied(square[0], square[1])) {
return true;
}
}
return false;
}
protected void drawShape(Color color) {
for (int[] square : getFallingSquares()) {
board[square[0]][square[1]] = color;
}
}
protected void placeShape() {
drawShape(COLORS[shape]);
repaint();
}
protected void unplaceShape() {
drawShape(EMPTY);
}
protected boolean playing = false;
protected boolean paused = false;
protected boolean isPlaying() {
return playing && !paused;
}
protected void togglePause() {
paused = !paused;
}
protected void beginGame() {
emptyBoard();
createShape();
placeShape();
score = 0;
playing = true;
paused = false;
}
protected void endGame() {
playing = false;
}
protected boolean maybeAdjustShape(int rotation, int dx, int dy) {
if (!isPlaying()) {
return true;
}
unplaceShape();
orientation += rotation;
x += dx;
y += dy;
boolean collides = shapeCollides();
if (collides) {
orientation -= rotation;
x -= dx;
y -= dy;
}
placeShape();
return collides;
}
protected boolean sinkShape() {
if (!isPlaying()) {
return true;
}
if (maybeAdjustShape(0, 0, 1)) {
clearRows();
createShape();
if (shapeCollides()) {
endGame();
} else {
placeShape();
}
return true;
}
return false;
}
protected void dropShape() {
while (!sinkShape())
;
}
protected void rotateShapeLeft() {
maybeAdjustShape(-1, 0, 0);
}
protected void rotateShapeRight() {
maybeAdjustShape(1, 0, 0);
}
protected void shiftShapeLeft() {
maybeAdjustShape(0, -1, 0);
}
protected void shiftShapeRight() {
maybeAdjustShape(0, 1, 0);
}
@Override
public void paint(Graphics graphics) {
super.paint(graphics);
int xScale = getWidth() / WIDTH;
int yScale = getHeight() / HEIGHT;
for (int x = 0; x < WIDTH; ++x) {
for (int y = 0; y < HEIGHT; ++y) {
graphics.setColor(board[x][y]);
graphics.fillRect(xScale * x, yScale * y, xScale, yScale);
}
}
String scoreString = (playing ? ROWS_CLEARED : FINAL_SCORE) + SCORE_SEPARATOR + String.valueOf(score);
graphics.setFont(TEXT_FONT);
graphics.setColor(TEXT_COLOR);
graphics.drawString(scoreString, (getWidth() - graphics.getFontMetrics().stringWidth(scoreString)) / 2,
(getHeight() / 2 - graphics.getFontMetrics().getHeight()) / 2);
}
public Tetris(int width, int height) {
super("Tetris");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(width, height);
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent event) {
switch (event.getKeyCode()) {
case ROTATE_LEFT:
rotateShapeLeft();
break;
case ROTATE_RIGHT:
rotateShapeRight();
break;
case SHIFT_LEFT:
shiftShapeLeft();
break;
case SHIFT_RIGHT:
shiftShapeRight();
break;
case DROP:
dropShape();
break;
case PAUSE:
togglePause();
break;
case NEW_GAME:
if (playing) {
endGame();
}
beginGame();
break;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
});
new Thread() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(getDelay());
sinkShape();
} catch (InterruptedException ignored) {
}
}
}
}.start();
}
public static void main(String... arguments) {
Tetris tetris = new Tetris(WIDTH * DEFAULT_SQUARE_SIZE, HEIGHT * DEFAULT_SQUARE_SIZE);
tetris.setVisible(true);
tetris.beginGame();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment