欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

Box2D的Edge Shape的碰撞处理

程序员文章站 2022-06-13 13:34:44
...

有时候两个body碰撞时需要精确到某条边,所以在创建body的时候需要创建multiFixture,也就是多个fixture的组合。早期Box2D版本中Polygon Shape有setAsEdge方法设置每条边的fixture,v2.2.1之后只有setAsBox方法了。 方法一:可以在每条边的位置上加上一个Edg

有时候两个body碰撞时需要精确到某条边,所以在创建body的时候需要创建multiFixture,也就是多个fixture的组合。早期Box2D版本中Polygon Shape有setAsEdge方法设置每条边的fixture,v2.2.1之后只有setAsBox方法了。

方法一:可以在每条边的位置上加上一个Edge Shape,然后再body中加入这个边的fixture并保存起来,碰撞的时候就能判断是碰到哪条边了。

方法二:直接用body的createFixture(edgeShape,density)方法,直接创建一条edge的fixture,因为一般边不需要其他属性。默认边有摩擦力和弹力。

边也是以body中点为原点,所以边的起点和终点要用宽和高的一半来算。

这样添加后的碰撞种类(以player站在platform)上为例,可分为:

1. player的polygonShape和platform的topEdgeShape碰撞。

2. player的bottomEdgeShape和platform的polygonShape碰撞。

3. player的polygonShape和platform的polygonShape碰撞。

4. player的bottomEdgeShape和platform的topEdgeShape不会发生碰撞,因为他们都是Edge类型。

edgeShape的长度比polygonShape相应边的长度短一点,这样分别在判断左右两边和上下两边是否发生碰撞时,不会相互影响到。当rightEdge碰撞时,bottomEdge不会发生碰撞;当bottomEdge碰撞时,rightEdge也不会发生碰撞。

如果edgeShape的长度和polygonShape相应边的长度一样的话,当rightEdge碰撞时,bottomEdge的右端也会顶到墙上,发生碰撞,从而产生逻辑错误。比如:设定bottomShape发生碰撞时player的状态是isJump=NO,bottomEdge没有碰撞时isJump=YES。当player跳起并碰到墙壁时,isJump应该是YES状态,但bottomEdge检查到了碰撞,将isJump设为NO,这样player的其他行为和动作会发生错误。

或者把矩形polygonShape的直角顶点“切掉”,变成八边形。

如下图所示:

Box2D的Edge Shape的碰撞处理

1.

    //DELTA_LENGTH = 0.5   
    //fixture1 with polygon shape
    b2PolygonShape rectShape;
    rectShape.SetAsBox(size.x/2/PTM_RATIO, size.y/2/PTM_RATIO);
    
    b2FixtureDef fixtureDef1;
    p_body->CreateFixture(&fixtureDef1);
    
    //fixture2 with edge shape
    b2EdgeShape edgeShape;
    edgeShape.Set(b2Vec2((-size.x/2 + DELTA_LENGTH)/PTM_RATIO, (-size.y/2)/PTM_RATIO), 
                  b2Vec2((size.x/2 - DELTA_LENGTH)/PTM_RATIO, (s-size.y/2)/PTM_RATIO));
                        
    b2FixtureDef fixtureDef2;
    fixtureDef2.shape = &edgeShape;
    p_bottomFixture = p_body->CreateFixture(&fixtureDef2);

2.

b2EdgeShape edgeShape;
    edgeShape.Set(b2Vec2((-size.x/2 + DELTA_LENGTH)/PTM_RATIO, (-size.y/2)/PTM_RATIO), 
                  b2Vec2((size.x/2 - DELTA_LENGTH)/PTM_RATIO, (-size.y/2)/PTM_RATIO));

    p_bottomFixture = p_body->CreateFixture(&edgeShape, 0);

3 polygonShape必须是凸多边形,顶点按照逆时针方向依次给出

b2PolygonShape polygonShape;
    b2Vec2 vec[] = {b2Vec2(-size.x/2/PTM_RATIO, -size.y/2/PTM_RATIO), 
                    b2Vec2(size.x/2/PTM_RATIO, -size.y/2/PTM_RATIO), 
                    b2Vec2(size.x/2/PTM_RATIO, -size.y/4/PTM_RATIO), 
                    b2Vec2(size.x/4/PTM_RATIO, size.y/2/PTM_RATIO), 
                    b2Vec2(-size.x/4/PTM_RATIO, size.y/2/PTM_RATIO), 
                    b2Vec2(-size.x/2/PTM_RATIO, -size.y/4/PTM_RATIO)};
    polygonShape.Set(vec, 6);
    b2FixtureDef fixtureDef1;
    fixtureDef1.shape = &polygonShape;
    fixtureDef1.density = dens;
    fixtureDef1.friction = f;
    fixtureDef1.restitution = rest;
    p_polygonFixture = p_body->CreateFixture(&fixtureDef1);