使用js和canvas、html实现简单的俄罗斯方块小游戏
// 获取画布和上下文
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score');
const startButton = document.getElementById('start-button');
// 游戏板的宽度和高度
const boardWidth = 10;
const boardHeight = 20;
const blockSize = 30;
// 初始化游戏板、当前方块、得分和游戏间隔
let board = [];
let currentPiece = null;
let score = 0;
let gameInterval = null;
// 颜色数组
const colors = [
'cyan', 'blue', 'orange', 'yellow', 'green', 'purple', 'red'
];
// 方块形状数组
const pieces = [
[[1, 1, 1, 1]], // I
[[1, 1, 1], [0, 1, 0]], // T
[[1, 1, 1], [1, 0, 0]], // L
[[1, 1, 1], [0, 0, 1]], // J
[[1, 1], [1, 1]], // O
[[0, 1, 1], [1, 1, 0]], // S
[[1, 1, 0], [0, 1, 1]] // Z
];
// 方块类
class Piece {
constructor(tetromino) {
this.tetromino = tetromino; // 方块形状
this.color = colors[Math.floor(Math.random() * colors.length)]; // 随机颜色
this.x = 3; // 初始位置
this.y = -2; // 初始位置
}
// 旋转方块
rotate() {
const newTetromino = this.tetromino[0].map((_, i) => this.tetromino.map(row => row[i])).reverse();
if (!this.collision(newTetromino, this.x, this.y)) {
this.tetromino = newTetromino;
}
}
// 检测碰撞
collision(tetromino, x, y) {
for (let row = 0; row < tetromino.length; row++) {
for (let col = 0; col < tetromino[row].length; col++) {
if (tetromino[row][col] && (board[y + row] && board[y + row][x + col] || x + col < 0 || x + col >= boardWidth || y + row >= boardHeight)) {
return true;
}
}
}
return false;
}
// 向下移动
moveDown() {
if (!this.collision(this.tetromino, this.x, this.y + 1)) {
this.y++;
} else {
this.lockPiece(); // 锁定方块
clearLines(); // 清除满行
if (this.y <= 0) { // 检查是否触顶
gameOver();
} else {
newPiece(); // 生成新方块
}
}
}
// 向左移动
moveLeft() {
if (!this.collision(this.tetromino, this.x - 1, this.y)) {
this.x--;
}
}
// 向右移动
moveRight() {
if (!this.collision(this.tetromino, this.x + 1, this.y)) {
this.x++;
}
}
// 锁定方块到游戏板
lockPiece() {
for (let row = 0; row < this.tetromino.length; row++) {
for (let col = 0; col < this.tetromino[row].length; col++) {
if (this.tetromino[row][col]) {
board[this.y + row][this.x + col] = this.color;
}
}
}
}
}
// 生成新方块
function newPiece() {
const randomPiece = pieces[Math.floor(Math.random() * pieces.length)];
currentPiece = new Piece(randomPiece);
}
// 绘制游戏板
function drawBoard() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
for (let row = 0; row < boardHeight; row++) {
for (let col = 0; col < boardWidth; col++) {
if (board[row][col]) {
ctx.fillStyle = board[row][col]; // 设置颜色
ctx.fillRect(col * blockSize, row * blockSize, blockSize, blockSize); // 绘制方块
}
}
}
if (currentPiece) {
for (let row = 0; row < currentPiece.tetromino.length; row++) {
for (let col = 0; col < currentPiece.tetromino[row].length; col++) {
if (currentPiece.tetromino[row][col]) {
ctx.fillStyle = currentPiece.color; // 设置颜色
ctx.fillRect((currentPiece.x + col) * blockSize, (currentPiece.y + row) * blockSize, blockSize, blockSize); // 绘制方块
}
}
}
}
}
// 清除满行
function clearLines() {
for (let row = boardHeight - 1; row >= 0; row--) {
if (board[row].every(cell => cell !== 0)) { // 检查行是否满
board.splice(row, 1); // 删除满行
board.unshift(Array(boardWidth).fill(0)); // 添加空行
score += 10; // 增加得分
scoreDisplay.textContent = `得分: ${score}`; // 更新得分显示
}
}
}
// 游戏循环
function gameLoop() {
if (currentPiece) {
currentPiece.moveDown(); // 移动方块
}
drawBoard(); // 绘制游戏板
}
// 开始游戏
function startGame() {
if (gameInterval) {
clearInterval(gameInterval); // 清除之前的定时器
}
board = Array.from({ length: boardHeight }, () => Array(boardWidth).fill(0)); // 重置游戏板
score = 0; // 重置得分
scoreDisplay.textContent = `得分: ${score}`; // 更新得分显示
newPiece(); // 生成新方块
gameInterval = setInterval(gameLoop, 300); // 启动游戏循环
document.addEventListener('keydown', handleKeyPress); // 监听键盘事件
}
// 处理键盘事件
function handleKeyPress(event) {
if (currentPiece) {
switch (event.key) {
case 'ArrowDown':
currentPiece.moveDown(); // 向下移动
break;
case 'ArrowLeft':
currentPiece.moveLeft(); // 向左移动
break;
case 'ArrowRight':
currentPiece.moveRight(); // 向右移动
break;
case 'ArrowUp':
currentPiece.rotate(); // 旋转方块
break;
}
}
}
// 游戏结束
function gameOver() {
clearInterval(gameInterval); // 清除游戏循环
document.removeEventListener('keydown', handleKeyPress); // 移除键盘事件监听
alert('游戏结束!');
}
// 绑定开始游戏按钮的点击事件
startButton.addEventListener('click', startGame);