晴明的博客园 GitHub      CodePen      CodeWars     

[canvas] 碰撞

碰撞检测的方法

判断物体与物体之间是否有重叠,这里使用物体的外接矩形边界来确定。

判断物体与物体之间的距离,当距离小于某个值时,满足碰撞条件,物体产生碰撞效果。

光线投射法

画一条与物体速度向量相重合的线,
然后再从待检测物体出发,绘制第二条线,根据两条线的交点位置来判定是否发生碰撞。

#1是与小球速度向量相重合的线,
#2线是从待测物体触发绘制的第二条线。
在小球的飞行过程中,程序不断地擦出并重回从小球到1,2号交点处的连线。

小球落入桶中的条件:
1号线与2号线的交点在同口的左边沿与右边沿之间。
小球位于2号线下方。

斜截式

y = kx + b

k表示斜率, 
b表示与y轴的截距,也就是直线与y轴交点的纵坐标。

寻找两条直线的交点,
就是寻找同时满足两条直线方程的点,
我们假设这个点为(X0, Y0),
两条直线方程分别为 y = (k1)X + b1, y = (k2)X + b2

交点就是同时满足的点,那么就有:

(k1)X0 + b1 = (k2)X0 + b2
X0(k1 - k2) = b2 - b1
 
X0 = (b2 - b1)/(k1 - k2)
Y0 = (k1b2 - k2b1)/(k1 - k2)

该方法也有弊端,当小球做水平运动或是垂直运动时,
其斜率为0或是无穷,这时用该方法就不适用了。


catchBall = {
    intersectionPoint: {x:0, y:0},
    
    isBallInBucket: function () {
        if(lastBallPosition.left === ball.left ||
           lastBallPosition.top === ball.top){
            return;
        }
        
        //(x1, y1) = Last ball position
        //(x2, y2) = Current ball position
        //(x3, y3) = Bucket left
        //(x4, y4) = Bucket right
        
        var x1 = lastBallPosition.left,
            y1 = lastBallPosition.top,
            x2 = ball.left,
            y2 = ball.top,
            x3 = bucket_left + bucket_width/4,
            y3 = bucket_top,
            x4 = bucket_left + bucket_width,
            y4 = y3;
        
        //(x1, y1)到(x2, y2)的斜率
        var k1 = (ball.top - lastBallPosition.top)/(ball.left - lastBallPosition.left);
        
        //(x3, y3)到(x4, y4)的斜率
        var k2 = (y4 - y3) / (x4 - x3);
        
        //截距b1
        var b1 = y1 - k1*x1;
        
        //截距b2
        var b2 = y3 - k2*x3;
        
        this.intersectionPoint.x = (b2 - b1) / (k1 - k2);
        this.intersectionPoint.y = k1 * this.intersectionPoint.x + b1;
        
        return intersectionPoint.x > x3 &&
               intersectionPoint.x < x4 &&
               ball.top + ball.height > y3 &&
               ball.left + ball.width < x4;
        
    }
}

分离轴定理(SAT)

分离轴定理只适用于凸多边形,也就是所有内角均小于180度的多边形。
比如矩形,三角形等。
而如果有一个内角大于180度,就如吃豆人的形状,就不适合使用该定理。

把受测的两个物体置于一睹墙前面,然后用光线照射它们,
根据阴影部分是否香蕉来判断二者有没有相撞。

碰到了

没碰到

posted @ 2016-12-23 17:03  晴明桑  阅读(625)  评论(0编辑  收藏  举报