有时候两个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的直角顶点“切掉”,变成八边形。
如下图所示:
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);