Implement all Tetris basic functions.
This commit is contained in:
parent
880a56ddca
commit
e533edac08
@ -11,4 +11,7 @@ public class Block {
|
|||||||
this.active=active;
|
this.active=active;
|
||||||
this.color=col;
|
this.color=col;
|
||||||
}
|
}
|
||||||
|
public String toString() {
|
||||||
|
return active?"O":"-";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package sig.game;
|
package sig.game;
|
||||||
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
@ -16,6 +17,11 @@ public class Game {
|
|||||||
public static int rotation = 0; //0-3
|
public static int rotation = 0; //0-3
|
||||||
public static Grid gameGrid = new Grid();
|
public static Grid gameGrid = new Grid();
|
||||||
|
|
||||||
|
public static int rotateDelay = 20;
|
||||||
|
public static int rotateTimer = rotateDelay;
|
||||||
|
|
||||||
|
public static GameState state = GameState.PLAYING;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
final Frame LPiece = new Frame(
|
final Frame LPiece = new Frame(
|
||||||
@ -26,8 +32,8 @@ public class Game {
|
|||||||
+ "XXXX"),
|
+ "XXXX"),
|
||||||
new Shape(
|
new Shape(
|
||||||
"XXXX"
|
"XXXX"
|
||||||
+ "OOOO"
|
+ "XOOO"
|
||||||
+ "OXXX"
|
+ "XOXX"
|
||||||
+ "XXXX"),
|
+ "XXXX"),
|
||||||
new Shape(
|
new Shape(
|
||||||
"XOOX"
|
"XOOX"
|
||||||
@ -36,8 +42,8 @@ public class Game {
|
|||||||
+ "XXXX"),
|
+ "XXXX"),
|
||||||
new Shape(
|
new Shape(
|
||||||
"XXXX"
|
"XXXX"
|
||||||
+ "XXXO"
|
+ "XXOX"
|
||||||
+ "OOOO"
|
+ "OOOX"
|
||||||
+ "XXXX")
|
+ "XXXX")
|
||||||
,Color.ORANGE);
|
,Color.ORANGE);
|
||||||
final Frame JPiece = new Frame(
|
final Frame JPiece = new Frame(
|
||||||
@ -47,8 +53,8 @@ public class Game {
|
|||||||
+ "XOOX"
|
+ "XOOX"
|
||||||
+ "XXXX"),
|
+ "XXXX"),
|
||||||
new Shape(
|
new Shape(
|
||||||
"OXXX"
|
"XOXX"
|
||||||
+ "OOOO"
|
+ "XOOO"
|
||||||
+ "XXXX"
|
+ "XXXX"
|
||||||
+ "XXXX"),
|
+ "XXXX"),
|
||||||
new Shape(
|
new Shape(
|
||||||
@ -57,8 +63,8 @@ public class Game {
|
|||||||
+ "XOOX"
|
+ "XOOX"
|
||||||
+ "XXXX"),
|
+ "XXXX"),
|
||||||
new Shape(
|
new Shape(
|
||||||
"OOOO"
|
"OOOX"
|
||||||
+ "XXXO"
|
+ "XXOX"
|
||||||
+ "XXXX"
|
+ "XXXX"
|
||||||
+ "XXXX")
|
+ "XXXX")
|
||||||
,Color.BLUE);
|
,Color.BLUE);
|
||||||
@ -193,12 +199,22 @@ public class Game {
|
|||||||
|
|
||||||
static void step() {
|
static void step() {
|
||||||
tickDelay--;
|
tickDelay--;
|
||||||
|
rotateTimer--;
|
||||||
if (tickDelay<=0) {
|
if (tickDelay<=0) {
|
||||||
moveBlock();
|
moveBlock();
|
||||||
tickDelay=levelDelay[level];
|
tickDelay=levelDelay[level];
|
||||||
}
|
}
|
||||||
|
if (rotateTimer<=0) {
|
||||||
|
//p.rotateCounterClockwise();
|
||||||
|
p.moveBlockLeft();
|
||||||
|
rotateTimer=rotateDelay;
|
||||||
|
}
|
||||||
|
DrawBoard();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawBoard() {
|
||||||
ClearScreen();
|
ClearScreen();
|
||||||
Point[] checkPoints = p.GetPlayerBlocksInGrid();
|
Point[] checkPoints = p.GetPlayerBlocksInGrid(p.getCurrentShape());
|
||||||
for (int y=19;y>=0;y--) {
|
for (int y=19;y>=0;y--) {
|
||||||
for (int x=0;x<10;x++) {
|
for (int x=0;x<10;x++) {
|
||||||
boolean plotted=false;
|
boolean plotted=false;
|
||||||
@ -210,7 +226,7 @@ public class Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!plotted) {
|
if (!plotted) {
|
||||||
System.out.print((gameGrid.grid[x][y].active)?'O':'-');
|
System.out.print(gameGrid.grid[x][y]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println();
|
System.out.println();
|
||||||
@ -236,25 +252,88 @@ public class Game {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
Point[] checkPoints = p.GetPlayerBlocksInGrid();
|
Point[] checkPoints = p.GetPlayerBlocksInGrid(p.getCurrentShape());
|
||||||
|
|
||||||
|
boolean isOccupied = isOccupied(checkPoints,new Point(0,-1));
|
||||||
|
|
||||||
|
if (isOccupied) {
|
||||||
|
SnapPieceThatCollided(checkPoints);
|
||||||
|
ClearLinesThatHaveFullRows();
|
||||||
|
} else {
|
||||||
|
MovePlayerBlockDownByOne();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ClearLinesThatHaveFullRows() {
|
||||||
|
int deletionRows=0;
|
||||||
|
for (int y=0;y<gameGrid.grid[0].length;y++) {
|
||||||
|
//System.out.println("Called: "+y);
|
||||||
|
deletionRows = CheckAndClearFullRows(deletionRows, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int CheckAndClearFullRows(int deletionRows, int y) {
|
||||||
|
boolean isAllActive=true;
|
||||||
|
for (int x=0;x<gameGrid.grid.length;x++) {
|
||||||
|
//System.out.print(gameGrid.grid[x][y]);
|
||||||
|
if (!gameGrid.grid[x][y].active) {
|
||||||
|
isAllActive=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//System.out.println();
|
||||||
|
if (isAllActive) {
|
||||||
|
//Take every block above this row, and shift it all down by one.
|
||||||
|
//x is the current row we are on.
|
||||||
|
//Move every row down, if we find a row that is also a match, increment the amount of rows we move down by 1.
|
||||||
|
deletionRows++;
|
||||||
|
} else {
|
||||||
|
for (int x=0;x<gameGrid.grid.length;x++) {
|
||||||
|
ShiftBlockDownByNumberOfDeletionRows(deletionRows, y, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deletionRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ShiftBlockDownByNumberOfDeletionRows(int deletionRows, int y, int x) {
|
||||||
|
if (deletionRows>0) {
|
||||||
|
gameGrid.grid[x][y-deletionRows].active=gameGrid.grid[x][y].active;
|
||||||
|
gameGrid.grid[x][y].active=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MovePlayerBlockDownByOne() {
|
||||||
|
p.pos.translate(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SnapPieceThatCollided(Point[] checkPoints) {
|
||||||
|
for (Point point : checkPoints) {
|
||||||
|
//If any point in the grid is outside, this is our lose condition.
|
||||||
|
if (point.y>=gameGrid.grid[0].length) {
|
||||||
|
state = GameState.LOSE;
|
||||||
|
}
|
||||||
|
gameGrid.grid[point.x][point.y].active=true;
|
||||||
|
}
|
||||||
|
p.ShuffleNextPiece();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isOccupied(Point[] checkPoints) {
|
||||||
|
return isOccupied(checkPoints,new Point(0,0));
|
||||||
|
}
|
||||||
|
static boolean isOccupied(Point[] checkPoints,Point offset) {
|
||||||
boolean isOccupied = false;
|
boolean isOccupied = false;
|
||||||
for (int i=0;i<checkPoints.length;i++) {
|
for (int i=0;i<checkPoints.length;i++) {
|
||||||
Point point = checkPoints[i];
|
Point point = checkPoints[i];
|
||||||
//point.translate(p.pos.x,p.pos.y);
|
//point.translate(p.pos.x,p.pos.y);
|
||||||
if (point.y-1<0 || gameGrid.grid[point.x][point.y-1].active) {
|
if (point.y+offset.y<0 ||
|
||||||
|
point.y+offset.y>=gameGrid.grid[0].length||
|
||||||
|
point.x+offset.x>=gameGrid.grid.length||
|
||||||
|
point.x+offset.x<0
|
||||||
|
|| gameGrid.grid[point.x+offset.x][point.y+offset.y].active) {
|
||||||
isOccupied=true;
|
isOccupied=true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return isOccupied;
|
||||||
if (isOccupied) {
|
|
||||||
for (Point point : checkPoints) {
|
|
||||||
gameGrid.grid[point.x][point.y].active=true;
|
|
||||||
}
|
|
||||||
p.ShuffleNextPiece();
|
|
||||||
} else {
|
|
||||||
p.pos.translate(0, -1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
Tetris/src/sig/game/GameState.java
Normal file
7
Tetris/src/sig/game/GameState.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sig.game;
|
||||||
|
|
||||||
|
public enum GameState {
|
||||||
|
PLAYING,
|
||||||
|
WIN,
|
||||||
|
LOSE;
|
||||||
|
}
|
12
Tetris/src/sig/game/MoveDirection.java
Normal file
12
Tetris/src/sig/game/MoveDirection.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package sig.game;
|
||||||
|
|
||||||
|
public enum MoveDirection {
|
||||||
|
LEFT(-1),
|
||||||
|
RIGHT(1);
|
||||||
|
|
||||||
|
int value;
|
||||||
|
|
||||||
|
MoveDirection(int value) {
|
||||||
|
this.value=value;
|
||||||
|
}
|
||||||
|
}
|
@ -17,19 +17,15 @@ public class Player {
|
|||||||
pos = new Point(5,20);
|
pos = new Point(5,20);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Frame SelectRandomTetrimino() {
|
|
||||||
return Game.piecePool[(int)(Math.random()*Game.piecePool.length)];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShuffleNextPiece() {
|
public void ShuffleNextPiece() {
|
||||||
piece = nextPiece.clone();
|
piece = nextPiece.clone();
|
||||||
nextPiece = SelectRandomTetrimino();
|
nextPiece = SelectRandomTetrimino();
|
||||||
pos = new Point(5,20);
|
pos = new Point(5,20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Point[] GetPlayerBlocksInGrid() {
|
public Point[] GetPlayerBlocksInGrid(Shape s) {
|
||||||
Point[] checkPoints = new Point[4];
|
Point[] checkPoints = new Point[4];
|
||||||
Shape tetShape = piece.shape[Game.rotation];
|
Shape tetShape = s;
|
||||||
int pointsInserted=0;
|
int pointsInserted=0;
|
||||||
for (int x=0;x<tetShape.shape.length;x++) {
|
for (int x=0;x<tetShape.shape.length;x++) {
|
||||||
for (int y=0;y<tetShape.shape[0].length;y++) {
|
for (int y=0;y<tetShape.shape[0].length;y++) {
|
||||||
@ -42,4 +38,89 @@ public class Player {
|
|||||||
}
|
}
|
||||||
return checkPoints;
|
return checkPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Shape getCurrentShape() {
|
||||||
|
return piece.shape[Game.rotation];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotateClockwise() {
|
||||||
|
//Get the new rotated piece.
|
||||||
|
//See if the current piece position with the new rotation shape overlaps any active squares.
|
||||||
|
//If they do, try to shift the piece one left, and compare again.
|
||||||
|
//If they still do, try to shift the piece one right, and compare again.
|
||||||
|
//If no piece position is free, we cannot rotate. Return.
|
||||||
|
//Otherwise, all conditions have been met, and we can rotate the piece.
|
||||||
|
Point[] checkPoints = GetPlayerBlocksInGrid(GetClockwiseRotatedCurrentPiece());
|
||||||
|
RotateIfSpaceIsFree(checkPoints,RotationDirection.CLOCKWISE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotateCounterClockwise() {
|
||||||
|
Point[] checkPoints = GetPlayerBlocksInGrid(GetCounterClockwiseRotatedCurrentPiece());
|
||||||
|
RotateIfSpaceIsFree(checkPoints,RotationDirection.COUNTERCLOCKWISE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveBlockRight() {
|
||||||
|
moveBlock(MoveDirection.RIGHT);
|
||||||
|
}
|
||||||
|
public void moveBlockLeft() {
|
||||||
|
moveBlock(MoveDirection.LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void moveBlock(MoveDirection dir) {
|
||||||
|
Point[] checkPoints = GetPlayerBlocksInGrid(getCurrentShape());
|
||||||
|
boolean isFree = true;
|
||||||
|
for (Point p : checkPoints) {
|
||||||
|
if (Game.isOccupied(checkPoints,new Point(dir.value,0))) {
|
||||||
|
isFree=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isFree) {
|
||||||
|
pos.translate(dir.value, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Frame SelectRandomTetrimino() {
|
||||||
|
return Game.piecePool[(int)(Math.random()*Game.piecePool.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RotateIfSpaceIsFree(Point[] checkPoints,RotationDirection dir) {
|
||||||
|
int[] offset = new int[]{0,-1,1};
|
||||||
|
int freeOffset = -1;
|
||||||
|
for (int i=0;i<offset.length;i++) {
|
||||||
|
if (!Game.isOccupied(checkPoints,new Point(offset[i],0))) {
|
||||||
|
freeOffset = offset[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (freeOffset!=-1) {
|
||||||
|
pos.translate(freeOffset, 0);
|
||||||
|
Game.rotation=rotatePiece(Game.rotation,dir);
|
||||||
|
//System.out.println("rotation: "+Game.rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Shape GetClockwiseRotatedCurrentPiece() {
|
||||||
|
return piece.shape[rotatePiece(Game.rotation,RotationDirection.CLOCKWISE)];
|
||||||
|
}
|
||||||
|
private Shape GetCounterClockwiseRotatedCurrentPiece() {
|
||||||
|
return piece.shape[rotatePiece(Game.rotation,RotationDirection.COUNTERCLOCKWISE)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rotatePiece(int currentRotation,RotationDirection direction) {
|
||||||
|
currentRotation+=direction.value;
|
||||||
|
if (currentRotation<0) {
|
||||||
|
currentRotation=3;
|
||||||
|
} else
|
||||||
|
if (currentRotation>3) {
|
||||||
|
currentRotation=0;
|
||||||
|
}
|
||||||
|
return currentRotation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
12
Tetris/src/sig/game/RotationDirection.java
Normal file
12
Tetris/src/sig/game/RotationDirection.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package sig.game;
|
||||||
|
|
||||||
|
public enum RotationDirection {
|
||||||
|
CLOCKWISE(1),
|
||||||
|
COUNTERCLOCKWISE(-1);
|
||||||
|
|
||||||
|
int value;
|
||||||
|
|
||||||
|
RotationDirection(int value) {
|
||||||
|
this.value=value;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user