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()
}