文章目錄
- 貪吃蛇專案
- 1.專案預覽
- 2.起步(涉及知識點)
- 3.原始碼
貪吃蛇專案
1.專案預覽


- 功能實作:
- 可以通過鍵盤的
上下左右控制 蛇 的移動 - 游戲剛開始隨機生成食物,蛇 默認往右走
- 在沒吃到食物前,食物靜止不動;吃到食物后,食物隨機生成
- 蛇 每吃到一個食物身體(蛇節) 增加一節
- 當蛇頭碰到地圖(方格)的邊界時,游戲結束(蛇無法再控制,靜止不動)
- 可以通過鍵盤的
2.起步(涉及知識點)
canvas : 相當于畫布;行內元素,讓方格在網頁水平居中對齊先轉塊級( display: block); 寬高設定用行內樣式,
- canvas 引數:
- getContext(‘2d’) 獲取繪制工具箱;創建 Context 物件
- fillStyle = ‘blue` or fillStyle = ‘#ccc’ 填充顏色
- fillRect 繪制矩形
fillRect(x,y,width,height) - strokeStyle 繪制畫筆的顏色
- stroke() 開始繪制
- clearRect() 擦除畫布上的內容
- moveTo 定義線條開始時的坐標
- lineTo 定義線條結束時的坐標
setInterval: 定時器,蛇 移動的原理就是,利用每一張不同位置的蛇的位置圖片,一直覆寫掉(并擦除掉上一次的圖)上一張的圖,通過定時器 1000/3 (1s執行3次這樣的操作),讓視覺效果看起來蛇平滑的移動,
addEventListener: 事件監聽(keydown)鍵盤按下監聽,利用 e.keyCode 獲取 上下左右 對應的鍵值(上: 38 下: 40 左:37 右:39)
pop(): pop() 洗掉并回傳陣列的最后一個元素
unshift(): 向陣列的開頭添加一個或多個元素,并回傳新的長度
3.原始碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>貪吃蛇繪制</title>
<!-- 設定一個背景色、 -->
<style>
canvas {
/* 在這里要居中的時候,要先轉成塊級元素 */
display: block;
margin: 0 auto;
background-color: #33cc99;
}
</style>
</head>
<body>
<!-- 準備畫布 -->
<canvas width="500" height="500" id="huabu">
</canvas>
</body>
<script>
// 通過 js 代碼來繪制網格
// 獲取畫布物件
let huabu = document.getElementById('huabu');
// 獲取繪制工具箱
let tools = huabu.getContext('2d');
// 從畫圖工具箱取出要使用的工具;
// 隨機生成x 和 y軸的坐標
let x = Math.floor(Math.random() * 20) * 25;
let y = Math.floor(Math.random() * 20) * 25;
let isEated = false;
// 每次移動的距離為一格(默認就是在這個位置出發)
let snake = [{
x: 3,
y: 0
}, {
x: 2,
y: 0
}, {
x: 1,
y: 0
}]
let directionX = 1;
let directionY = 0;
// 判斷游戲是否結束
let isGameOver = false;
document.addEventListener('keydown', (e) => {
let k = event.keyCode;
// 上: 38 下: 40 左:37 右:39
if (k === 38) {
directionX = 0
directionY = -1
} else if (k === 40) {
directionX = 0
directionY = 1
} else if (k === 37) {
directionX = -1
directionY = 0
} else if (k === 39) {
directionX = 1
directionY = 0
}
})
// 利用定時器,讓貪吃蛇動起來
setInterval(() => {
if (isGameOver) {
return
}
// 只需要將擦除 -> 重繪 的代碼放里面即可(記得每次都先擦除畫布再重繪一次)
tools.clearRect(0, 0, 500, 500);
// 注意:食物有默認的行為,剛開始是不動 的,被蛇吃后才會動
// -------------繪制食物開始------------
// 這段代碼的意思是: 只有食物被吃掉了,才會生成新的食物
if (isEated) {
// 在這里是對 x 和 y 進行重新復制,不用加 var 宣告
x = Math.floor(Math.random() * 20) * 25;
y = Math.floor(Math.random() * 20) * 25;
}
// 設定矩形的顏色
tools.fillStyle = '#fff000';
// 畫一個矩形
// fillRect(x,y,width,height)
// 不能隨機生成 x,y
// 隨機生成一個位置 Math.random() 生成一個亂數 * 25就得到一個范圍
// 問題: 如果根據 Math.random() 得到一個 [0,19] 并且 0 和 19 都能取到的值?
// 解決方案: Math.random() * 20 => [0,1) * 20 => [0,20)
// Math.floor() 向下取整
tools.fillRect(x, y, 25, 25);
// -------------繪制食物結束------------
// ----------繪制貪吃蛇開始---------
// 說明: 貪吃蛇隨著 擦除 重繪,會動起來
// 蛇已經動起來,默認向右: x + 1,y 不變
// 水平向左: x -1y 不變
// 垂直向下:y +1 x 不變
// 垂直向上: y -1 x 不變
// 新添加的節,是上一次的蛇頭位置再加1,就得到了
let oldHead = snake[0];
let newHead = {
x: oldHead.x + directionX,
y: oldHead.y + directionY
}
// 在這里做一個邊界的判定
console.log(newHead.x * 30);
// 1.如果蛇頭的 y 坐標比0小,說明游戲結束
if (newHead.y < 0 || newHead.x < 0 || newHead.x * 30 >= 600 || newHead.y * 30 >= 600) {
// 游戲就結束了
isGameOver = true;
} else {
snake.unshift(newHead); //向陣列的開頭添加一個或多個元素,并回傳新的長度
// 蛇吃食物分析:
// 當蛇頭的坐標 和 食物的坐標重合的時候,就表示食物被吃掉了
// 此時應該做兩件事
// 1. 讓 isEated 變成 true,表示食物被吃掉
// 2. 讓 蛇 的身體增加一節
if (snake[0].x * 25 === x && snake[0].y * 25 === y) {
// 當蛇頭的 x 和 Y 坐標都與 食物的 x和y坐標 重合,才證明食物被吃了
isEated = true;
// 如果蛇吃到了食物,就不執行 pop() 洗掉最后一節
} else {
// 在這里重新把 isEated 設定為 false
isEated = false; // 重新設定食物沒被吃掉
// 表示蛇沒吃到食物
snake.pop(); //
}
}
// ----------繪制貪吃蛇結束---------
// 默認移動方向為水平向右
// 繪制蛇頭的顏色,每一屆都是一個矩形
for (var i = 0; i < snake.length; i++) {
if (i === 0) {
// 只有蛇頭是紫色的,0 的時候
tools.fillStyle = 'purple'
} else {
tools.fillStyle = 'blue'
}
tools.fillRect(snake[i].x * 25, snake[i].y * 25, 25, 25);
}
// -----------繪制網格開始----------
// 找位置
// 起點坐標
// 規律: (0,25 * N + 0.5)(500, 25 * N + 0.5)
for (let i = 1; i < 20; i++) {
tools.moveTo(0, 25 * i + 0.5);
// 終點坐標
tools.lineTo(500, 25 * i + 0.5);
tools.moveTo(25 * i + 0.5, 0);
// 終點坐標
tools.lineTo(25 * i + 0.5, 500);
}
// 設定繪制的畫筆顏色
tools.strokeStyle = 'white';
// 繪制
tools.stroke();
// -----------繪制網格結束----------
}, 1000 / 3); //1000/3 為 1秒執行 3 次操作
</script>
</html>
4.同原始碼(無注釋)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>貪吃蛇繪制二次代碼編輯</title>
<style>
canvas {
display: block;
margin: 0 auto;
background-color: #33cc99;
}
</style>
</head>
<body>
<canvas width="500" height="500" id="huabu"></canvas>
</body>
<script>
let huabu = document.getElementById('huabu');
let tol = huabu.getContext('2d');
let x = Math.floor(Math.random() * 20) * 25;
let y = Math.floor(Math.random() * 20) * 25;
let isEated = false;
let snake = [{
x: 3,
y: 0
}, {
x: 2,
y: 0
}, {
x: 1,
y: 0
}];
let directionX = 1;
let directionY = 0;
let isGameOver = false;
document.addEventListener('keydown', (e) => {
let k = e.keyCode;
if (k === 38) {
directionX = 0;
directionY = -1
} else if (k === 40) {
directionX = 0;
directionY = 1
} else if (k === 37) {
directionX = -1;
directionY = 0
} else if (k === 39) {
directionX = 1;
directionY = 0
}
});
setInterval(() => {
if (isGameOver) {
return
}
tol.clearRect(0, 0, 500, 500);
if (isEated) {
x = Math.floor(Math.random() * 20) * 25;
y = Math.floor(Math.random() * 20) * 25;
}
tol.fillStyle = '#fff000';
tol.fillRect(x, y, 25, 25);
let oldHead = snake[0];
let newHead = {
x: oldHead.x + directionX,
y: oldHead.y + directionY
}
if (newHead.y < 0 || newHead.x < 0 || newHead.x * 30 >= 600 || newHead.y * 30 >= 600) {
isGameOver = true;
} else {
snake.unshift(newHead);
if (snake[0].x * 25 === x && snake[0].y * 25 === y) {
isEated = true;
} else {
isEated = false;
snake.pop();
}
}
for (var i = 0; i < snake.length; i++) {
if (i === 0) {
tol.fillStyle = 'purple';
} else {
tol.fillStyle = 'blue';
}
tol.fillRect(snake[i].x * 25, snake[i].y * 25, 25, 25);
}
for (let i = 1; i < 20; i++) {
tol.moveTo(0, 25 * i + 0.5);
tol.lineTo(500, 25 * i + 0.5);
tol.moveTo(25 * i + 0.5, 0);
tol.lineTo(25 * i + 0.5, 500);
}
tol.strokeStyle = 'white';
tol.stroke();
}, 300)
</script>
</html>
后續補全其他功能更,琢磨琢磨
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/64483.html
標籤:AI
上一篇:lucene索引檔案存盤在hadoop hdfs檔案系統的疑問
下一篇:虛機訪問
