專案地址 -> 已上傳github
專案地址 -> 碼雲
專案演示地址
- 先畫ui介面
function draw_line() {
ctx.strokeStyle = 'black'
for (var i = w; i < canvas.height; i += w) {
ctx.moveTo(0, i)
ctx.lineTo(canvas.width, i)
ctx.stroke()
}
for (var i = w; i < canvas.width; i += w) {
ctx.moveTo(i, 0)
ctx.lineTo(i, canvas.height)
ctx.stroke()
}
// 將第一個畫布作為引數給畫下來,畫布的起始座標和寬高和第一個畫布大小一致。
ctx2.drawImage(canvas, 0, 0, canvas.width, canvas.height)
}
複製程式碼
首先先確定一件事,我們這個並不是一個
canvas
完成的,因為我們在黑塊兒移動的時候,背景是不能被清除的,而clearRect(x, y, width, height)
方法會將指定區域的所有顏色給清除掉,所以我們用了兩個canvas
,兩個canvas
是不相干涉的。所以第二個canvas
的context
物件將第一個canvas
畫布給畫了下來。
- 這是所需要的屬性介紹
// 定義變數
var w = 100 // 一個黑塊的寬度和高度
var blocks = [] // 存放所有黑塊資訊物件的陣列
var flag = false // 只有最後一個黑塊的flag才允許為true,因為遊戲規則是隻有最最後一個黑塊被點選才可以點選上一個黑塊
var speed = 2 // 黑塊的移動速度,他會隨著你獲得的分數而變快
var num = 0 // 分數
var requestId = 0 // requestAnimationFrame()方法的返回值,方便停止動畫用的
複製程式碼
- 準備開始遊戲
// 準備開始遊戲
function ready_game() {
// 在遊戲開始的時候初始化變數
blocks = []
flag = false
speed = 2
num = 0
ctx.clearRect(0, 0, canvas.width, canvas.height)
score.textContent = '得分: ' + num
ctx.fillStyle = 'black'
var x = 0
for (var i = 0; i < canvas.height; i += w) {
// 隨機生產黑塊的x軸位置
x = ~~(Math.random() * 3) * w
var obj = { x: x, y: i }
ctx.fillRect(x, i, w, w)
if (i == 300) {
ctx.fillStyle = 'white'
ctx.font = '20px consolas'
ctx.fillText('開始遊戲', x + 10, i + w / 2)
obj.flag = true
}
// 新增滑鼠點選事件
addClick_event(obj)
// 將當前黑塊物件存入陣列中
blocks.push(obj)
}
}
複製程式碼
- 新增滑鼠點選事件的方法
// 在指定位置新增click事件
function addClick_event(obj) {
canvas2.addEventListener('click', function (e) {
var cli_x = e.x - 10
var cli_y = e.y - 10
/// 如果點選中了有開始遊戲文字描述的那個黑塊
if (cli_x > obj.x && cli_x < obj.x + w && cli_y > obj.y && cli_y < obj.y + w && obj.flag && !flag) {
start_game() // 開始遊戲
} else destroy_block(e) // 銷燬黑塊
})
}
複製程式碼
- 開始遊戲
// 開始遊戲
function start_game() {
blocks.pop()
num++
score.textContent = '得分: ' + num
flag = true
// 開始動畫
animate()
}
複製程式碼
- 黑塊移動的方法
// 方塊移動
function destroy_block(e) {
if (!flag) return
var cli_x = e.x, cli_y = e.y
blocks.forEach(function (val, index) {
if (cli_x > val.x && cli_x < val.x + w && cli_y > val.y && cli_y < val.y + w) {
// 超出高度的黑塊將會被銷燬,原本是不需要這樣做的,因為黑塊只要超出高度,就代表遊戲結束了。
// 但是一開始沒有考慮到,後來又不想改了,就這樣吧~~
if (index === blocks.length - 1) {
blocks.pop()
num++
score.textContent = '得分: ' + num
}
}
})
}
複製程式碼
- 動畫方法
// 動畫
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = 'black'
// 遍歷陣列中的黑塊,不斷的增加它們的y軸值
blocks.forEach(function (val, index) {
ctx.fillRect(val.x, val.y += speed, w, w)
// if (val.y > canvas.height) {
// blocks.splice(index, 1)
// }
})
// 如果螢幕上顯示的黑塊用完了,就馬上再畫一個
if (blocks.length === 0) {
ctx.fillStyle = 'black'
var x = ~~(Math.random() * 3) * w
var obj = { x: x, y: -100 }
ctx.fillRect(obj.x, obj.y, w, w)
blocks.unshift(obj)
addClick_event(obj)
}
// 陣列中第一個黑塊的y軸值如果超過了0,那麼再它的上面再生成一個黑塊,這個和上面那個if判斷條件可以讓螢幕中不斷生成新的黑塊
if (blocks[0].y > 0) {
ctx.fillStyle = 'black'
var x = ~~(Math.random() * 3) * w
var obj = { x: x, y: -100 }
ctx.fillRect(obj.x, obj.y, w, w)
blocks.unshift(obj)
addClick_event(obj)
}
// 速度會隨分數而提高
speed = num / 10 + 2
requestId = requestAnimationFrame(animate)
if (blocks[blocks.length - 1].y >= canvas.height) {
// 結束動畫
cancelAnimationFrame(requestId)
// 遊戲結束
game_over()
}
}
複製程式碼
- 遊戲結束
// 遊戲結束
function game_over() {
alert('遊戲結束,請重新開始!')
ready_game()
}
複製程式碼