矩形的碰撞检测(模仿俄罗斯方块)

  以前一直以为玄之又玄的碰撞检测算法,其实也不过是一些加减法。看来还是写的太少,大多时候只是停留在望而止步的层次。

矩形的碰撞检测原理就是两个矩形的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>
原文地址:https://www.cnblogs.com/11lang/p/6082811.html