2012-02-08 204 views
2

使用Box2d,如何創建像Parachute Ninja (ZeptoLab)這樣的橡膠線(橡皮筋/彈性繩)?如何在Box2D中創建橡膠線?

enter image description here

-(void) CreateElasticRope { 
//=======Params 
// Position and size 
b2Vec2 lastPos = b2Vec2(4,4); //set position first body 
float widthBody = 0.35; 
float heightBody = 0.1; 
// Body params 
float density = 0.05; 
float restitution = 0.5; 
float friction = 0.5; 
// Distance joint 
float dampingRatio = 0.85; 
float frequencyHz = 10; 
// Rope joint 
float kMaxWidth = 1.1; 
// Bodies 
int countBodyInChain = 10; 
b2Body* prevBody; 
//========Create bodies and joints 
for (int k = 0; k < countBodyInChain; k++) { 
    b2BodyDef bodyDef; 
    if(k==0 || k==countBodyInChain-1) bodyDef.type = b2_staticBody; //first and last bodies are static 
    else bodyDef.type = b2_dynamicBody; 
    bodyDef.position = lastPos; 
    lastPos += b2Vec2(2*widthBody, 0); //modify b2Vect for next body 
    bodyDef.fixedRotation = YES; 
    b2Body* body = world->CreateBody(&bodyDef); 

    b2PolygonShape distBodyBox; 
    distBodyBox.SetAsBox(widthBody, heightBody); 
    b2FixtureDef fixDef; 
    fixDef.density = density; 
    fixDef.restitution = restitution; 
    fixDef.friction = friction; 
    fixDef.shape = &distBodyBox; 
    body->CreateFixture(&fixDef); 

    if(k>0) { 
     //Create distance joint 
     b2DistanceJointDef distJDef; 
     b2Vec2 anchor1 = prevBody->GetWorldCenter(); 
     b2Vec2 anchor2 = body->GetWorldCenter(); 
     distJDef.Initialize(prevBody, body, anchor1, anchor2); 
     distJDef.collideConnected = false; 
     distJDef.dampingRatio = dampingRatio; 
     distJDef.frequencyHz = frequencyHz; 
     world->CreateJoint(&distJDef); 

     //Create rope joint 
     b2RopeJointDef rDef; 
     rDef.maxLength = (body->GetPosition() - prevBody->GetPosition()).Length() * kMaxWidth; 
     rDef.localAnchorA = rDef.localAnchorB = b2Vec2_zero; 
     rDef.bodyA = prevBody; 
     rDef.bodyB = body; 
     world->CreateJoint(&rDef); 

    } //if k>0 

    prevBody = body; 
} //for -loop 
} 

我用距離和繩索接頭,參數dampingRatio和frequencyHz的設定不同的值,但效果是遠未一個例子(我的很長一段時間的線程來原始狀態,並不那麼有彈性)。

+3

你應該包括一些代碼,並解釋你的代碼是如何出錯的。否則,想要幫助的人將不得不編寫完整的教程,而不是僅僅指出已有的缺陷。 – Dennis 2012-02-08 11:53:54

回答

-4

添加到我見過的遊戲中的最佳物理實現是由具有工程學位的人完成的。他將你在物理/工程中做的計算轉換成C++。從簡單的重力,反衝,推力到由偶然爆炸引起的旋轉速度。所有的數學都被分成了一個與動畫不同的模塊。

我建議查找公式彈性的特性,同時也考慮到你有鬆緊帶三種情況:被應用 1)形力拉伸回 2)的形狀,現在是由驅動樂隊的彈性屬性 3)形狀不再接觸樂隊,樂隊鬆散地擺動自己的重量和慣性

你越接近使用真實的物理計算,它會越逼真出現。我敢肯定,你可以把它變得簡單,讓自己變得更輕鬆,但是人類天生善於看到假貨。

+0

'真實的物理'往往不能應用於有價值的領域,讓我們來看看遊戲吧! – CapelliC 2012-02-08 13:05:51

+0

當然。但Box2d使用真正的公式,並在此引擎的幫助下可以實現物理。 – Sinba 2012-02-08 13:38:59

1

我非常懷疑他們在那裏使用任何關節。他們可能只是在忍者的當前位置和兩個職位的中間位置之間的距離來計算一個方向和開始的衝動......並且在職位和忍者之間畫兩條線。

+0

有趣的想法。但是在跳躍忍者橡膠行爲彈性後。 – Sinba 2012-02-08 13:39:51

+0

可以是固定的動畫。 – iforce2d 2012-02-08 18:37:21

3

您可以通過施加力來模擬彈簧。在每個時間步更新連接體上的力(如果需要,也可以喚醒身體)。如果其中一個物體是地面(或靜態物體),那麼您不需要對動態物體施加任何力量到地面。

定期的彈簧將根據撓度來施加拉力和壓力(拉力和推力)。在你的情況下,你有一個蹦極,所以沒有壓力只是拉力(拉力)。

這是你需要下式:

F = K * X

其中F是力,K是彈簧剛度(力/變形),和x是偏轉。偏轉計算爲初始長度與當前長度(連接點之間的距離)之間的差值。 F的符號決定它是否在拉或推。一旦你計算F,那麼你需要沿着連接兩個彈簧連接點的線應用它。爲了滿足力平衡,你需要在相反的方向上施加這個力(其中一個體得到正面,另一個得到負面力)。這是因爲牛頓爵士這樣說。

下面是一個例子(與pyBox2D工作,但你可以很容易地將它轉換爲C++)

你需要用一些屬性春天的對象。你的春天對象需要知道他們的初始長度,剛度,body1,body2,連接座標(B1X,B1Y,B2X,B2Y(本地座標))

在你的情況,你需要檢查,如果長度< spr.initialLength,如果這是真的,那麼你不會施加任何武力。

  body1 = spr.box2DBody1 
      body2 = spr.box2DBody2 

      pA = body1.GetWorldPoint(b2Vec2(spr.box2Db1x, spr.box2Db1y)) 
      pB = body2.GetWorldPoint(b2Vec2(spr.box2Db2x, spr.box2Db2y)) 
      lenVector = pB - pA 
      length = lenVector.Length() 
      deltaL = length - spr.initialLength 
      force = spr.K * deltaL 
      #normalize the lenVector 
      if length == 0: 
       lenVector = b2Vec2(0.70710678118654757, 0.70710678118654757) 
      else: 
       lenVector = b2Vec2(lenVector.x/length, lenVector.y/length) 
      sprForce = b2Vec2(lenVector.x * force, lenVector.y * force) 
      body1.ApplyForce(sprForce, pA) 
      body2.ApplyForce(-sprForce, pB)