有時候兩個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的直角頂點“切掉”,變成八邊形。
如下圖所示:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0NXYFhGd192UvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LchGbtFmdGdUY2YFSlZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DOxcjNxgTMxIjMwITMzEDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
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);