Página en revisión
Código en Processing, tomado de: http://www.danepieri.com/tetris_play.html
// Controls: // Arrow keys for left, right, down, rotate // Spacebar to drop piece //import processing.opengl.*; PFont Hira; Board myBoard; Board.BoardBlock[][] myBoardBlock; fallingPiece myPiece; int numRows = 15; int numCol = 10; int brickSize = 25; int offset = 20; int numRowsCleared; boolean gameIsOver = false; void setup(){ size(440,415); stroke(100); Hira = loadFont("Ziggurat.vlw"); myBoard = new Board(); myBoardBlock = new Board.BoardBlock[10][15]; for (int i=0; i<numCol; i++){ for (int j=0; j<numRows; j++){ myBoardBlock[i][j] = myBoard.new BoardBlock(i,j); } } myPiece = new fallingPiece((int)random(6.99999)); } void draw(){ background(200); myBoard.renderBoard(); myBoard.clearFullRows(); myBoard.displayScore(); myBoard.displayGameOver(); myPiece.animate(); } // ======= Falling Piece Class =============== // =========================================== class fallingPiece{ int pieceUsed; int posCreating; color pieceCol; int[][] brickPos = new int[4][2]; // [0]=x [1]=y // These boolean arrays are used to create the pieces // however after that a piece is just a set of 4 x and y values // so really it is four pieces. boolean[][] I_PIECE = { { true, true, true, true } }; boolean[][] J_PIECE = { { true, false, false } , { true, true, true } }; boolean[][] L_PIECE = { { false, false, true }, { true, true, true } }; boolean[][] O_PIECE = { { true, true }, { true, true } }; boolean[][] S_PIECE = { { false, true, true }, { true, true, false } }; boolean[][] T_PIECE = { { false, true, false }, { true, true, true } }; boolean[][] Z_PIECE = { { true, true, false } , { false, true, true } }; color[] pieceColors = { color(0,240,240),color(0,0,240), color(240,160,0), color(240,240,0), color(0,240,0), color(160,0,240), color(240,0,0) }; boolean[][][] allPieces = { I_PIECE, J_PIECE, L_PIECE, O_PIECE, S_PIECE, T_PIECE, Z_PIECE }; // Pieces are rotated according to their relationship to the center brick int[] centerPiece = { 1, 2, 1, 1, 2, 2, 2 }; // Constructor fallingPiece(int pieceUsed){ int[][] brickPosTemp = new int[4][2]; this.pieceUsed = pieceUsed; pieceCol = pieceColors[pieceUsed]; for (int j=0; j<allPieces[pieceUsed][0].length; j++){ for (int i=0; i<allPieces[pieceUsed].length; i++){ if(allPieces[pieceUsed][i][j]){ brickPosTemp[posCreating%4][0] = (numCol/2)-1 + i; brickPosTemp[posCreating%4][1] = j; if (myBoardBlock[brickPosTemp[posCreating%4][0]][brickPosTemp[posCreating%4][1]].isTaken() == true){ myBoard.gameOver(); break; } posCreating ++; } } if (gameIsOver == true){ break; } } if (gameIsOver == false){ for (int i=0; i<brickPos.length; i++){ brickPos[i][0] = brickPosTemp[i][0]; brickPos[i][1] = brickPosTemp[i][1]; } } } // Functions void render(){ strokeWeight(1); for (int i=0; i<brickPos.length; i++){ fill(pieceCol); rect( brickPos[i][0]*brickSize+offset, brickPos[i][1]*brickSize+offset, brickSize,brickSize); } } void animate(){ if(gameIsOver == false){ if(frameCount%(max(10,(25-numRowsCleared))) == 0 && this.canItMove()){ this.moveY(); } if(keyPressed){ if (key == CODED){ if(keyCode == RIGHT && this.canItMoveR()){ this.moveRight(); keyPressed = false; } else if(keyCode == LEFT && this.canItMoveL()){ this.moveLeft(); keyPressed = false; } else if(keyCode == DOWN && this.canItMove()){ this.moveY(); keyPressed = false; } else if(keyCode == UP){ this.rotate(); keyPressed = false; } } else if(key == ' '){ while (myPiece.canItMove()){ this.moveY(); } keyPressed = false; } } this.render(); } } void moveY(){ for (int i=0; i<brickPos.length; i++){ brickPos[i][1] ++; } } void moveRight(){ for (int i=0; i<brickPos.length; i++){ brickPos[i][0] ++; } } void moveLeft(){ for (int i=0; i<brickPos.length; i++){ brickPos[i][0] --; } } boolean canItMove(){ for (int i=0; i<brickPos.length; i++){ if(brickPos[i][1] == numRows-1){ this.freezeBlock(); return false; } if(myBoardBlock[brickPos[i][0]][brickPos[i][1]+1].isTaken() == true){ this.freezeBlock(); return false; } } return true; } boolean canItMoveL(){ for (int i=0; i<brickPos.length; i++){ if(brickPos[i][0] == 0){ return false; } if(myBoardBlock[brickPos[i][0]-1][brickPos[i][1]].isTaken() == true){ return false; } } return true; } boolean canItMoveR(){ for (int i=0; i<brickPos.length; i++){ if(brickPos[i][0] == numCol-1){ return false; } if(myBoardBlock[brickPos[i][0]+1][brickPos[i][1]].isTaken() == true){ return false; } } return true; } boolean canItRotate(int x, int y){ if (x > numCol-1 || x < -1 || y > numRows-1 || myBoardBlock[x][y].isTaken() == true ){ return false; } return true; } void freezeBlock(){ for (int i=0; i<brickPos.length; i++){ myBoardBlock[brickPos[i][0]][brickPos[i][1]].take(); myBoardBlock[brickPos[i][0]][brickPos[i][1]].col = pieceColors[pieceUsed]; } myPiece = new fallingPiece((int)random(6.9999)); } void rotate(){ int[][] brickPosTemp = new int[4][2]; boolean isItGoingToRotate = true; for (int i=0; i<brickPos.length; i++){ if( i != centerPiece[pieceUsed] && pieceUsed != 3){ int xDifference; int yDifference; int temp; xDifference = brickPos[i][0] - brickPos[centerPiece[pieceUsed]][0]; yDifference = brickPos[i][1] - brickPos[centerPiece[pieceUsed]][1]; xDifference *= -1; // rotate and check if new position is taken brickPosTemp[i][1] = brickPos[centerPiece[pieceUsed]][1] + xDifference; brickPosTemp[i][0] = brickPos[centerPiece[pieceUsed]][0] + yDifference; if(canItRotate(brickPosTemp[i][0], brickPosTemp[i][1]) == false){ isItGoingToRotate = false; break; } } } // Actually rotate if (isItGoingToRotate == true){ for (int i=0; i<brickPos.length; i++){ if( i != centerPiece[pieceUsed] && pieceUsed != 3){ brickPos[i][1] = brickPosTemp[i][1]; brickPos[i][0] = brickPosTemp[i][0]; } } } isItGoingToRotate = true; } } // ============== Board Class ================ // =========================================== public class Board{ int score = 0; // constructor Board(){ } void clearFullRows(){ int numFullRows = 0; for (int i=0; i<numRows; i++){ if(myBoardBlock[0][i].isTaken() == true && myBoardBlock[1][i].isTaken() == true && myBoardBlock[2][i].isTaken() == true && myBoardBlock[3][i].isTaken() == true && myBoardBlock[4][i].isTaken() == true && myBoardBlock[5][i].isTaken() == true && myBoardBlock[6][i].isTaken() == true && myBoardBlock[7][i].isTaken() == true && myBoardBlock[8][i].isTaken() == true && myBoardBlock[9][i].isTaken() == true) { numFullRows ++; //println("full" + numFullRows); for (int j=0; j<numCol; j++){ myBoardBlock[j][i].take(); for (int k = i; k>0; k--){ myBoardBlock[j][k].taken = myBoardBlock[j][k-1].taken; myBoardBlock[j][k].col = myBoardBlock[j][k-1].col; } } } } if (numFullRows == 4){ score += 800; // Tetris!! } else if(numFullRows > 0){ score = score + (numFullRows * 100); numRowsCleared += numFullRows; } numFullRows = 0; } void renderBoard(){ for (int i=0; i<10; i++){ for (int j=0; j<15; j++){ myBoardBlock[i][j].render(); } } noFill(); strokeWeight(1); rect(offset,offset, brickSize*numCol, brickSize*numRows); } void gameOver(){ gameIsOver = true; // println("Game Over"); } void newGame(){ score = 0; gameIsOver = false; for (int i=0; i<numCol; i++){ for (int j=0; j<numRows; j++){ myBoardBlock[i][j].taken = false; myBoardBlock[i][j].col = color(150,150,230); } } myPiece = new fallingPiece((int)random(6.9999)); //println("New Game"); } void displayScore(){ textFont(Hira,25); strokeWeight(1); fill(255); text("Score:", width-120,70); rect(width-130,85, 100,30); fill(150); text(score, width-125,110); } void displayGameOver(){ if (gameIsOver == true){ int bX = 70; int bY = 125; int bWidth = 140; int bHeight = 32; fill(220,100); rect(offset,offset, brickSize*numCol, brickSize*numRows); textFont(Hira,25); strokeWeight(1); fill(255); text("Game Over!", 70,70); noStroke(); fill(20,30,200); rect(bX,bY, bWidth,bHeight); fill(255,200); text("New Game", 75,150); stroke(100); // Click for new game if(mouseX > bX && mouseX < bX + bWidth && mouseY > bY && mouseX < bY + bHeight){ if(mousePressed){ myBoard.newGame(); } } } } // ============ Board Block sub class =============== public class BoardBlock extends Board{ color col; int x; int y; boolean taken; // Constructor BoardBlock(int x, int y){ col = color(150,150,230); this.x = offset+ x*25; this.y = offset+ y*25; this.taken = false; } // Accessor boolean isTaken(){ return taken; } // Setter void take(){ this.taken = true; } void render(){ fill(col); if(taken){ strokeWeight(1); } else{ strokeWeight(1); } rect(x,y, brickSize,brickSize); } } }