Box2d进阶 使用光线投射实现Box2d爆炸效果模拟

以后要多写一下文章,把在做项目的过程中灵光一现的地方记录下来,免得记性不好,给忘掉了。
首先说一下什么是光线投射,当然高手可以跳过了..Box2d自带这个API的意思是,已知点A和点B和形状shape,由点A向点B做一条射线,返回AB射线是否与shape相交并且可以算出相交的点,具体用法如下
b2Shape *shape = f->GetShape();
b2RayCastInput input;
input.p1.Set(startBody.body->GetPosition().x,startBody.body->GetPosition().y);
input.p2.Set(nowPoint.x/PTM_RATIO, nowPoint.y/PTM_RATIO);
input.maxFraction = 1.0f;
b2RayCastOutput output;
bool hit =shape->RayCast(&output, input, b->GetTransform(),0);
if (hit )
{
b2Vec2 hitPoint = input.p1 +output.fraction * (input.p2 – input.p1);
}
p1为始发点,p2为结束点,maxFraction = 1.0f 可以理解为整条线段的比例为1,output.fraction即为始发点到相交点的距离占p1-p2距离的比例,及是 0 – maxFraction。所以求hitPoint的方法是那样写的。
我们可以利用光线投射来做出一些效果,比如下面这样:
首先这是画一条随着鼠标走的线

然后现在根据光线投射我们让它做出被墙挡住的效果,如下

下面说一下爆炸效果,这里要模拟的效果是已一个刚体作为爆炸物,点击爆炸后产生类似冲击波的效果。查资料网上线有两种解决思路,一种是让刚体真实的爆炸分 裂成多个小的球行刚体让他们去撞击其他刚体,另一种是根据爆炸中心遍历范围内所有刚体并根据距离向量对刚体施加大小不同的力。个人觉得第一种情况过于复杂 而且效果也有偏差,第二种效果就更有问题了。所以这里想到了使用光线投射来做一个爆炸效果。首先设想是这样的:

取圆心和圆周上平均的100个来对世界当中的所有刚体进行光线投射,如果出现相交,则任务该投射对该刚体上的相交点施加了一个力,这个力的大小取(相交点 -圆心)的距离向量来决定,100条光线可以有多条光线打到同一刚体上,这样的话就充分考虑到了刚体的受力面积和不同的位置所受的力有所不同,类似于真实 的冲击波。此外我们还可以实现根据刚体离中心的距离来判断A,B刚体对同一条光线投射的遮挡效果,即是如果光线先打中了A,那么他将不继续去撞击下一刚 体。
核心方法其实很简单
  - (void)doBoom:(b2Vec2) position
{
    for (int i = 0;i < 100;i++)
    {
        float angle = 360/100*i;
        int x = cos(angle)*5+position.x;
        int y = sin(angle)*5+position.y;
        b2RayCastInput input;
        input.p1.Set(position.x,position.y);
        input.p2.Set(x,y);
        input.maxFraction = 1.0f;
        b2RayCastOutput output;
        b2Body *tempBody;
        b2Vec2 tempPoint;
        float minDistance = -1;
        for (b2Body *b = world->GetBodyList(); b; b = b->GetNext())
        {
            b2Shape *shape = b->GetFixtureList()->GetShape();
            bool hit =shape->RayCast(&output, input, b->GetTransform(),0);
            if(hit)
            {
                    b2Vec2 hitPoint = input.p1 +output.fraction * (input.p2 - input.p1);
                    float nowDistance = sqrtf(powf((position.x-hitPoint.x), 2)+powf((position.y-hitPoint.y), 2));
                    if(minDistance == - 1 || nowDistance < minDistance)
                    {
                        minDistance = nowDistance;
                        tempBody = b;
                        tempPoint = hitPoint;
                    }
            }
        }
        if(tempBody)
        {
            b2Vec2 vec = tempPoint - position;
            tempBody->ApplyForce(b2Vec2(vec.x*(1.0f-output.fraction)*30, vec.y*(1.0f-output.fraction)*30),tempPoint);
        }
    } 
}
上一下简单的效果图..



你可能感兴趣的:(光线投射,Box2d光线投射,Box2d爆炸效果模拟,Box2d爆炸效果)