以前一直以为玄之又玄的碰撞检测算法,其实也不过是一些加减法。看来还是写的太少,大多时候只是停留在望而止步的层次。
矩形的碰撞检测原理就是两个矩形的x值+宽度和y值+高度的各种比较。
function(c1,c2{ return !{ b1.x + b1.w < b2.x || b1.y + b1.h < b2.y || b2.x + b2.w < b1.x || b2.y + b2.h < b1.y }
意思就是矩形1的x加上矩形1的宽度是否小于矩形2的x,这样就能检测到当矩形1在矩形2的左边的时候,两个矩形在水平方向上是否有重叠;垂直方向同理,把x改为y,宽度改为高度即可。
碰撞检测的原理搞清楚了之后其他的就是小意思了,利用动画帧即可做出方块下落的动画。
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>碰撞检测</title>
<style type="text/css">
canvas{
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id="cav" width="300" height="300"></canvas>
<script>
/*通过调整方块的y轴位置而不断下落,如果到了画布的底部或者碰撞到了其他方块则停止下落,这是矩形的碰撞检测*/
var cav = document.getElementById("cav"),
ctx = cav.getContext('2d');
var rects = [],//把方块存储起来
speed = 2;//下落速度
//方块的初始化
function rectInit(x, y, width, height) {
this.x = x;
this.y = y;
this.w = width;
this.h = height;
}
//创建方块
function createRect() {
var x = cav.width * Math.random(),
y = 0;
var rect = new rectInit(x, y, 30, 30);
rects.push(rect);
return rect;
}
//一开始先创建一个方块
var oRect = new rectInit(cav.width / 2, 0, 30, 30);
rects.push(oRect);
//方块下落动画
function animate() {
ctx.clearRect(0, 0, cav.width, cav.height);
//如果没有到底部
if(oRect.y < cav.height-oRect.h){
oRect.y += speed;
}
else{//到了底部后停止下落
oRect.y = cav.height-oRect.h;
oRect = createRect();//再度创建一个方块
}
ctx.fillStyle = '#f00';
//循环数组里存储的方块
rects.forEach(function(r,i){
if(oRect !== r && collision(oRect,r)){
// console.log('碰撞成功');
oRect.y = r.y - oRect.h;
oRect = createRect();
}
ctx.fillRect(r.x,r.y,r.w,r.h);
});
requestAnimationFrame(animate);
}
animate();
//矩形的碰撞检测
function collision(c1, c2) {
return !(c1.x + c1.w < c2.x ||
c1.y + c1.h < c2.y ||
c2.x + c2.w < c1.x ||
c2.y + c2.h < c1.y
);
}
</script>
</body>
</html>