tleewu / tetris

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

#Tetris

Tetris is a childhood favorite of mine, and I just had to build this. This game is built in Javascript and HTML5 Canvas.

You can play it [here] (https://tleewu.github.io/tetris).

Main Challenges

Challenge 1: Managing the relationships amongst pieces

  • This initial structure is essential for determining when a player can move a piece or not or figuring out when a falling piece has stopped and the game needs to instantiate another piece.

My Solution: Implement a grid (an array of arrays). To check if a move is valid, ensure that all of a piece's positions are empty on the grid. A value of 0 means that the position on the grid is empty; a value of 1 means that the position on the grid has been filled.

Game.prototype.isAnIllegalMove = function (arrayOfGridPositions) {
  var illegalMove = false;
  for (var i = 0; i < arrayOfGridPositions.length; i++) {
    var row = arrayOfGridPositions[i][0];
    var col = arrayOfGridPositions[i][1];

    if (row < 0 || col < 0 || col >= Constants.GRID_WIDTH || this.grid[row] === undefined || this.grid[row][col]) {
      illegalMove = true;
      break;

  }
  return illegalMove;
};

When a piece has been mounted, update the grid.

for (var i = 0; i < arrayOfGridPositions.length; i++) {
  var rowNumber = arrayOfGridPositions[i][0];
  var colNumber = arrayOfGridPositions[i][1];
  this.grid[rowNumber][colNumber] = 1;
}

Challenge 2: Rotating pieces

  • Yeah, it's pretty easy for square and straight pieces because the rotations are pretty minimal. But the other pieces involved a little bit more math.

My Solution: Gave an internal angle and a center to pieces and used trigonometry to manipulate the position of other parts. Here's an example of what I did with the L-shaped Tetris piece.

var allPositions = [center];

var positionsToAddToCenter = [[2*parseInt(Math.sin(angle).toFixed()), 2*parseInt(Math.cos(angle).toFixed())],
                              [parseInt(Math.sin(angle).toFixed()), parseInt(Math.cos(angle).toFixed())],
                              [parseInt(Math.cos(angle).toFixed()), -parseInt(Math.sin(angle).toFixed())]];

By adjusting the other parts in relationship to the center, I could map out a piece at any rotation.

Challenge 3: Hard Drop

  • In Tetris, a hard drop causes the piece to fall straight down.

My Solution: Iterate through all possible "down" steps, starting from 1. When a step will cause an 'illegal move', stop.

var hardHit;
while (!newPos || !this.game.isAnIllegalMove(newPos)) {
  if (!hardHit) {
    hardHit = 0;
  }
  hardHit++;
  newPos = [];
  for (var i = 0; i < this.gridPos.length; i++) {
    newPos.push(this.gridPos[i].addAnotherArray([hardHit,0]));
  }
}
return [hardHit-1, 0];

Challenge 4: Wall Kick

  • I took this feature for granted when I normally play the game, and it wasn't until one of my close friends pointed that my game was missing it. I'm not great at explaining what a wall kick is, so I'll refer you to [this] (www.tetris.wikia.com/wiki/Wall_kick).

My Solution: If an attempt to rotate a piece is illegal, I moved the piece over one to the left and one to the right to see if the rotation is still illegal. If the move became legal, I rotated the piece and moved it over one.

if (this.game.isAnIllegalMove(newPos)){
  var leftPos = [], rightPos = [];
  for (var j = 0; j < newPos.length; j++) {
    leftPos.push(newPos.clone()[j].addAnotherArray([0,-1]));
    rightPos.push(newPos.clone()[j].addAnotherArray([0,1]));
  }

  if (this.game.isAnIllegalMove(leftPos) && this.game.isAnIllegalMove(rightPos)) {
    return;
  } else {
    if (this.game.isAnIllegalMove(leftPos)) {
      this.updateCenterPosition([0,1]);
      newPos = rightPos;
    } else {
      this.updateCenterPosition([0,-1]);
      newPos = leftPos;
    }
    this.rotate();
  }

Features to be Implemented

  • Optimize game to reduce flickering.
  • Include player score and levels.
  • Show 'next' piece.

About


Languages

Language:JavaScript 95.6%Language:HTML 4.4%