--- /dev/null
+/**
+ *
+ */
+package de.android.androidtetris;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This enum stores every piece and the square related to that piece.
+ *
+ * @author gusarapo
+ *
+ */
+public enum CurrentPiece {
+ /*The tower piece*/
+ I(0) {
+ @Override
+ void fill() {
+ size[1][0]=Tile.RED;
+ size[1][1]=Tile.RED;
+ size[1][2]=Tile.RED;
+ size[1][3]=Tile.RED;
+ }
+ },
+ /*The box piece*/
+ O(1) {
+ @Override
+ void fill() {
+ size[1][1]=Tile.BLUE;
+ size[1][2]=Tile.BLUE;
+ size[2][1]=Tile.BLUE;
+ size[2][2]=Tile.BLUE;
+ }
+ },
+ /*The pyramid piece*/
+ T(2) {
+ @Override
+ void fill() {
+ size[1][1]=Tile.YELLOW;
+ size[0][2]=Tile.YELLOW;
+ size[1][2]=Tile.YELLOW;
+ size[2][2]=Tile.YELLOW;
+ }
+ },
+ /*The left leaner piece*/
+ Z(3) {
+ @Override
+ void fill() {
+ size[0][1]=Tile.CYAN;
+ size[1][1]=Tile.CYAN;
+ size[1][2]=Tile.CYAN;
+ size[2][2]=Tile.CYAN;
+ }
+ },
+ /*The right leaner piece*/
+ S(4) {
+ @Override
+ void fill() {
+ size[2][1]=Tile.GREEN;
+ size[1][1]=Tile.GREEN;
+ size[1][2]=Tile.GREEN;
+ size[0][2]=Tile.GREEN;
+ }
+ },
+ /*The left knight piece*/
+ L(5) {
+ @Override
+ void fill() {
+ size[1][1]=Tile.MAGENTA;
+ size[2][1]=Tile.MAGENTA;
+ size[2][2]=Tile.MAGENTA;
+ size[2][3]=Tile.MAGENTA;
+ }
+ },
+ /*The right knight piece*/
+ J(6) {
+ @Override
+ void fill() {
+ size[2][1]=Tile.WHITE;
+ size[1][1]=Tile.WHITE;
+ size[1][2]=Tile.WHITE;
+ size[1][3]=Tile.WHITE;
+ }
+ };
+
+
+ //Every piece is contained in a square. This is the square's width.
+ public static final int WIDTH = 4;
+ //Every piece is contained in a square. This is the square's height.
+ public static final int HEIGHT = 4;
+ //Stores the x coordinate (the position of this piece on the grid)
+ public int x;
+ //Stores the y coordinate (the position of this piece on the grid)
+ public int y;
+ //Every piece is contained in a square.
+ public final Tile[][] size = new Tile[WIDTH][HEIGHT];
+ //Stores the argument of the enum constant (passed to the constructor) JLS§8.9.1
+ public final int pieceNumber;
+ //Map with every enum constant. Class variable initializer. JLS§12.4.2 Executed in textual order.
+ private static final Map<Integer, CurrentPiece> pieceMap = new HashMap<Integer, CurrentPiece>();
+
+
+ //Static initializer. JLS§12.4.2 Executed in textual order.
+ static {
+ for (CurrentPiece piece : CurrentPiece.values())
+ {
+ pieceMap.put(piece.pieceNumber, piece);
+ }
+ }
+
+
+ /**
+ * Because we have enum constants with arguments we have to create this constructor.
+ * It initializes the piece with the right values.
+ *
+ * @param pieceNumber It is the argument of the enum constant
+ */
+ private CurrentPiece (final int pieceNumber)
+ {
+ this.pieceNumber = pieceNumber;
+
+ //Pre-Initialization of matrix size
+ for (int i=0; i< WIDTH; i++)
+ for (int j=0; j< HEIGHT; j++)
+ size[i][j]= Tile.NOCOLOR;
+
+ this.x = 0;
+ this.y = 0;
+ //It depends on what kind of piece, we have to fill the square in the right way.
+ this.fill();
+ }
+
+
+ /**
+ * This method is used to retrieve the enum piece related to its number
+ *
+ * @param pieceNumber The piece number is associated to the argument of the enum constant.
+ * @return the enum whose argument of the enum constant matches the pieceNumber.
+ */
+ public static final CurrentPiece getPiece (final int pieceNumber)
+ {
+ return pieceMap.get(pieceNumber);
+ }
+
+
+ /**
+ * This method is intended to be overridden by every piece to fill the square which contains the piece's shape.
+ */
+ abstract void fill();
+
+}
private AndroidTetrisThread thread;
private Bitmap[] tileArray;
private Tile[][] mapMatrix;
- private Piece prePiece;
- private Piece currentPiece;
+ private PrePiece prePiece;
+ private CurrentPiece currentPiece;
class AndroidTetrisThread extends Thread
{
this.newGame();
- currentPiece = newBlock();
+ currentPiece = newCurrentBlock();
currentPiece.x = MAPWIDTH/2-2;
- currentPiece.y = -1;
- prePiece = newBlock();
- prePiece.x=MAPWIDTH+2;
- prePiece.y=GREY/4;
+ currentPiece.y = -1;
+ prePiece = newPreBlock();
+ prePiece.x = MAPWIDTH+2;
+ prePiece.y = GREY/4;
// register our interest in hearing about changes to our surface
//SurfaceHolder holder = getHolder();
//start out the map
for(int x=0;x< MAPWIDTH;x++)
{
- for(int y=0;y< MAPHEIGHT+1;y++)
+ for(int y=0; y<= MAPHEIGHT;y++)
{
mapMatrix[x][y]=Tile.BLACK;
}
}
}
- protected Piece newBlock()
+ private CurrentPiece newCurrentBlock()
{
Random random = new Random();
-
- Piece piece = Piece.getPiece(random.nextInt(7)%7);
- return piece;
+ return CurrentPiece.getPiece(random.nextInt(7)%7);
+ }
+
+
+ private PrePiece newPreBlock()
+ {
+ Random random = new Random();
+
+ return PrePiece.getPiece(random.nextInt(7)%7);
}
protected void drawTile(Canvas canvas, int color, int x, int y)
drawTile(canvas, Tile.GRAY.getColor(), x, y);
//draw the pre-piece
- for(int x=0; x<4; x++)
- for(int y=0; y<4; y++)
+ for(int x=0; x < PrePiece.WIDTH; x++)
+ for(int y=0; y< PrePiece.HEIGHT; y++)
if(prePiece.size[x][y] != Tile.NOCOLOR)
- drawTile(canvas, prePiece.size[x][y].getColor(), prePiece.x+x, prePiece.y +y);
+ drawTile(canvas, prePiece.size[x][y].getColor(), prePiece.x + x, prePiece.y +y);
//draw grid
- for(int x=0; x< MAPWIDTH; x++)
- for(int y=0; y< MAPHEIGHT; y++)
+ for(int x=0; x < MAPWIDTH; x++)
+ for(int y=0; y < MAPHEIGHT; y++)
drawTile(canvas, mapMatrix[x][y].getColor(), x, y);
//draw the current block
- for(int x=0; x<4; x++)
- for(int y=0; y<4; y++)
+ for(int x=0; x < CurrentPiece.WIDTH; x++)
+ for(int y=0; y < CurrentPiece.HEIGHT; y++)
if(currentPiece.size[x][y] != Tile.NOCOLOR)
- drawTile(canvas, currentPiece.size[x][y].getColor(), currentPiece.x+x, currentPiece.y +y);
+ drawTile(canvas, currentPiece.size[x][y].getColor(), currentPiece.x + x, currentPiece.y +y);
}
protected void move (int x, int y)
{
if (y == 1)
{
- currentPiece = prePiece;
- currentPiece.x = MAPWIDTH/2-2;
- currentPiece.y = -1;
- prePiece = newBlock();
- prePiece.x=MAPWIDTH+2;
- prePiece.y=GREY/4;
+ if (currentPiece.y == -1)
+ {
+ //GAMEOVER
+ //start out the map
+ for(int xx=0;xx< MAPWIDTH;xx++)
+ {
+ for(int yy=0; yy<= MAPHEIGHT;yy++)
+ {
+ mapMatrix[xx][yy]=Tile.BLACK;
+ }
+ }
+ currentPiece = newCurrentBlock();
+ currentPiece.x = MAPWIDTH/2-2;
+ currentPiece.y = -1;
+ prePiece = newPreBlock();
+ prePiece.x = MAPWIDTH+2;
+ prePiece.y = GREY/4;
+ }
+ else
+ {
+ //Add block to Grid
+ for(int i=0; i<CurrentPiece.WIDTH; i++)
+ for(int j=0; j<CurrentPiece.HEIGHT; j++)
+ if(currentPiece.size[i][j] != Tile.NOCOLOR)
+ mapMatrix[currentPiece.x+i][currentPiece.y+j] = currentPiece.size[i][j];
+
+ //check for cleared row!
+
+ for(int j=0; j< MAPHEIGHT; j++)
+ {
+ boolean filled=true;
+ for(int i=0; i< MAPWIDTH; i++)
+ if(mapMatrix[i][j] == Tile.BLACK)
+ filled=false;
+
+ if(filled)
+ {
+ removeRow(j);
+ }
+ }
+
+ currentPiece = CurrentPiece.getPiece(prePiece.pieceNumber);
+ currentPiece.x = MAPWIDTH/2-2;
+ currentPiece.y = -1;
+ prePiece = newPreBlock();
+ prePiece.x = MAPWIDTH+2;
+ prePiece.y = GREY/4;
+ }
}
}
else
}
}
- protected boolean collisionTest(int cx, int cy)
+
+ private void removeRow(int row) {
+
+ for(int x=0; x< MAPWIDTH; x++)
+ for(int y=row; y>0; y--)
+ mapMatrix[x][y]=mapMatrix[x][y-1];
+ }
+
+
+ private boolean collisionTest(int cx, int cy)
{
int newx = currentPiece.x + cx;
int newy = currentPiece.y + cy;
//Check grid boundaries
- for(int x=0; x<4; x++)
- for(int y=0; y<4; y++)
+ for(int x=0; x<CurrentPiece.WIDTH; x++)
+ for(int y=0; y<CurrentPiece.HEIGHT; y++)
if(currentPiece.size[x][y] != Tile.NOCOLOR)
- if ((newy + y == MAPHEIGHT) || (newy + y < 0) || (newx + x == MAPWIDTH) || (newx + x < 0))
+ if ((newy + y >= MAPHEIGHT) || (newy + y < 0) || (newx + x >= MAPWIDTH) || (newx + x < 0))
return true;
//Check collisions with other blocks
for(int x=0; x< MAPWIDTH; x++)
for(int y=0; y< MAPHEIGHT; y++)
- if(x >= newx && x < newx + 4)
- if(y >= newy && y < newy +4)
+ if(x >= newx && x < newx + CurrentPiece.WIDTH)
+ if(y >= newy && y < newy + CurrentPiece.HEIGHT)
if(mapMatrix[x][y] != Tile.BLACK)
if(currentPiece.size[x - newx][y - newy] != Tile.NOCOLOR)
return true;
return false;
}
+ /**
+ * TODO: reuse the collisionTest method for this one (the are the same thing with just a few changes)
+ * Sorry I am too tired to rewrite the methods right now.
+ */
+ private void rotateBlock() {
+ Tile[][] temporal = new Tile[CurrentPiece.WIDTH][CurrentPiece.HEIGHT];
+
+ //Copy and rotate current piece to the temporary array
+ for(int x=0; x<CurrentPiece.WIDTH; x++)
+ for(int y=0; y<CurrentPiece.HEIGHT; y++)
+ temporal[3-y][ x ]=currentPiece.size[ x ][y];
+
+ //Check grid boundaries
+ for(int x=0; x<CurrentPiece.WIDTH; x++)
+ for(int y=0; y<CurrentPiece.HEIGHT; y++)
+ if(temporal[x][y] != Tile.NOCOLOR)
+ if ((currentPiece.y + y >= MAPHEIGHT) || (currentPiece.y + y < 0) ||
+ (currentPiece.x + x >= MAPWIDTH) || (currentPiece.x + x < 0))
+ return;
+
+ //Check collisions with other blocks
+ for(int x=0; x< MAPWIDTH; x++)
+ for(int y=0; y< MAPHEIGHT; y++)
+ if(x >= currentPiece.x && x < currentPiece.x + CurrentPiece.WIDTH)
+ if(y >= currentPiece.y && y < currentPiece.y + CurrentPiece.HEIGHT)
+ if(mapMatrix[x][y] != Tile.BLACK)
+ if(temporal[x - currentPiece.x][y - currentPiece.y] != Tile.NOCOLOR)
+ return;
+
+ //Rotate is allowed
+ for(int x=0; x<CurrentPiece.WIDTH; x++)
+ for(int y=0; y<CurrentPiece.HEIGHT; y++)
+ currentPiece.size[x][y]=temporal[x][y];
+ }
@Override
public boolean onKeyDown(int keyCode, KeyEvent msg) {
//view.onDraw(c);
this.getHolder().unlockCanvasAndPost(c);
}
- return(true);
+ return true;
}
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
synchronized (this.getHolder())
//view.onDraw(c);
this.getHolder().unlockCanvasAndPost(c);
}
- return(true);
+ return true;
}
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
synchronized (this.getHolder())
//view.onDraw(c);
this.getHolder().unlockCanvasAndPost(c);
}
- return(true);
+ return true;
}
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
- return(true);
+ synchronized (this.getHolder())
+ {
+ Canvas c = this.getHolder().lockCanvas();
+ this.rotateBlock();
+ this.drawMap(c);
+ //view.onDraw(c);
+ this.getHolder().unlockCanvasAndPost(c);
+ }
+ return true;
}
return false;
+++ /dev/null
-/**
- *
- */
-package de.android.androidtetris;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * This enum stores every piece and the square related to that piece.
- *
- * @author gusarapo
- *
- */
-public enum Piece {
- /*The tower piece*/
- I(0) {
- @Override
- void fill() {
- size[1][0]=Tile.RED;
- size[1][1]=Tile.RED;
- size[1][2]=Tile.RED;
- size[1][3]=Tile.RED;
- }
- },
- /*The box piece*/
- O(1) {
- @Override
- void fill() {
- size[1][1]=Tile.BLUE;
- size[1][2]=Tile.BLUE;
- size[2][1]=Tile.BLUE;
- size[2][2]=Tile.BLUE;
- }
- },
- /*The pyramid piece*/
- T(2) {
- @Override
- void fill() {
- size[1][1]=Tile.YELLOW;
- size[0][2]=Tile.YELLOW;
- size[1][2]=Tile.YELLOW;
- size[2][2]=Tile.YELLOW;
- }
- },
- /*The left leaner piece*/
- Z(3) {
- @Override
- void fill() {
- size[0][1]=Tile.CYAN;
- size[1][1]=Tile.CYAN;
- size[1][2]=Tile.CYAN;
- size[2][2]=Tile.CYAN;
- }
- },
- /*The right leaner piece*/
- S(4) {
- @Override
- void fill() {
- size[2][1]=Tile.GREEN;
- size[1][1]=Tile.GREEN;
- size[1][2]=Tile.GREEN;
- size[0][2]=Tile.GREEN;
- }
- },
- /*The left knight piece*/
- L(5) {
- @Override
- void fill() {
- size[1][1]=Tile.MAGENTA;
- size[2][1]=Tile.MAGENTA;
- size[2][2]=Tile.MAGENTA;
- size[2][3]=Tile.MAGENTA;
- }
- },
- /*The right knight piece*/
- J(6) {
- @Override
- void fill() {
- size[2][1]=Tile.WHITE;
- size[1][1]=Tile.WHITE;
- size[1][2]=Tile.WHITE;
- size[1][3]=Tile.WHITE;
- }
- };
-
-
- //Every piece is contained in a square. This is the square's width.
- private static final int WIDTH = 4;
- //Every piece is contained in a square. This is the square's height.
- private static final int HEIGHT = 4;
- //Every piece is contained in a square.
- public final Tile[][] size = new Tile[WIDTH][HEIGHT];
- //Stores the x coordinate (the position of this piece on the grid)
- public int x = 0;
- //Stores the y coordinate (the position of this piece on the grid)
- public int y = 0;
- //Stores the argument of the enum constant (passed to the constructor) JLS§8.9.1
- private final int pieceNumber;
- //Map with every enum constant. Class variable initializer. JLS§12.4.2 Executed in textual order.
- private static final Map<Integer, Piece> pieceMap = new HashMap<Integer, Piece>();
-
-
- //Static initializer. JLS§12.4.2 Executed in textual order.
- static {
- for (Piece piece : Piece.values())
- {
- pieceMap.put(piece.pieceNumber, piece);
- }
- }
-
-
- /**
- * Because we have enum constants with arguments we have to create this constructor.
- * It initializes the piece with the right values.
- *
- * @param pieceNumber It is the argument of the enum constant
- */
- private Piece (final int pieceNumber)
- {
- this.pieceNumber = pieceNumber;
-
- //Pre-Initialization of matrix size
- for (int i=0; i< WIDTH; i++)
- for (int j=0; j< HEIGHT; j++)
- size[i][j]= Tile.NOCOLOR;
-
- //It depends on what kind of piece, we have to fill the square in the right way.
- this.fill();
- }
-
-
- /**
- * This method is used to retrieve the enum piece related to its number
- *
- * @param pieceNumber The piece number is associated to the argument of the enum constant.
- * @return the enum whose argument of the enum constant matches the pieceNumber.
- */
- public static final Piece getPiece (final int pieceNumber)
- {
- return pieceMap.get(pieceNumber);
- }
-
-
- /**
- * This method is intended to be overridden by every piece to fill the square which contains the piece's shape.
- */
- abstract void fill();
-
-}
--- /dev/null
+/**
+ *
+ */
+package de.android.androidtetris;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This enum stores every piece and the square related to that piece.
+ *
+ * @author gusarapo
+ *
+ */
+public enum PrePiece {
+ /*The tower piece*/
+ I(0) {
+ @Override
+ void fill() {
+ size[1][0]=Tile.RED;
+ size[1][1]=Tile.RED;
+ size[1][2]=Tile.RED;
+ size[1][3]=Tile.RED;
+ }
+ },
+ /*The box piece*/
+ O(1) {
+ @Override
+ void fill() {
+ size[1][1]=Tile.BLUE;
+ size[1][2]=Tile.BLUE;
+ size[2][1]=Tile.BLUE;
+ size[2][2]=Tile.BLUE;
+ }
+ },
+ /*The pyramid piece*/
+ T(2) {
+ @Override
+ void fill() {
+ size[1][1]=Tile.YELLOW;
+ size[0][2]=Tile.YELLOW;
+ size[1][2]=Tile.YELLOW;
+ size[2][2]=Tile.YELLOW;
+ }
+ },
+ /*The left leaner piece*/
+ Z(3) {
+ @Override
+ void fill() {
+ size[0][1]=Tile.CYAN;
+ size[1][1]=Tile.CYAN;
+ size[1][2]=Tile.CYAN;
+ size[2][2]=Tile.CYAN;
+ }
+ },
+ /*The right leaner piece*/
+ S(4) {
+ @Override
+ void fill() {
+ size[2][1]=Tile.GREEN;
+ size[1][1]=Tile.GREEN;
+ size[1][2]=Tile.GREEN;
+ size[0][2]=Tile.GREEN;
+ }
+ },
+ /*The left knight piece*/
+ L(5) {
+ @Override
+ void fill() {
+ size[1][1]=Tile.MAGENTA;
+ size[2][1]=Tile.MAGENTA;
+ size[2][2]=Tile.MAGENTA;
+ size[2][3]=Tile.MAGENTA;
+ }
+ },
+ /*The right knight piece*/
+ J(6) {
+ @Override
+ void fill() {
+ size[2][1]=Tile.WHITE;
+ size[1][1]=Tile.WHITE;
+ size[1][2]=Tile.WHITE;
+ size[1][3]=Tile.WHITE;
+ }
+ };
+
+
+ //Every piece is contained in a square. This is the square's width.
+ public static final int WIDTH = 4;
+ //Every piece is contained in a square. This is the square's height.
+ public static final int HEIGHT = 4;
+ //Stores the x coordinate (the position of this piece on the grid)
+ public int x;
+ //Stores the y coordinate (the position of this piece on the grid)
+ public int y;
+ //Every piece is contained in a square.
+ public final Tile[][] size = new Tile[WIDTH][HEIGHT];
+ //Stores the argument of the enum constant (passed to the constructor) JLS§8.9.1
+ public final int pieceNumber;
+ //Map with every enum constant. Class variable initializer. JLS§12.4.2 Executed in textual order.
+ private static final Map<Integer, PrePiece> pieceMap = new HashMap<Integer, PrePiece>();
+
+
+ //Static initializer. JLS§12.4.2 Executed in textual order.
+ static {
+ for (PrePiece piece : PrePiece.values())
+ {
+ pieceMap.put(piece.pieceNumber, piece);
+ }
+ }
+
+
+ /**
+ * Because we have enum constants with arguments we have to create this constructor.
+ * It initializes the piece with the right values.
+ *
+ * @param pieceNumber It is the argument of the enum constant
+ */
+ private PrePiece (final int pieceNumber)
+ {
+ this.pieceNumber = pieceNumber;
+
+ //Pre-Initialization of matrix size
+ for (int i=0; i< WIDTH; i++)
+ for (int j=0; j< HEIGHT; j++)
+ size[i][j]= Tile.NOCOLOR;
+
+ this.x = 0;
+ this.y = 0;
+ //It depends on what kind of piece, we have to fill the square in the right way.
+ this.fill();
+ }
+
+
+ /**
+ * This method is used to retrieve the enum piece related to its number
+ *
+ * @param pieceNumber The piece number is associated to the argument of the enum constant.
+ * @return the enum whose argument of the enum constant matches the pieceNumber.
+ */
+ public static final PrePiece getPiece (final int pieceNumber)
+ {
+ return pieceMap.get(pieceNumber);
+ }
+
+
+ /**
+ * This method is intended to be overridden by every piece to fill the square which contains the piece's shape.
+ */
+ abstract void fill();
+
+}