利用html5的canvas可以做出很多非常酷炫的效果,今天就利用canvas绘制一个见缝插针的小游戏,游戏效果如图:
首先:
我们新建一个html文件 使用canvas标签
<canvas class="canvas" width="600" height="600px">canvas>
画布的大小 由个人决定 如果需要改变大小,小球的坐标可能需要重新寻找。
接下来就开始写javascript代码
定义接下来所需要的数值,大圆半径,大圆的坐标,链接大圆与小圆之间的线条长度,旋转小球的半径,关卡数,旋转小球的数组,等待小球的数组,以及小球的数量和旋转角度等;
var canvas = document.querySelector('.canvas');
var cxt = canvas.getContext('2d');
//var Rballs = parseInt(Math.random()*10+1);
//var RballWait = parseInt(Math.random()*20+1);
var arcX = 300; //大圆X
var arcY = 160;//大圆Y
var arcR = 30;//大圆半径
var lineWidth = 100;//线条长度
var radius = 10;//小球半径
//游戏的等级 速度 等待小球
var LevelSpeed = [
{
"speed": 1,//速度
"ballnum": 3,//旋转小球
"waitNum": 5//等待小球
},
{
"speed": 1.5,
"ballnum": 3,
"waitNum": 6
},
{
"speed": 2,
"ballnum": 4,
"waitNum": 7
},
{
"speed": 2.5,
"ballnum": 4,
"waitNum": 7
}
];
var balls = []; //定义一个旋转的小球数组
var waitBalls = []; //等待小球的数组
//定义关卡
var level;
if (parseInt(window.location.href.split('#')[1])) {
level = parseInt(window.location.href.split('#')[1]);
} else {
level = 0;
}
var ballNum = LevelSpeed[level].ballnum;//定义旋转小球的数量
var waitNum = LevelSpeed[level].waitNum;//定义等待小球的数量
var rotateAngle = LevelSpeed[level].speed;//定义旋转的角度
绘制大圆和中间的关卡数
function ballBig() {
//大圆
cxt.beginPath();
cxt.arc(arcX, arcY, arcR, 0, Math.PI * 2);
cxt.fillStyle = '#000';
cxt.fill();
cxt.closePath();
//字体
cxt.fillStyle = '#fff';
cxt.font = '30px 微软雅黑';
if (level == LevelSpeed.length) {
level = LevelSpeed.length - 1;
}
var txt = (level + 1) + "";
cxt.fillText(txt, arcX, arcY);
}
绘制旋转的小球
function ballRotate() {
cxt.clearRect(100, 20, 350, 280);
ballBig();
cxt.save();
cxt.translate(arcX, arcY);
balls.forEach(function (item) {
cxt.save();
cxt.rotate(Math.PI / 180 * item.angle);
item.angle += rotateAngle;
if (item.angle >= 360) item.angle = 0;
//绘制小球和线条
cxt.beginPath();
cxt.moveTo(0, -arcR);
cxt.lineTo(0, -(arcR + lineWidth));
cxt.closePath();
cxt.stroke();
cxt.beginPath();
cxt.arc(0, -(arcR + lineWidth), radius, 0, Math.PI * 2);
cxt.fillStyle = '#000';
cxt.fill();
cxt.closePath();
if (item.numStr != "") {
cxt.fillStyle = '#fff';
cxt.font = '10px 微软雅黑';
cxt.fillText(item.numStr, 0, -(arcR + lineWidth));
}
cxt.restore();
});
cxt.restore();
window.requestAnimationFrame(ballRotate);
}
注意:在让小球旋转时,如果想要让小球旋转的更流畅,请使用
window.requestAnimationFrame();
此方法比定时函数流畅,不会出现卡顿的情况。每次旋转开始不要忘记清空画布。
绘制等待小球
//绘制等待小球
function ballWait() {
//清空小球的等待区域
cxt.clearRect(arcX - radius, 270, 20, 360);
waitBalls.forEach(function (item, index) {
cxt.save();
cxt.beginPath();
cxt.arc(arcX, arcY + lineWidth + arcR + radius * 3 + (radius * index * 2), radius, 0, Math.PI * 2);
cxt.fillStyle = '#000';
cxt.fill();
cxt.fillStyle = '#fff';
cxt.font = '10px 微软雅黑';
cxt.fillText(item.numStr, arcX, arcY + lineWidth + radius * 3 + arcR + (radius * index * 2));
cxt.closePath();
cxt.restore();
})
}
当一切准备就绪时,我们最后需要的就是,通过点击画布,来让等待中的小球插入到旋转中的小球中去,从而来实现我们的游戏。
canvas.onclick = function () {
//删除等待小球,并且把删除的小球插入到转动小球的末尾处
var obj = waitBalls.shift();
if (waitBalls.length != 0) {
//更改小球的角度
obj.angle = 180;
//判断小球之间是否碰撞
for (var i = 0; i < balls.length; i++) {
if (balls[i].angle >= 171 && balls[i].angle <= 189) {
alert('游戏失败');
window.location.href = "index.html#" + level;
}
}
balls.push(obj);
} else if (waitBalls.length == 0) {
alert('闯关成功!');
level++;
window.location.href = "index.html#" + level;
}
ballWait();
};
这里主要用到了数组的两个方法:shift();和 push();
完整的代码请到GitHub上取:
使用canvas绘制见缝插针小游戏
里面写好了游戏的开始和结束。
如游戏有不足之处请自行修改。