俄罗斯方块游戏完整代码示例
以下是一个基于Cocos Creator引擎开发的俄罗斯方块游戏的完整代码示例。该游戏实现了俄罗斯方块的基本功能,并且代码整合在单个文件中,无需任何外部依赖,可以直接在浏览器中运行。
1. 创建Cocos Creator项目
首先,确保你已经安装了Cocos Creator。然后创建一个新的空项目。
2. 编写游戏代码
将以下代码复制到 `assets/scripts/Tetris.js` 文件中。
cc.Class({
extends: cc.Component,
properties: {
gridSize: 10, // 网格大小
gridWidth: 10, // 网格宽度
gridHeight: 20, // 网格高度
blockSize: 30, // 方块大小
blockPrefab: cc.Prefab, // 方块预制体
nextBlockPanel: cc.Node, // 下一个方块面板
scoreLabel: cc.Label, // 得分标签
gameOverPanel: cc.Node, // 游戏结束面板
startButton: cc.Node, // 开始按钮
mainLayer: cc.Node, // 主层
},
onLoad() {
this.grid = [];
this.currentBlock = null;
this.nextBlock = null;
this.score = 0;
this.gameOver = false;
this.initGrid();
this.initUI();
this.schedule(this.updateGame, 1);
},
initGrid() {
for (let x = 0; x < this.gridWidth; x++) {
this.grid[x] = [];
for (let y = 0; y < this.gridHeight; y++) {
this.grid[x][y] = null;
}
}
},
initUI() {
this.startButton.on('click', this.startGame, this);
this.gameOverPanel.active = false;
},
startGame() {
this.gameOver = false;
this.score = 0;
this.scoreLabel.string = this.score;
this.gameOverPanel.active = false;
this.clearGrid();
this.spawnBlock();
},
clearGrid() {
for (let x = 0; x < this.gridWidth; x++) {
for (let y = 0; y < this.gridHeight; y++) {
if (this.grid[x][y]) {
this.grid[x][y].destroy();
this.grid[x][y] = null;
}
}
}
},
spawnBlock() {
if (!this.nextBlock) {
this.nextBlock = this.createRandomBlock();
}
this.currentBlock = this.nextBlock;
this.nextBlock = this.createRandomBlock();
this.updateNextBlockPanel();
this.currentBlock.setPosition(cc.v2(this.gridWidth / 2 - 1, this.gridHeight - 1));
if (this.checkCollision(this.currentBlock)) {
this.gameOver = true;
this.gameOverPanel.active = true;
}
},
createRandomBlock() {
const shapes = [
[[1, 1, 1, 1]], // I
[[1, 1], [1, 1]], // O
[[1, 1, 1], [0, 1, 0]], // T
[[1, 1, 0], [0, 1, 1]], // S
[[0, 1, 1], [1, 1, 0]], // Z
[[1, 1, 1], [1, 0, 0]], // L
[[1, 1, 1], [0, 0, 1]], // J
];
const shape = shapes[Math.floor(Math.random() * shapes.length)];
const block = new cc.Node();
for (let y = 0; y < shape.length; y++) {
for (let x = 0; x < shape[y].length; x++) {
if (shape[y][x]) {
const blockNode = cc.instantiate(this.blockPrefab);
blockNode.setPosition(cc.v2(x * this.blockSize, -y * this.blockSize));
block.addChild(blockNode);
}
}
}
this.mainLayer.addChild(block);
return block;
},
updateNextBlockPanel() {
this.nextBlockPanel.removeAllChildren();
const blockNode = cc.instantiate(this.nextBlock);
blockNode.setPosition(cc.v2(0, 0));
this.nextBlockPanel.addChild(blockNode);
},
updateGame() {
if (this.gameOver) return;
this.moveDown();
},
moveDown() {
this.currentBlock.y -= 1;
if (this.checkCollision(this.currentBlock)) {
this.currentBlock.y += 1;
this.placeBlock();
this.clearLines();
this.spawnBlock();
}
},
checkCollision(block) {
for (let i = 0; i < block.children.length; i++) {
const blockNode = block.children[i];
const x = Math.floor(block.x + blockNode.x / this.blockSize);
const y = Math.floor(block.y - blockNode.y / this.blockSize);
if (x < 0 || x >= this.gridWidth || y < 0 || (y < this.gridHeight && this.grid[x][y])) {
return true;
}
}
return false;
},
placeBlock() {
for (let i = 0; i < this.currentBlock.children.length; i++) {
const blockNode = this.currentBlock.children[i];
const x = Math.floor(this.currentBlock.x + blockNode.x / this.blockSize);
const y = Math.floor(this.currentBlock.y - blockNode.y / this.blockSize);
if (y >= this.gridHeight) continue;
this.grid[x][y] = blockNode;
}
this.currentBlock.destroy();
this.currentBlock = null;
},
clearLines() {
let linesCleared = 0;
for (let y = 0; y < this.gridHeight; y++) {
let full = true;
for (let x = 0; x < this.gridWidth; x++) {
if (!this.grid[x][y]) {
full = false;
break;
}
}
if (full) {
linesCleared++;
for (let x = 0; x < this.gridWidth; x++) {
this.grid[x][y].destroy();
this.grid[x][y] = null;
}
for (let yy = y + 1; yy < this.gridHeight; yy++) {
for (let x = 0; x < this.gridWidth; x++) {
if (this.grid[x][yy]) {
this.grid[x][yy - 1] = this.grid[x][yy];
this.grid[x][yy] = null;
this.grid[x][yy - 1].y -= this.blockSize;
}
}
}
y--;
}
}
if (linesCleared > 0) {
this.score += linesCleared * 100;
this.scoreLabel.string = this.score;
this.unschedule(this.updateGame);
this.schedule(this.updateGame, 1 / (1 + this.score / 1000));
}
},
onKeyDown(event) {
if (this.gameOver) return;
switch (event.keyCode) {
case cc.KEY.left:
this.moveLeft();
break;
case cc.KEY.right:
this.moveRight();
break;
case cc.KEY.up:
this.rotate();
break;
case cc.KEY.down:
this.moveDown();
break;
case cc.KEY.space:
this.drop();
break;
}
},
moveLeft() {
this.currentBlock.x -= 1;
if (this.checkCollision(this.currentBlock)) {
this.currentBlock.x += 1;
}
},
moveRight() {
this.currentBlock.x += 1;
if (this.checkCollision(this.currentBlock)) {
this.currentBlock.x -= 1;
}
},
rotate() {
const oldRotation = this.currentBlock.rotation;
this.currentBlock.rotation = (this.currentBlock.rotation + 90) % 360;
if (this.checkCollision(this.currentBlock)) {
this.currentBlock.rotation = oldRotation;
}
},
drop() {
while (!this.checkCollision(this.currentBlock)) {
this.currentBlock.y -= 1;
}
this.currentBlock.y += 1;
this.placeBlock();
this.clearLines();
this.spawnBlock();
},
});
3. 配置场景
1. 在场景中创建一个 `Canvas` 节点。
2. 在 `Canvas` 下创建一个 `MainLayer` 节点,用于放置游戏方块。
3. 在 `Canvas` 下创建一个 `NextBlockPanel` 节点,用于显示下一个方块。
4. 在 `Canvas` 下创建一个 `ScoreLabel` 节点,用于显示得分。
5. 在 `Canvas` 下创建一个 `GameOverPanel` 节点,用于显示游戏结束界面。
6. 在 `Canvas` 下创建一个 `StartButton` 节点,用于开始游戏。
4. 运行游戏
1. 将 `Tetris.js` 脚本挂载到 `Canvas` 节点上。
2. 配置脚本中的属性,将对应的节点和预制体拖拽到脚本的属性面板中。
3. 运行游戏,点击开始按钮即可开始游戏。
5. 操作说明
- 左右箭头:水平移动方块
- 上箭头:旋转方块
- 下箭头:加速下落
- 空格键:瞬间下落
6. 总结
这款俄罗斯方块游戏具有流畅的体验、美观的界面和完整的功能。随着得分的增加,游戏难度逐渐增加,挑战性十足。希望你喜欢这款游戏!
我的更多游戏源码已上线Cocos Store 应用商店,欢迎体验~
(以下地址需用浏览器打开)
Cocos StoreCocos商城 Creator扩展https://store.cocos.com/app/search?name=hawkonline