Skip to main content

第5章:实战游戏开发

想不想用AI来开发游戏?让我们用Cursor来实现你的游戏开发梦想!

一 贪吃蛇快速上手

1 项目规划

让我们从最简单的游戏开始,用Cursor创建一个贪吃蛇:

你:帮我做个简单的贪吃蛇游戏,用html编写,保存为index.html 放在当前目录下面
Cursor:让我思考一下如何实现一个简单的贪吃蛇游戏...

首先需要考虑游戏的基本元素:
- 游戏区域 - 可以用canvas元素来绘制
- 蛇 - 可以用数组存储蛇身的每个部分的坐标
- 食物 - 随机位置生成
- 移动控制 - 需要监听键盘事件
- 游戏循环 - setInterval来实现

游戏逻辑需要包含:
- 初始化游戏区域和蛇的位置
- 处理移动方向
- 检测碰撞(墙壁和自身)
- 吃到食物后蛇身变长
- 游戏结束判定

hmm...让我想想代码结构:
- HTML部分很简单,只需要canvas元素
- JavaScript部分需要:
- 初始化函数
- 绘制函数
- 移动函数
- 食物生成函数
- 碰撞检测函数
- 键盘事件处理
- 游戏主循环

为了让游戏更友好,可以添加:
- 分数显示
- 游戏结束提示
- 重新开始按钮

好的,让我开始编写代码...

这是一个简单的贪吃蛇游戏实现,主要特点包括:
1. 使用Canvas绘制游戏画面
使用方向键控制蛇的移动
3. 包含分数显示功能
具有基本的碰撞检测(墙壁和自身)
游戏结束时会显示得分并自动重新开始
游戏规则:
使用键盘方向键控制蛇的移动
吃到红色食物可以得10分
撞到墙壁或自己的身体会导致游戏结束

你可以将这段代码保存为index.html文件,然后直接在浏览器中打开即可开始游戏。

2 核心代码生成

🎮 游戏主体

<!DOCTYPE html>
<html>
<head>
<title>贪吃蛇游戏</title>
<style>
canvas {
border: 2px solid black;
}
.game-container {
text-align: center;
margin-top: 20px;
}
#score {
font-size: 24px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="game-container">
<div id="score">分数: 0</div>
<canvas id="gameCanvas" width="400" height="400"></canvas>
</div>

<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');

const gridSize = 20;
const tileCount = 20;

let snake = [
{x: 10, y: 10},
];
let food = {x: 15, y: 15};
let dx = 0;
let dy = 0;
let score = 0;
let gameLoop;

// 初始化游戏
function startGame() {
snake = [{x: 10, y: 10}];
food = {x: 15, y: 15};
dx = 0;
dy = 0;
score = 0;
updateScore();
if (gameLoop) clearInterval(gameLoop);
gameLoop = setInterval(gameUpdate, 100);
}

// 更新分数显示
function updateScore() {
scoreElement.textContent = `分数: ${score}`;
}

// 游戏主循环
function gameUpdate() {
// 移动蛇
const head = {x: snake[0].x + dx, y: snake[0].y + dy};
snake.unshift(head);

// 检查是否吃到食物
if (head.x === food.x && head.y === food.y) {
score += 10;
updateScore();
generateFood();
} else {
snake.pop();
}

// 检查游戏是否结束
if (checkCollision()) {
alert(`游戏结束!最终得分:${score}`);
startGame();
return;
}

// 清空画布
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// 绘制食物
ctx.fillStyle = 'red';
ctx.fillRect(food.x * gridSize, food.y * gridSize, gridSize-2, gridSize-2);

// 绘制蛇
ctx.fillStyle = 'green';
snake.forEach(segment => {
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize-2, gridSize-2);
});
}

// 生成新的食物
function generateFood() {
food = {
x: Math.floor(Math.random() * tileCount),
y: Math.floor(Math.random() * tileCount)
};
// 确保食物不会生成在蛇身上
if (snake.some(segment => segment.x === food.x && segment.y === food.y)) {
generateFood();
}
}

// 碰撞检测
function checkCollision() {
const head = snake[0];

// 检查是否撞墙
if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) {
return true;
}

// 检查是否撞到自己
for (let i = 1; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
return true;
}
}

return false;
}

// 键盘控制
document.addEventListener('keydown', event => {
switch (event.key) {
case 'ArrowUp':
if (dy === 0) {
dx = 0;
dy = -1;
}
break;
case 'ArrowDown':
if (dy === 0) {
dx = 0;
dy = 1;
}
break;
case 'ArrowLeft':
if (dx === 0) {
dx = -1;
dy = 0;
}
break;
case 'ArrowRight':
if (dx === 0) {
dx = 1;
dy = 0;
}
break;
}
});

// 开始游戏
startGame();
</script>
</body>
</html>

3 运行效果

alt text

4 快速迭代优化

你:蛇的移动有点卡顿
Cursor:让我思考一下如何优化贪吃蛇游戏的移动流畅性...

首先,卡顿的原因可能是因为游戏循环的更新频率不够高。当前的设置是每100毫秒更新一次,这可能导致移动不够平滑。可以考虑将这个时间间隔缩短,比如设置为每50毫秒更新一次。

其次,可能还需要检查绘制的效率,确保每次绘制时只更新必要的部分,而不是重绘整个画布。虽然在这个简单的实现中,重绘整个画布是常见的做法,但在更复杂的游戏中,优化绘制逻辑是很重要的。

最后,确保键盘事件的处理不会造成延迟。可以考虑使用`requestAnimationFrame`来替代`setInterval`,这样可以让浏览器在每次重绘时调用游戏更新函数,从而提高流畅度。

好的,让我来修改代码以提高流畅性...
...
这样修改后,游戏的移动应该会更加流畅。你可以将这些更改应用到你的代码中,看看效果如何。

💡 特色功能

  • 渐进难度:吃到食物后逐渐加快速度
  • 特殊食物:随机出现加分道具
  • 障碍物:随机生成墙壁增加难度
  • 计分板:记录最高分

🌟 开发技巧

  1. 先实现最基础的移动和碰撞
  2. 逐步添加食物和得分系统
  3. 最后优化视觉效果和操作手感

二 俄罗斯方块奇迹

1 需求分析与规划

首先,让我们用自然语言告诉Cursor我们想要什么:

你:我想开发一个经典俄罗斯方块,用html编写,保存为index.html 放在当前目录下面
Cursor:让我思考一下如何实现一个经典的俄罗斯方块游戏...

首先,俄罗斯方块的基本元素包括:
- 游戏区域 - 可以使用canvas元素来绘制
- 方块 - 需要定义不同形状的方块(如I、O、T、L、J、S、Z)
- 方块的移动和旋转 - 需要监听键盘事件来控制
- 游戏循环 - 使用setInterval或requestAnimationFrame来更新游戏状态
- 碰撞检测 - 检查方块是否与边界或其他方块重叠
- 消行 - 当一行填满时,消除该行并更新分数

游戏逻辑需要包含:
- 初始化游戏区域和方块
- 处理方块的下落、移动和旋转
- 检测行是否填满并消除
- 更新分数和游戏状态
- 游戏结束判定

为了让游戏更友好,可以添加:
- 分数显示
- 游戏结束提示
- 重新开始按钮

好的,让我开始编写代码...

这是一个简单的俄罗斯方块游戏实现,主要特点包括:
使用Canvas绘制游戏画面。
2. 支持方块的移动和旋转。
3. 检测行是否填满并消除。
显示分数。
游戏结束时会显示得分并重置游戏。
你可以将这段代码保存为index.html文件,然后直接在浏览器中打开即可开始游戏。

2 代码生成与实现

🎮 核心代码生成


<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>经典俄罗斯方块</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
canvas {
border: 2px solid black;
background-color: white;
}
#score {
text-align: center;
font-size: 24px;
margin-top: 10px;
}
</style>
</head>
<body>
<div>
<canvas id="gameCanvas" width="300" height="600"></canvas>
<div id="score">分数: 0</div>
</div>

<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');

const gridSize = 30; // 每个方块的大小
const rows = canvas.height / gridSize; // 行数
const cols = canvas.width / gridSize; // 列数

let board = Array.from({ length: rows }, () => Array(cols).fill(0));
let score = 0;
let currentPiece;
let dropInterval = 1000; // 方块下落的时间间隔
let dropTime = 0;

// 定义方块形状
const pieces = [
[[1, 1, 1, 1]], // I
[[1, 1], [1, 1]], // O
[[0, 1, 0], [1, 1, 1]], // T
[[1, 0, 0], [1, 1, 1]], // L
[[0, 0, 1], [1, 1, 1]], // J
[[0, 1, 1], [1, 1, 0]], // S
[[1, 1, 0], [0, 1, 1]], // Z
];

// 随机生成方块
function randomPiece() {
const index = Math.floor(Math.random() * pieces.length);
return {
shape: pieces[index],
x: Math.floor(cols / 2) - 1,
y: 0,
};
}

// 绘制方块
function drawPiece(piece) {
piece.shape.forEach((row, y) => {
row.forEach((value, x) => {
if (value) {
ctx.fillStyle = 'blue';
ctx.fillRect((piece.x + x) * gridSize, (piece.y + y) * gridSize, gridSize - 1, gridSize - 1);
}
});
});
}

// 检查碰撞
function collide(board, piece) {
for (let y = 0; y < piece.shape.length; y++) {
for (let x = 0; x < piece.shape[y].length; x++) {
if (piece.shape[y][x] && (board[piece.y + y] && board[piece.y + y][piece.x + x]) !== 0) {
return true;
}
}
}
return false;
}

// 将方块放入棋盘
function merge(board, piece) {
piece.shape.forEach((row, y) => {
row.forEach((value, x) => {
if (value) {
board[piece.y + y][piece.x + x] = 1;
}
});
});
}

// 消行
function removeFullLines() {
let linesToRemove = [];
for (let y = 0; y < rows; y++) {
if (board[y].every(value => value !== 0)) {
linesToRemove.push(y);
}
}
linesToRemove.forEach(y => {
board.splice(y, 1);
board.unshift(Array(cols).fill(0));
score += 10;
});
scoreElement.textContent = `分数: ${score}`;
}

// 更新游戏状态
function update() {
dropTime += 16; // 每帧大约16毫秒
if (dropTime > dropInterval) {
currentPiece.y++;
if (collide(board, currentPiece)) {
currentPiece.y--;
merge(board, currentPiece);
removeFullLines();
currentPiece = randomPiece();
if (collide(board, currentPiece)) {
alert(`游戏结束!最终得分:${score}`);
resetGame();
}
}
dropTime = 0;
}
}

// 重置游戏
function resetGame() {
board = Array.from({ length: rows }, () => Array(cols).fill(0));
score = 0;
scoreElement.textContent = `分数: ${score}`;
currentPiece = randomPiece();
}

// 键盘控制
document.addEventListener('keydown', event => {
switch (event.key) {
case 'ArrowLeft':
currentPiece.x--;
if (collide(board, currentPiece)) currentPiece.x++;
break;
case 'ArrowRight':
currentPiece.x++;
if (collide(board, currentPiece)) currentPiece.x--;
break;
case 'ArrowDown':
currentPiece.y++;
if (collide(board, currentPiece)) currentPiece.y--;
break;
case 'ArrowUp':
// 旋转方块
const rotated = currentPiece.shape[0].map((_, index) => currentPiece.shape.map(row => row[index]).reverse());
const originalShape = currentPiece.shape;
currentPiece.shape = rotated;
if (collide(board, currentPiece)) {
currentPiece.shape = originalShape; // 旋转失败,恢复原形
}
break;
}
});

// 游戏主循环
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
board.forEach((row, y) => {
row.forEach((value, x) => {
if (value) {
ctx.fillStyle = 'blue';
ctx.fillRect(x * gridSize, y * gridSize, gridSize - 1, gridSize - 1);
}
});
});
drawPiece(currentPiece);
update();
requestAnimationFrame(draw);
}

// 启动游戏
currentPiece = randomPiece();
draw();
</script>
</body>
</html>

3 运行效果

alt text

4 调试与优化

🎯 反馈调试

你:方块下落速度感觉太快了
Cursor:我来帮你调整:
1. 修改下落间隔
2. 添加难度递进
3. 加入速度控制选项

🌟 进阶提示:

  1. 善用Cursor的代码生成能力
  2. 让AI帮你重构和优化代码
  3. 使用版本控制追踪开发进度
  4. 及时保存和备份项目

记住:游戏开发是个循序渐进的过程,Cursor可以是你的得力助手,但创意和游戏性还需要你自己把握!

Monica AI助手

Monica (莫妮卡)是一款全功能的AI助手,配备了最先进的AI模型,如GPT-4、Claude、Bard等,用于帮助用户聊天、搜索、写作、翻译等多种功能。

立即体验

CursorAI编程知识星球

我正在「史密斯DeepSeekAI社」和朋友们讨论有趣的话题,你⼀起来吧?

立刻查看