本文为AI开发实例,所有代码均为AI生成,红色字体为本人开发中思考过程,仅供参考。 使用工具:智谱清言 项目:贪吃蛇游戏开发 时间:2024年11月10日15:52:08 用户:祎果 AI:ChatGLM
开门见山提问开始
用户_祎果
使用H5和js写一个贪吃蛇小游戏
ChatGLM
当然可以。以下是一个简单的贪吃蛇小游戏的基本代码,使用HTML5和JavaScript实现。这个例子中,我们将创建一个基本的游戏界面,控制蛇的移动,以及食物的随机生成和蛇的增长逻辑。 HTML部分(index.html):
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>贪吃蛇小游戏</title>
<style>
#gameCanvas {
border: 1px solid black;
background-color: #ddd;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<script src="game.js"></script>
</body>
</html>
JavaScript部分(game.js):
const canvas = document.getElementById('gameCanvas')
const ctx = canvas.getContext('2d')
const scale = 20
const rows = canvas.height / scale
const columns = canvas.width / scale
let snake
;(function setup() {
snake = new Snake()
fruit = new Fruit()
fruit.pickLocation()
window.setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
fruit.draw()
snake.update()
snake.draw()
if (snake.eat(fruit)) {
fruit.pickLocation()
}
snake.checkCollision()
document.querySelector('#score').innerText = snake.total
}, 250)
})()
window.addEventListener('keydown', evt => {
const direction = evt.key.replace('Arrow', '')
snake.changeDirection(direction)
})
function Snake() {
this.x = 0
this.y = 0
this.xSpeed = scale * 1
this.ySpeed = 0
this.total = 0
this.tail = []
this.draw = function () {
ctx.fillStyle = '#FFFFFF'
for (let i = 0; i < this.tail.length; i++) {
ctx.fillRect(this.tail[i].x, this.tail[i].y, scale, scale)
}
ctx.fillRect(this.x, this.y, scale, scale)
}
this.update = function () {
for (let i = 0; i < this.tail.length - 1; i++) {
this.tail[i] = this.tail[i + 1]
}
this.tail[this.total - 1] = {x: this.x, y: this.y}
this.x += this.xSpeed
this.y += this.ySpeed
if (this.x > canvas.width) {
this.x = 0
}
if (this.y > canvas.height) {
this.y = 0
}
if (this.x < 0) {
this.x = canvas.width
}
if (this.y < 0) {
this.y = canvas.height
}
}
this.changeDirection = function (direction) {
switch (direction) {
case 'Up':
this.xSpeed = 0
this.ySpeed = -scale * 1
break
case 'Down':
this.xSpeed = 0
this.ySpeed = scale * 1
break
case 'Left':
this.xSpeed = -scale * 1
this.ySpeed = 0
break
case 'Right':
this.xSpeed = scale * 1
this.ySpeed = 0
break
}
}
this.eat = function (fruit) {
if (this.x === fruit.x && this.y === fruit.y) {
this.total++
return true
}
return false
}
this.checkCollision = function () {
for (let i = 0; i < this.tail.length; i++) {
if (this.x === this.tail[i].x && this.y === this.tail[i].y) {
this.total = 0
this.tail = []
}
}
}
}
function Fruit() {
this.x
this.y
this.pickLocation = function () {
this.x = (Math.floor(Math.random() * rows - 1) + 1) * scale
this.y = (Math.floor(Math.random() * columns - 1) + 1) * scale
}
this.draw = function () {
ctx.fillStyle = '#FF0000'
ctx.fillRect(this.x, this.y, scale, scale)
}
}
这个代码实现了一个基本的贪吃蛇游戏,包括蛇的移动、食物的随机生成以及蛇吃到食物后的增长。你可以在此基础上添加更多的功能,比如分数显示、游戏结束逻辑等。
用户_祎果
有一个bug,如果我按下前进方向的反方向(例如朝右走的时候按下左)蛇的长度会缩短直到变成1,解决一下这个bug
ChatGLM
确实,按照当前的代码,如果蛇朝一个方向移动,然后立即按下相反的方向,蛇会吃掉自己的尾巴,导致长度缩短。为了修复这个bug,我们需要在改变方向时添加一个检查,确保新的方向不是当前移动方向的反方向。
以下是修复后的changeDirection方法:
this.changeDirection = function (direction) {
const oppositeDirections = {
Up: 'Down',
Down: 'Up',
Left: 'Right',
Right: 'Left',
}
// 防止蛇掉头
if (oppositeDirections[direction] !== this.currentDirection) {
switch (direction) {
case 'Up':
this.xSpeed = 0
this.ySpeed = -scale * 1
break
case 'Down':
this.xSpeed = 0
this.ySpeed = scale * 1
break
case 'Left':
this.xSpeed = -scale * 1
this.ySpeed = 0
break
case 'Right':
this.xSpeed = scale * 1
this.ySpeed = 0
break
}
this.currentDirection = direction // 更新当前方向
}
}
在Snake构造函数中,我们需要添加一个currentDirection属性来跟踪蛇当前的移动方向:
function Snake() {
this.currentDirection = 'Right' // 初始化当前方向
this.x = 0
this.y = 0
this.xSpeed = scale * 1
this.ySpeed = 0
this.total = 0
this.tail = []
// ... 其他代码保持不变
}
这样,changeDirection方法现在会检查蛇是否尝试向相反方向移动,并且在这种情况下不会改变方向。这样就可以防止蛇吃掉自己的尾巴了。
用户_祎果
能加个暂停功能吗?
ChatGLM
当然可以。为了添加暂停功能,我们可以在JavaScript中添加一个变量来跟踪游戏是否暂停,并提供一个方法来切换暂停状态。同时,我们还需要修改游戏循环,使其在游戏暂停时不更新游戏状态。 以下是添加暂停功能的步骤:
- 在
Snake构造函数中添加一个paused属性。 - 添加一个
togglePause方法来切换暂停状态。 - 修改
gameLoop函数,使其在游戏暂停时不执行更新。 以下是完整的代码示例,包括了暂停功能:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>贪吃蛇小游戏</title>
<style>
#gameCanvas {
border: 1px solid black;
background-color: #ddd;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<script>
var canvas = document.getElementById('gameCanvas')
var ctx = canvas.getContext('2d')
var scale = 20
var rows = canvas.height / scale
var columns = canvas.width / scale
function Snake() {
this.x = 0
this.y = 0
this.xSpeed = scale * 1
this.ySpeed = 0
this.total = 0
this.tail = []
this.currentDirection = 'Right'
this.paused = false // 添加暂停状态
}
Snake.prototype.draw = function () {
ctx.fillStyle = '#000000'
for (var i = 0; i < this.tail.length; i++) {
ctx.fillRect(this.tail[i].x, this.tail[i].y, scale, scale)
}
ctx.fillRect(this.x, this.y, scale, scale)
}
Snake.prototype.update = function () {
if (!this.paused) {
// 检查是否暂停
for (var i = 0; i < this.tail.length - 1; i++) {
this.tail[i] = this.tail[i + 1]
}
if (this.total >= 1) {
this.tail[this.total - 1] = {x: this.x, y: this.y}
}
this.x += this.xSpeed
this.y += this.ySpeed
}
}
Snake.prototype.changeDirection = function (direction) {
// ...(之前的代码保持不变)
}
Snake.prototype.togglePause = function () {
this.paused = !this.paused // 切换暂停状态
}
var snake = new Snake()
var food = {
x: (Math.floor(Math.random() * rows - 1) + 1) * scale,
y: (Math.floor(Math.random() * columns - 1) + 1) * scale,
}
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
snake.update()
snake.draw()
food.draw()
// ...(其他游戏逻辑保持不变)
setTimeout(gameLoop, 1000 / 10) // 10 updates per second
}
gameLoop()
// 添加键盘事件监听器
window.addEventListener('keydown', function (e) {
var direction = ''
switch (e.keyCode) {
case 37:
direction = 'Left'
break
case 38:
direction = 'Up'
break
case 39:
direction = 'Right'
break
case 40:
direction = 'Down'
break
case 32: // 按空格键暂停/继续游戏
snake.togglePause()
return // 不需要改变方向
}
snake.changeDirection(direction)
})
</script>
</body>
</html>
在这个代码中,我们添加了一个togglePause方法来切换paused属性,并且在update方法中检查paused属性,以确定是否应该更新蛇的位置。我们还添加了一个键盘事件监听器来监听空格键(键码为32),当按下空格键时,调用togglePause方法来暂停或继续游戏。
用户_祎果
还是按照之前分开game.js和index.html的方式写吧
这里是因为写的过程中格式变了,出于保持格式一致和考虑单文件太长AI容易出bug两个原因,我让AI修改了格式
ChatGLM
当然可以。下面是按照您的要求,将游戏逻辑分离到game.js文件中的代码。
首先是index.html文件:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>贪吃蛇小游戏</title>
<style>
#gameCanvas {
border: 1px solid black;
background-color: #ddd;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<script src="game.js"></script>
</body>
</html>
接下来是game.js文件的内容:
var canvas = document.getElementById('gameCanvas')
var ctx = canvas.getContext('2d')
var scale = 20
var rows = canvas.height / scale
var columns = canvas.width / scale
function Snake() {
this.x = 0
this.y = 0
this.xSpeed = scale * 1
this.ySpeed = 0
this.total = 0
this.tail = []
this.paused = false // 添加暂停状态
}
Snake.prototype.draw = function () {
ctx.fillStyle = '#000000'
for (var i = 0; i < this.tail.length; i++) {
ctx.fillRect(this.tail[i].x, this.tail[i].y, scale, scale)
}
ctx.fillRect(this.x, this.y, scale, scale)
}
Snake.prototype.update = function () {
if (!this.paused) {
// 检查是否暂停
for (var i = 0; i < this.tail.length - 1; i++) {
this.tail[i] = this.tail[i + 1]
}
if (this.total >= 1) {
this.tail[this.total - 1] = {x: this.x, y: this.y}
}
this.x += this.xSpeed
this.y += this.ySpeed
}
}
Snake.prototype.changeDirection = function (direction) {
switch (direction) {
case 'Left':
if (this.currentDirection !== 'Right') {
this.xSpeed = -scale
this.ySpeed = 0
this.currentDirection = direction
}
break
case 'Up':
if (this.currentDirection !== 'Down') {
this.xSpeed = 0
this.ySpeed = -scale
this.currentDirection = direction
}
break
case 'Right':
if (this.currentDirection !== 'Left') {
this.xSpeed = scale
this.ySpeed = 0
this.currentDirection = direction
}
break
case 'Down':
if (this.currentDirection !== 'Up') {
this.xSpeed = 0
this.ySpeed = scale
this.currentDirection = direction
}
break
}
}
Snake.prototype.togglePause = function () {
this.paused = !this.paused // 切换暂停状态
}
function Food() {
this.x = (Math.floor(Math.random() * rows - 1) + 1) * scale
this.y = (Math.floor(Math.random() * columns - 1) + 1) * scale
this.draw = function () {
ctx.fillStyle = '#FF0000'
ctx.fillRect(this.x, this.y, scale, scale)
}
}
var snake = new Snake()
var food = new Food()
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
snake.update()
snake.draw()
food.draw()
// Check for collision with food
if (snake.x === food.x && snake.y === food.y) {
snake.total++
food = new Food()
}
// Check for collision with self
for (var i = 0; i < snake.tail.length; i++) {
if (snake.x === snake.tail[i].x && snake.y === snake.tail[i].y) {
snake.total = 0
snake.tail = []
}
}
setTimeout(gameLoop, 1000 / 10) // 10 updates per second
}
gameLoop()
// Add keyboard event listener
window.addEventListener('keydown', function (e) {
var direction = ''
switch (e.keyCode) {
case 37:
direction = 'Left'
break
case 38:
direction = 'Up'
break
case 39:
direction = 'Right'
break
case 40:
direction = 'Down'
break
case 32: // Space key to pause/resume the game
snake.togglePause()
return // No need to change direction
}
snake.changeDirection(direction)
})
这样,游戏的逻辑就被封装在了game.js文件中,而index.html
用户_祎果
能加个得分显示吗?
ChatGLM
当然可以。我们可以在HTML中添加一个元素来显示得分,并在JavaScript中更新这个得分。以下是添加得分显示的完整代码。
首先是更新后的index.html文件:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>贪吃蛇小游戏</title>
<style>
#gameCanvas {
border: 1px solid black;
background-color: #ddd;
}
#score {
font-family: Arial, sans-serif;
font-size: 24px;
margin-top: 10px;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div id="score">得分: 0</div>
<script src="game.js"></script>
</body>
</html>
接下来是game.js文件的更新:
var canvas = document.getElementById('gameCanvas')
var ctx = canvas.getContext('2d')
var scoreElement = document.getElementById('score') // 获取得分元素
var scale = 20
var rows = canvas.height / scale
var columns = canvas.width / scale
var score = 0 // 初始化得分
function Snake() {
// ... Snake的其余代码保持不变
}
// ... Snake的方法保持不变
function Food() {
// ... Food的其余代码保持不变
}
var snake = new Snake()
var food = new Food()
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
snake.update()
snake.draw()
food.draw()
// Check for collision with food
if (snake.x === food.x && snake.y === food.y) {
snake.total++
score += 10 // 每次吃到食物得分增加10
updateScore() // 更新得分显示
food = new Food()
}
// Check for collision with self
for (var i = 0; i < snake.tail.length; i++) {
if (snake.x === snake.tail[i].x && snake.y === snake.tail[i].y) {
snake.total = 0
score = 0 // 重置得分
updateScore() // 更新得分显示
snake.tail = []
}
}
setTimeout(gameLoop, 1000 / 10) // 10 updates per second
}
gameLoop()
// Update the score display
function updateScore() {
scoreElement.textContent = '得分: ' + score
}
// Add keyboard event listener
window.addEventListener('keydown', function (e) {
// ... 键盘事件监听器的其余代码保持不变
})
现在,当蛇吃到食物时,得分会增加,并且在页面上显示当前的得分。如果蛇撞到自己,得分会重置为0。通过updateScore函数,我们可以确保得分始终在页面上正确显示。
用户_祎果
记录回到我让你添加暂停功能的位置
这一步是因为前面格式变了,然后出现了bug,无法正常运行了,所以这里让AI把思维回退一下到稳定的位置重来。这里重来也是考虑到这是一个完整的实例,多覆盖一些情况,正常开发遇到这种情况可以复制代码新建对话。
ChatGLM
当然,让我们回到添加暂停功能的位置,并在此基础上添加得分显示。以下是更新后的代码,包括暂停功能和得分显示。
首先是index.html文件:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>贪吃蛇小游戏</title>
<style>
#gameCanvas {
border: 1px solid black;
background-color: #ddd;
}
#score {
font-family: Arial, sans-serif;
font-size: 24px;
margin-top: 10px;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div id="score">得分: 0</div>
<script src="game.js"></script>
</body>
</html>
接下来是game.js文件,包括暂停功能和得分显示:
var canvas = document.getElementById('gameCanvas')
var ctx = canvas.getContext('2d')
var scoreElement = document.getElementById('score') // 获取得分元素
var scale = 20
var rows = canvas.height / scale
var columns = canvas.width / scale
var score = 0 // 初始化得分
var paused = false // 初始化暂停状态
function Snake() {
// ... Snake的其余代码保持不变
}
// ... Snake的方法保持不变
function Food() {
// ... Food的其余代码保持不变
}
var snake = new Snake()
var food = new Food()
function gameLoop() {
if (!paused) {
// 如果游戏没有暂停,则更新游戏
ctx.clearRect(0, 0, canvas.width, canvas.height)
snake.update()
snake.draw()
food.draw()
// Check for collision with food
if (snake.x === food.x && snake.y === food.y) {
snake.total++
score += 10 // 每次吃到食物得分增加10
updateScore() // 更新得分显示
food = new Food()
}
// Check for collision with self
for (var i = 0; i < snake.tail.length; i++) {
if (snake.x === snake.tail[i].x && snake.y === snake.tail[i].y) {
snake.total = 0
score = 0 // 重置得分
updateScore() // 更新得分显示
snake.tail = []
}
}
}
setTimeout(gameLoop, 1000 / 10) // 10 updates per second
}
gameLoop()
// Update the score display
function updateScore() {
scoreElement.textContent = '得分: ' + score
}
// Toggle pause state
function togglePause() {
paused = !paused
}
// Add keyboard event listener
window.addEventListener('keydown', function (e) {
var direction = ''
switch (e.keyCode) {
case 37:
direction = 'Left'
break
case 38:
direction = 'Up'
break
case 39:
direction = 'Right'
break
case 40:
direction = 'Down'
break
case 32: // Space key to pause/resume the game
togglePause()
return // No need to change direction
}
if (direction && snake.direction !== direction && snake.direction !== oppositeDirection(direction)) {
snake.changeDirection(direction)
}
})
// Helper function to get the opposite direction
function oppositeDirection(direction) {
switch (direction) {
case 'Up':
return 'Down'
case 'Down':
return 'Up'
case 'Left':
return 'Right'
case 'Right':
return 'Left'
}
}
在这个版本的game.js中,我们添加了一个paused变量来跟踪游戏是否暂停,并定义了一个togglePause函数来切换暂停状态。在gameLoop函数中,我们检查paused变量,如果游戏没有暂停,则继续更新游戏状态。此外,我们还添加了一个得分显示,并在蛇吃到食物时更新得分。
用户_祎果
请把你刚刚的回答,var的使用换成const和let
这里是写完代码后我观察发现关键字换了,出于规范让他修改了一下,不自己修改是为了保持AI的思维连贯性,否则就要复制代码刷新AI的思路了。
ChatGLM
当然,以下是使用const和let替换var的代码:
首先是index.html文件,它保持不变:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>贪吃蛇小游戏</title>
<style>
#gameCanvas {
border: 1px solid black;
background-color: #ddd;
}
#score {
font-family: Arial, sans-serif;
font-size: 24px;
margin-top: 10px;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div id="score">得分: 0</div>
<script src="game.js"></script>
</body>
</html>
接下来是更新后的game.js文件:
const canvas = document.getElementById('gameCanvas')
const ctx = canvas.getContext('d')
const scoreElement = document.getElementById('score') // 获取得分元素
const scale = 20
const rows = canvas.height / scale
const columns = canvas.width / scale
let score = 0 // 初始化得分
let paused = false // 初始化暂停状态
function Snake() {
// ... Snake的其余代码保持不变
}
// ... Snake的方法保持不变
function Food() {
// ... Food的其余代码保持不变
}
const snake = new Snake()
const food = new Food()
function gameLoop() {
if (!paused) {
// 如果游戏没有暂停,则更新游戏
ctx.clearRect(0, 0, canvas.width, canvas.height)
snake.update()
snake.draw()
food.draw()
// Check for collision with food
if (snake.x === food.x && snake.y === food.y) {
snake.total++
score += 10 // 每次吃到食物得分增加10
updateScore() // 更新得分显示
food = new Food()
}
// Check for collision with self
for (let i = 0; i < snake.tail.length; i++) {
if (snake.x === snake.tail[i].x && snake.y === snake.tail[i].y) {
snake.total = 0
score = 0 // 重置得分
updateScore() // 更新得分显示
snake.tail = []
}
}
}
setTimeout(gameLoop, 1000 / 10) // 10 updates per second
}
gameLoop()
// Update the score display
function updateScore() {
scoreElement.textContent = '得分: ' + score
}
// Toggle pause state
function togglePause() {
paused = !paused
}
// Add keyboard event listener
window.addEventListener('keydown', function (e) {
let direction = ''
switch (e.keyCode) {
case 37:
direction = 'Left'
break
case 38:
direction = 'Up'
break
case 39:
direction = 'Right'
break
case 40:
direction = 'Down'
break
case 32: // Space key to pause/resume the game
togglePause()
return // No need to change direction
}
if (direction && snake.direction !== direction && snake.direction !== oppositeDirection(direction)) {
snake.changeDirection(direction)
}
})
// Helper function to get the opposite direction
function oppositeDirection(direction) {
switch (direction) {
case 'Up':
return 'Down'
case 'Down':
return 'Up'
case 'Left':
return 'Right'
case 'Right':
return 'Left'
}
}
在这个版本的代码中,我使用了const来声明那些不会改变的变量,如canvas、ctx、scoreElement、scale、rows、columns、snake和food。而let用于声明那些在代码执行过程中可能会改变的变量,如score、paused和循环中的i。使用const和let可以提高代码的可读性和可维护性,并且let和const有块级作用域,而var是函数作用域。
用户_祎果
这是现在的代码,运行发现不生成食物,检查并修改:
《此处省略代码……》
这一步是用AI给的最新代码无法运行,所以我把代码复制过来让他检查了,正常开发的话可以看到控制台有报错,解决也不难,但是我做这个实例是演示AI功能,所以假设用户完全不懂不修改任何代码。
ChatGLM
在提供的代码中,Food类的pickLocation方法没有被调用,这就是为什么食物没有被生成的原因。我们需要在创建新的食物实例时调用pickLocation方法来为食物设置一个随机的位置。以下是修正后的代码段:
在gameLoop函数中,当蛇吃到食物后,应该调用food.pickLocation()来为新生成的食物设置位置:
function gameLoop() {
if (!paused) {
// 如果游戏没有暂停,则更新游戏
ctx.clearRect(0, 0, canvas.width, canvas.height)
snake.update()
snake.draw()
food.draw()
// Check for collision with food
if (snake.x === food.x && snake.y === food.y) {
snake.total++
score += 10 // 每次吃到食物得分增加10
updateScore() // 更新得分显示
food = new Food() // 创建新的食物实例
food.pickLocation() // 为新食物设置位置
}
// Check for collision with self
for (let i = 0; i < snake.tail.length; i++) {
if (snake.x === snake.tail[i].x && snake.y === snake.tail[i].y) {
snake.total = 0
score = 0 // 重置得分
updateScore() // 更新得分显示
snake.tail = []
}
}
}
setTimeout(gameLoop, 1000 / 10) // 10 updates per second
}
此外,为了确保食物不会生成在蛇的身体上,我们可以在Food类的pickLocation方法中添加一个检查,确保生成的食物位置不在蛇的身体上:
function Food() {
this.pickLocation = function () {
let locationFound = false
while (!locationFound) {
this.x = (Math.floor(Math.random() * rows - 1) + 1) * scale
this.y = (Math.floor(Math.random() * columns - 1) + 1) * scale
locationFound = true // 假设位置是好的,除非下面的循环证明不是
// 检查食物是否生成在蛇的身体上
for (let i = 0; i < snake.tail.length; i++) {
if (this.x === snake.tail[i].x && this.y === snake.tail[i].y) {
locationFound = false // 如果食物在蛇的身体上,重新寻找位置
break
}
}
}
}
// ...其余Food类的代码保持不变
}
这样,每次生成新的食物时,都会确保它不会出现在蛇的身体上。
这里AI不仅找到了问题,还顺手优化了之前未发现的bug,好评。
用户_祎果
以下是修改后的Food和gameloop,还是没有生成食物:
《此处省略代码……》
这里是还有问题,因为咱不懂代码,所以让AI来解决。
ChatGLM
代码看起来是正确的,但是食物没有被生成的原因可能是因为rows和columns的计算方式不正确。在初始化变量时,rows和columns应该是基于scale来计算的,确保食物生成在网格内。让我们来检查并修正这部分代码。
首先,确保rows和columns的计算是正确的:
const rows = Math.floor(canvas.height / scale)
const columns = Math.floor(canvas.width / scale)
然后,在Food类的pickLocation方法中,确保食物的坐标是在网格内:
this.pickLocation = function () {
let locationFound = false
while (!locationFound) {
this.x = (Math.floor(Math.random() * (columns - 1)) + 1) * scale
this.y = (Math.floor(Math.random() * (rows - 1)) + 1) * scale
locationFound = true
for (let i = 0; i < snake.tail.length; i++) {
if (this.x === snake.tail[i].x && this.y === snake.tail[i].y) {
locationFound = false
break
}
}
}
}
注意,在计算this.x和this.y时,我们使用了(columns - 1)和(rows - 1)来确保食物不会生成在边界之外。
最后,确保在游戏开始时,食物的位置被初始化:
let food = new Food()
food.pickLocation() // 初始化食物位置
现在,让我们将这些修改整合到一起,并确保gameLoop函数在页面加载时被调用:
// ... 其他代码保持不变
// 初始化食物位置
let food = new Food()
food.pickLocation()
// 开始游戏循环
gameLoop()
确保你的HTML元素<canvas>具有正确的宽度和高度,这样rows和columns的计算才会正确。例如:
<canvas id="gameCanvas" width="400" height="400"></canvas>
如果上述修改后食物仍然没有被生成,请检查控制台是否有错误,并确保scale、canvas.width和canvas.height的值是正确的。如果控制台没有错误,食物应该会在游戏开始时被生成,并且在蛇吃到食物后重新生成。
这里AI发现了问题,然后我观察AI的回答发现是没有初始化食物位置,于是采纳了初始化食物位置这一行代码。
用户_祎果
加上初始化初始化食物位置后成功了
这里是完成了,出于礼貌回复了一下。
ChatGLM
太好了,我很高兴听到这个问题已经被解决了!如果你在开发过程中遇到任何其他问题,或者想要添加更多功能到你的贪吃蛇游戏中,比如增加难度级别、改进用户界面、添加音效等,随时欢迎你提问。祝你在编程和游戏开发中取得更多的进步!
AI情绪价值拉满。