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.color=col;
|
||||
}
|
||||
public String toString() {
|
||||
return active?"O":"-";
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package sig.game;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.Arrays;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
@ -16,6 +17,11 @@ public class Game {
|
||||
public static int rotation = 0; //0-3
|
||||
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) {
|
||||
|
||||
final Frame LPiece = new Frame(
|
||||
@ -26,8 +32,8 @@ public class Game {
|
||||
+ "XXXX"),
|
||||
new Shape(
|
||||
"XXXX"
|
||||
+ "OOOO"
|
||||
+ "OXXX"
|
||||
+ "XOOO"
|
||||
+ "XOXX"
|
||||
+ "XXXX"),
|
||||
new Shape(
|
||||
"XOOX"
|
||||
@ -36,8 +42,8 @@ public class Game {
|
||||
+ "XXXX"),
|
||||
new Shape(
|
||||
"XXXX"
|
||||
+ "XXXO"
|
||||
+ "OOOO"
|
||||
+ "XXOX"
|
||||
+ "OOOX"
|
||||
+ "XXXX")
|
||||
,Color.ORANGE);
|
||||
final Frame JPiece = new Frame(
|
||||
@ -47,8 +53,8 @@ public class Game {
|
||||
+ "XOOX"
|
||||
+ "XXXX"),
|
||||
new Shape(
|
||||
"OXXX"
|
||||
+ "OOOO"
|
||||
"XOXX"
|
||||
+ "XOOO"
|
||||
+ "XXXX"
|
||||
+ "XXXX"),
|
||||
new Shape(
|
||||
@ -57,8 +63,8 @@ public class Game {
|
||||
+ "XOOX"
|
||||
+ "XXXX"),
|
||||
new Shape(
|
||||
"OOOO"
|
||||
+ "XXXO"
|
||||
"OOOX"
|
||||
+ "XXOX"
|
||||
+ "XXXX"
|
||||
+ "XXXX")
|
||||
,Color.BLUE);
|
||||
@ -193,12 +199,22 @@ public class Game {
|
||||
|
||||
static void step() {
|
||||
tickDelay--;
|
||||
rotateTimer--;
|
||||
if (tickDelay<=0) {
|
||||
moveBlock();
|
||||
tickDelay=levelDelay[level];
|
||||
}
|
||||
if (rotateTimer<=0) {
|
||||
//p.rotateCounterClockwise();
|
||||
p.moveBlockLeft();
|
||||
rotateTimer=rotateDelay;
|
||||
}
|
||||
DrawBoard();
|
||||
}
|
||||
|
||||
private static void DrawBoard() {
|
||||
ClearScreen();
|
||||
Point[] checkPoints = p.GetPlayerBlocksInGrid();
|
||||
Point[] checkPoints = p.GetPlayerBlocksInGrid(p.getCurrentShape());
|
||||
for (int y=19;y>=0;y--) {
|
||||
for (int x=0;x<10;x++) {
|
||||
boolean plotted=false;
|
||||
@ -210,7 +226,7 @@ public class Game {
|
||||
}
|
||||
}
|
||||
if (!plotted) {
|
||||
System.out.print((gameGrid.grid[x][y].active)?'O':'-');
|
||||
System.out.print(gameGrid.grid[x][y]);
|
||||
}
|
||||
}
|
||||
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;
|
||||
for (int i=0;i<checkPoints.length;i++) {
|
||||
Point point = checkPoints[i];
|
||||
//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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isOccupied) {
|
||||
for (Point point : checkPoints) {
|
||||
gameGrid.grid[point.x][point.y].active=true;
|
||||
}
|
||||
p.ShuffleNextPiece();
|
||||
} else {
|
||||
p.pos.translate(0, -1);
|
||||
}
|
||||
return isOccupied;
|
||||
}
|
||||
}
|
||||
|
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);
|
||||
}
|
||||
|
||||
private Frame SelectRandomTetrimino() {
|
||||
return Game.piecePool[(int)(Math.random()*Game.piecePool.length)];
|
||||
}
|
||||
|
||||
public void ShuffleNextPiece() {
|
||||
piece = nextPiece.clone();
|
||||
nextPiece = SelectRandomTetrimino();
|
||||
pos = new Point(5,20);
|
||||
}
|
||||
|
||||
public Point[] GetPlayerBlocksInGrid() {
|
||||
public Point[] GetPlayerBlocksInGrid(Shape s) {
|
||||
Point[] checkPoints = new Point[4];
|
||||
Shape tetShape = piece.shape[Game.rotation];
|
||||
Shape tetShape = s;
|
||||
int pointsInserted=0;
|
||||
for (int x=0;x<tetShape.shape.length;x++) {
|
||||
for (int y=0;y<tetShape.shape[0].length;y++) {
|
||||
@ -42,4 +38,89 @@ public class Player {
|
||||
}
|
||||
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