<html>
<head>
  <title>Tetris</title>
  <style>
    body {
      background-color: #555;
    }
<pre><code>#tetris {
  position: relative;
  margin: 0 auto;
  border: 1px solid #999;
  background: #000;
  width: 200px;
  height: 400px;
}

.tetromino {
  background-color: #0f0;
  width: 20px;
  height: 20px;
  position: absolute;
}
</code></pre>
  </style>
</head>
<body>
  <h1>Tetris</h1>
  <div id='tetris'></div>
  <script>
    // Generate pieces
    const PIECES = [
      [Z, 'red'],
      [S, 'green'],
      [T, 'yellow'],
      [O, 'blue'],
      [L, 'purple'],
      [I, 'cyan'],
      [J, 'orange']
    ];
<pre><code>// Create pieces
let board = [];
let score = 0;
let gameOver = false;

// Create divs
let gameDiv = document.getElementById('tetris');
let nextDiv = document.createElement('div');
let scoreDiv = document.createElement('div');
scoreDiv.setAttribute('id', 'score');
gameDiv.appendChild(nextDiv);
gameDiv.appendChild(scoreDiv);

// Create pieces
let pieces = [];
let currentPiece = randomPiece();
let nextPiece = randomPiece();

// The main game loop
let dropCounter = 0;
let dropInterval = 1000;
let lastTime = 0;
function update(time = 0) {
  const deltaTime = time - lastTime;
  lastTime = time;

  dropCounter += deltaTime;
  if (dropCounter &gt; dropInterval) {
    movePieceDown();
  }

  draw();
  drawNext();
  scoreDiv.innerHTML = 'Score: ' + score;
  if (!gameOver) {
    requestAnimationFrame(update);
  }
}

update();

// Move pieces
document.addEventListener('keydown', movePiece);
function movePiece(event) {
  switch (event.keyCode) {
    case 37:
      movePieceLeft();
      break;
    case 38:
      rotatePiece();
      break;
    case 39:
      movePieceRight();
      break;
    case 40:
      movePieceDown();
      break;
  }
}

// Create functions
function randomPiece() {
  let r = randomN = Math.floor(Math.random() * PIECES.length) // 0 -&gt; 6
  return new Piece(PIECES[r][0], PIECES[r][1]);
}

function draw() {
  gameDiv.innerHTML = '';
  for (let r = 0; r &lt; board.length; r++) {
    for (let c = 0; c &lt; board[r].length; c++) {
      if (board[r][c] !== 0) {
        let div = document.createElement('div');
        div.setAttribute('class', 'tetromino');
        div.style.top = r * 20 + 'px';
        div.style.left = c * 20 + 'px';
        div.style.backgroundColor = board[r][c];
        gameDiv.appendChild(div);
      }
    }
  }
}

function drawNext() {
  nextDiv.innerHTML = '';
  for (let r = 0; r &lt; nextPiece.matrix.length; r++) {
    for (let c = 0; c &lt; nextPiece.matrix[r].length; c++) {
      if (nextPiece.matrix[r][c] !== 0) {
        let div = document.createElement('div');
        div.setAttribute('class', 'tetromino');
        div.style.top = r * 20 + 'px';
        div.style.left = c * 20 + 'px';
        div.style.backgroundColor = nextPiece.color;
        nextDiv.appendChild(div);
      }
    }
  }
}

// Create pieces
function Piece(tetromino, color) {
  this.tetromino = tetromino;
  this.color = color;

  this.tetrominoN = 0;
  this.activeTetromino = this.tetromino[this.tetrominoN];

  this.x = 3;
  this.y = -2;
}

// Move pieces
Piece.prototype.fill = function (color) {
  for (let r = 0; r &lt; this.activeTetromino.length; r++) {
    for (let c = 0; c &lt; this.activeTetromino.length; c++) {
      // We draw only occupied squares
      if (this.activeTetromino[r][c]) {
        board[this.y + r][this.x + c] = color;
      }
    }
  }
}

Piece.prototype.moveDown = function() {
  if (!this.collision(0, 1, this.activeTetromino)) {
    this.y++;
  } else {
    // Lock the current piece and generate a new one
    this.lock();
    currentPiece = nextPiece;
    nextPiece = randomPiece();
  }
}

Piece.prototype.moveLeft = function() {
  if (!this.collision(-1, 0, this.activeTetromino)) {
    this.x--;
  }
}

Piece.prototype.moveRight = function() {
  if (!this.collision(1, 0, this.activeTetromino)) {
    this.x++;
  }
}

Piece.prototype.rotate = function() {
  let nextPattern = this.tetromino[(this.tetrominoN + 1)%this.tetromino.length];
  let kick = 0;

  if (this.collision(0, 0, nextPattern)) {
    if (this.x &gt; COL/2) {
      // It's the right wall
      kick = -1; // We need to move the piece to the left
    } else {
      // It's the left wall
      kick = 1; // We need to move the piece to the right
    }
  }

  if (!this.collision(kick, 0, nextPattern)) {
    this.x += kick;
    this.tetrominoN = (this.tetrominoN + 1)%this.tetromino.length; // (0+1)%4 =&gt; 1
    this.activeTetromino = this.tetromino[this.tetrominoN];
  }
}

let ROW = 20;
let COL = 10;
let pieces = 'ILJOTSZ';
let board = [];
for (let r = 0; r &lt; ROW; r++) {
  board[r] = [];
  for (let c = 0; c &lt; COL; c++) {
    board[r][c] = 0;
  }
}

// Lock pieces
Piece.prototype.lock = function() {
  for (let r = 0; r &lt; this.activeTetromino.length; r++) {
    for (let c = 0; c &lt; this.activeTetromino.length; c++) {
      // We skip the vacant squares
      if (!this.activeTetromino[r][c]) {
        continue;
      }
      // Pieces to lock on top = game over
      if (this.y + r &lt; 0) {
        alert('Game Over!');
        // Stop request animation frame
        gameOver = true;
        break;
      }
      // We lock the piece
      board[this.y+r][this.x+c] = this.color;
    }
  }
  // Remove full rows
  for (let r = 0; r &lt; ROW; r++) {
    let isRowFull = true;
    for (let c = 0; c &lt; COL; c++) {
      isRowFull = isRowFull &amp;&amp; (board[r][c] != 0);
    }
    if (isRowFull) {
      board.splice(r, 1);
      board.unshift(new Array(COL).fill(0));
      score += 100;
    }
  }
}

// Check collisions
Piece.prototype.collision = function(xOffset, yOffset, matrix) {
  for (let r = 0; r &lt; matrix.length; r++) {
    for (let c = 0; c &lt; matrix.length; c++) {
      // We skip vacant squares
      if (!matrix[r][c]) {
        continue;
      }
      // Checks if the piece is inside the game board
      if (this.x + c + xOffset &lt; 0 || this.x + c + xOffset &gt;= COL || this.y + r + yOffset &gt;= ROW) {
        return true;
      }
      // Checks if there is a collision with the game board
      if (this.y + r + yOffset &lt; 0) {
        continue;
      }
      if (board[this.y + r + yOffset][this.x + c + xOffset] != 0) {
        return true;
      }
    }
  }
  return false;
}

// Pieces matrix
const Z = [
  [0, 0, 0],
  [1, 1, 0],
  [0, 1, 1],
  [0, 0, 0]
];
const S = [
  [0, 0, 0],
  [0, 1, 1],
  [1, 1, 0],
  [0, 0, 0]
];
const T = [
  [0, 0, 0],
  [1, 1, 1],
  [0, 1, 0],
  [0, 0, 0]
];
const O = [
  [0, 1, 1],
  [0, 1, 1],
  [0, 0, 0],
  [0, 0, 0]
];
const L = [
  [0, 1, 0],
  [0, 1, 0],
  [0, 1, 1],
  [0, 0, 0]
];
const I = [
  [0, 0, 0, 0],
  [1, 1, 1, 1],
  [0, 0, 0, 0],
  [0, 0, 0, 0]
];
const J = [
  [0, 1, 0],
  [0, 1, 0],
  [1, 1, 0],
  [0, 0, 0]
];
</code></pre>
  </script>
</body>
</htm
Play Tetris Online: Classic Brick-Stacking Game

原文地址: https://www.cveoy.top/t/topic/lmeK 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录