乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Box2D一:基礎(chǔ)知識(shí)

       gljin_cn 2015-02-16
      5、 創(chuàng)建一個(gè)動(dòng)態(tài)物體
      首先我們用 CreateBody 創(chuàng)建物體。
      b2BodyDef bodyDef;
      bodyDef.position.Set(0.0f4.0f);
      b2Body* body = world.CreateBody(&bodyDef); 

       

      接下來(lái)我們創(chuàng)建并添加一個(gè)多邊形形狀到物體上。注意我們把密度設(shè)置為 1,默認(rèn)的密度是 0。并且,形狀的摩擦設(shè)置到了 0.3。形狀添加好以后,我們就使用 SetMassFromShapes 方法來(lái)命令物體通過(guò)形狀去計(jì)算其自身的質(zhì)量。這暗示了你可以給單個(gè)物體添加一個(gè)以上的形狀。如果質(zhì)量計(jì)算結(jié)果為 0,那么物體會(huì)變成真正的靜態(tài)。

      復(fù)制代碼
       b2PolygonDef shapeDef;

      shapeDef.SetAsBox(1.0f1.0f);
      shapeDef.density = 1.0f;
      shapeDef.friction = 0.3f;
      body->CreateShape(&shapeDef);
      body->SetMassFromShapes();

      復(fù)制代碼

       

       6、模擬(Box2D 的)世界

       

       我們已經(jīng)初始化好了地面盒和一個(gè)動(dòng)態(tài)盒?,F(xiàn)在我們只有少數(shù)幾個(gè)問(wèn)題需要考慮。Box2D 中有一些數(shù)學(xué)代碼構(gòu)成的積分器(integrator),積分器在離散的時(shí)間點(diǎn)上模擬物理方程,它將與游戲動(dòng)畫(huà)循環(huán)一同運(yùn)行。所以我們需要為 Box2D 選取一個(gè)時(shí)間步,通常來(lái)說(shuō)游戲物理引擎需要至少 60Hz 的速度,也就是 1/60 的時(shí)間步。你可以使用更大的時(shí)間步,但是你必須更加小心地為你的世界調(diào)整定義。我們也不喜歡時(shí)間步變化得太大,所以不要把時(shí)間步關(guān)聯(lián)到幀頻(除非你真的必須這樣做)。直截了當(dāng)?shù)?,這個(gè)就是時(shí)間步:float32 timeStep = 1.0f / 60.0f

       除了積分器之外,Box2D 中還有約束求解器(constraint solver)。約束求解器用于解決模擬中的所有約束,一次一個(gè)。單個(gè)的約束會(huì)被完美的求解,然而當(dāng)我們求解一個(gè)約束的時(shí)候,我們就會(huì)稍微耽誤另一個(gè)。要得到良好的解,我們需要迭代所有約束多次。建議的 Box2D 迭代次數(shù)是 10 次。你可以按自己的喜好去調(diào)整這個(gè)數(shù),但要記得它是速度與質(zhì)量之間的平衡。更少的迭代會(huì)增加性能并降低精度,同樣地,更多的迭代會(huì)減少性能但提高模擬質(zhì)量。這是我們選擇的迭代次數(shù):

       int32 iterations = 10;//一個(gè)時(shí)間步遍歷10次約束

       

       現(xiàn)在我們可以開(kāi)始模擬循環(huán)了,在游戲中模擬循環(huán)應(yīng)該并入游戲循環(huán)。每次循環(huán)你都應(yīng)該調(diào)用 b2World::Step,通常調(diào)用一次就夠了,這取決于幀頻以及物理時(shí)間步。

       這就是模擬 1 秒鐘內(nèi) 60 個(gè)時(shí)間步的循環(huán)

      for (int32 i = 0; i < 60; ++i)
      {
          world.Step(timeStep, iterations);
      }

       

       

       7、API 設(shè)計(jì)

       

      單位

       

       Box2D 使用浮點(diǎn)數(shù),所以必須使用一些公差來(lái)保證它正常工作。這些公差已經(jīng)被調(diào)諧得適合米-千克-秒(MKS)單位。尤其是,Box2D 被調(diào)諧得能良好地處理 0.1 到 10 米之間的移動(dòng)物體。這意味著從罐頭盒到公共汽車大小的對(duì)象都能良好地工作。 

      · 注意:Box2D 已被調(diào)諧至 MKS 單位。移動(dòng)物體的尺寸大約應(yīng)該保持在 0.1 到 10 米之間。你可能需要一些縮放系統(tǒng)來(lái)渲染你的場(chǎng)景和物體。Box2D 中的例子是使用 OpenGL 的視口來(lái)變換的。

       

      用戶數(shù)據(jù)

      b2Shape,b2Body 和 b2Joint 類都允許你通過(guò)一個(gè) void 指針來(lái)附加用戶數(shù)據(jù)。這在你測(cè)試 Box2D 數(shù)據(jù)結(jié)構(gòu),以及你想把它們聯(lián)系到自己的引擎中的時(shí)候是較方便的。舉個(gè)典型的例子,在角色上的剛體中附加到角色的指針,這就構(gòu)成了一個(gè)循環(huán)引用。如果你有角色,你就能得到剛體。如果你有剛體,你就能得到角色。
      GameActor* actor = GameCreateActor();
      b2BodyDef bodyDef;
      bodyDef.userData = actor;
      actor->body = box2Dworld->CreateBody(&bodyDef);
      這是一些需要用戶數(shù)據(jù)的案例: 
      · 使用碰撞結(jié)果給角色施加傷害
      · 當(dāng)玩家進(jìn)入一個(gè)包圍盒時(shí)播放一段腳本事件
      · 當(dāng) Box2D 通知你一個(gè)關(guān)節(jié)即將摧毀時(shí)訪問(wèn)一個(gè)游戲結(jié)構(gòu)
      記得用戶數(shù)據(jù)是可選的,并且能放入任何東西。然而,你需要保持一致性。例如,如果你想在一個(gè)物體中保存一個(gè)角色的指針,那你就應(yīng)該在所有物體中都保存一個(gè)角色指針。不要在一個(gè)物體中保存角色指針,卻在另一個(gè)物體中保存一個(gè)其它指針。這可能會(huì)導(dǎo)致程序崩潰。 

       

      8、世界 

       b2World 類包含著物體和關(guān)節(jié)。它管理著模擬的方方面面,并允許異步查詢(就像 AABB 查詢)。你與 Box2D 的大部分交互都將通過(guò) b2World 對(duì)象來(lái)完成。

       要?jiǎng)?chuàng)建或摧毀一個(gè)世界你需要使用 new 和 delete:

      b2World* myWorld = new b2World(aabb, gravity, doSleep);
      // ... do stuff ...
      delete myWorld;

       世界類用于驅(qū)動(dòng)模擬。你需要指定一個(gè)時(shí)間步和一個(gè)迭代次數(shù)。例如:

      float32 timeStep = 1.0f / 60.f;
      int32 iterationCount = 10;
      myWorld->Step(timeStep, iterationCount);

       

       在時(shí)間步完成之后,你可以調(diào)查物體和關(guān)節(jié)的信息。最可能的情況是你會(huì)獲取物體的位置,這樣你才能更新你的角色并渲染它們。你可以在游戲循環(huán)的任何地方執(zhí)行時(shí)間步,但你應(yīng)該意識(shí)到事情發(fā)生的順序。例如,如果你想要在一幀中得到新物體的碰撞結(jié)果,你必須在時(shí)間步之前創(chuàng)建物體。推薦使用固定的時(shí)間步。使用大一些的時(shí)間步你可以在低幀率的情況下提升性能。1/60 的時(shí)間步通常會(huì)呈現(xiàn)一個(gè)高質(zhì)量的模擬。

        掃描世界:

      世界就是一個(gè)物體和關(guān)節(jié)的容器。你可以獲取世界中所有物體和關(guān)節(jié)并遍歷它們。例如,這段代碼會(huì)喚醒世界中的所有物體:
      for (b2Body* b = myWorld->GetBodyList(); b; b = b->GetNext())
      {
          b->WakeUp();

       

       AABB 查詢:

      有時(shí)你需要求出一個(gè)區(qū)域內(nèi)的所有形狀。b2World 類為此使用了 broad-phase 數(shù)據(jù)結(jié)構(gòu),提供了一個(gè) log(N) 的快速方法。你提供一個(gè)世界坐標(biāo)的 AABB,而 b2World 會(huì)返回一個(gè)所有大概相交于此 AABB 的形狀之?dāng)?shù)組。這不是精確的,因?yàn)楹瘮?shù)實(shí)際上返回那些 AABB 與規(guī)定之 AABB 相交的形狀。例如,下面的代碼找到所有大概與指定 AABB 相交的形狀并喚醒所有關(guān)聯(lián)的物體。
      復(fù)制代碼
      b2AABB aabb;
      aabb.minVertex.Set(-1.0f, -1.0f);
      aabb.maxVertex.Set(1.0f1.0f);
      const int32 k_bufferSize = 10;
      b2Shape *buffer[k_bufferSize];
      int32 count = myWorld->Query(aabb, buffer, k_bufferSize);
      for (int32 i = 0; i < count; ++i)
      {
          buffer[i]->GetBody()->WakeUp();
      復(fù)制代碼

       

       9、 物體

       物體具有位置和速度。你可以應(yīng)用力,扭矩和沖量到物體。物體可以是靜態(tài)的或動(dòng)態(tài)的,靜態(tài)物體永遠(yuǎn)不會(huì)移動(dòng),并且不會(huì)與其它靜態(tài)物體發(fā)生碰撞。物體是形狀的主干,物體攜帶形狀在世界中運(yùn)動(dòng)。在 Box2D 中物體總是剛體,這意味著同一剛體上的兩個(gè)形狀永遠(yuǎn)不會(huì)相對(duì)移動(dòng)。通常你會(huì)保存所有你所創(chuàng)建的物體的指針,這樣你就能查詢物體的位置,并在圖形實(shí)體中更新它的位置。另外在不需要它們的時(shí)候你也需要通過(guò)它們的指針摧毀它們。

        質(zhì)量性質(zhì):

      1)在物體定義中顯式地設(shè)置 

       bodyDef.massData.mass = 2.0f;//物體的質(zhì)量是2kg

       2)顯式地在物體上設(shè)置(在其創(chuàng)建之后)

      3)基于物體上的形狀來(lái)進(jìn)行密度設(shè)置 

       b2PolygonDef shapeDef;

      shapeDef.SetAsBox(1.0f1.0f);
      shapeDef.density = 1.0f;
      body->CreateShape(&shapeDef);
      body->SetMassFromShapes();//這個(gè)函數(shù)成本較高,所以你應(yīng)該只在需要時(shí)使用它。
      你可以在運(yùn)行時(shí)調(diào)整一個(gè)物體的質(zhì)量,這通常是在添加或移除物體上之形狀時(shí)完成的??赡苣銜?huì)根據(jù)物體上的當(dāng)前形狀來(lái)調(diào)整其質(zhì)量。
      可能你也會(huì)直接設(shè)置質(zhì)量。例如,你可能會(huì)改變形狀,但你只想使用自己的質(zhì)量公式。
      void SetMass(const b2MassData* massData);
      通過(guò)以下這些函數(shù)可以獲得物體的質(zhì)量數(shù)據(jù):
      float32 GetMass() const;
      float32 GetInertia() const;
      const b2Vec2& GetLocalCenter() const

       

      位置和角度:

      bodyDef.position.Set(0.0f2.0f);   // the body's origin position.
      bodyDef.angle = 0.25f * b2_pi;      // the body's angle in radians.
      你可以訪問(wèn)一個(gè)物體的位置和角度,這在你渲染相關(guān)游戲角色時(shí)很常用。你也可以設(shè)置位置,盡管這不怎么常用。
      bool SetXForm(const b2Vec2& position, float32 angle);
      const b2XForm& GetXForm() const;
      const b2Vec2& GetPosition() const;
      float32 GetAngle() const

       

       你可以訪問(wèn)線速度與角速度,線速度是對(duì)于質(zhì)心所言的。

      void SetLinearVelocity(const b2Vec2& v);
      b2Vec2 GetLinearVelocity() const;
      void SetAngularVelocity(float32 omega);
      float32 GetAngularVelocity() const;

       

      阻尼:

      阻尼用于減小物體在世界中的速率。阻尼與摩擦是不同的,因?yàn)槟Σ羶H在物體有接觸的時(shí)候才會(huì)發(fā)生,而阻尼的模擬要比摩擦便宜多了。然而,阻尼并不能取代摩擦,往往這兩個(gè)效果需要同時(shí)使用。阻尼參數(shù)的范圍可以在 0 到無(wú)窮之間,0 的就是沒(méi)有阻尼,無(wú)窮就是滿阻尼。通常來(lái)說(shuō),阻尼的值應(yīng)在 0 到 0.1 之間,我通常不使用線性阻尼,因?yàn)樗鼤?huì)使物體看起來(lái)發(fā)飄。
      bodyDef.linearDamping = 0.0f;
      bodyDef.angularDamping = 0.01f;
      阻尼相似于穩(wěn)定性與性能,阻尼值較小的時(shí)候阻尼效應(yīng)幾乎不依賴于時(shí)間步,而阻尼值較大的時(shí)候阻尼效應(yīng)將隨著時(shí)間步而變化。如果你使用固定的時(shí)間步(推薦)這就不是問(wèn)題了。 

       休眠參數(shù):

      模擬物體的成本是高昂的,所以如果物體更少,那模擬的效果就能更好。當(dāng)一個(gè)物體停止了運(yùn)動(dòng)時(shí),我們要停止去模擬它。 當(dāng) Box2D 確定一個(gè)物體(或一組物體)已經(jīng)停止移動(dòng)時(shí),物體就會(huì)進(jìn)入休眠狀態(tài),消耗很小的 CPU 開(kāi)銷。如果一個(gè)醒著的物體接觸到了一個(gè)休眠中的物體,那么休眠中的物體就會(huì)醒來(lái)。當(dāng)物體上的關(guān)節(jié)或
      觸點(diǎn)被摧毀的時(shí)候,它們同樣會(huì)醒來(lái)。你也可以手動(dòng)地喚醒物體。通過(guò)物體定義,你可以指定一個(gè)物體是否可以休眠,或者創(chuàng)建一個(gè)休眠的物體。
      bodyDef.allowSleep = true;
      bodyDef.isSleeping = false;

       

       子彈:

      高速移動(dòng)的物體在 Box2D 被稱為子彈(bullet),你需要按照游戲的設(shè)計(jì)來(lái)決定哪些物體是子彈。如果你決定一個(gè)物體應(yīng)該按照子彈去處理,使用下面的設(shè)置。
      bodyDef.isBullet = true;
      子彈開(kāi)關(guān)只影響動(dòng)態(tài)物體。
      有的時(shí)候,在一個(gè)時(shí)間步內(nèi)可能會(huì)有大量的剛體同時(shí)運(yùn)動(dòng)。如果一個(gè)物理引擎沒(méi)有處理好大幅度運(yùn)動(dòng)的問(wèn)題,你就可能會(huì)看見(jiàn)一些物體錯(cuò)誤地穿過(guò)了彼此。這種效果被稱為隧道效應(yīng)(tunneling)。默認(rèn)情況下,Box2D 會(huì)通過(guò)連續(xù)碰撞檢測(cè)(CCD)來(lái)防止動(dòng)態(tài)物體穿越靜態(tài)物體,這是通過(guò)從形狀的舊位置到新位置的掃描來(lái)完成的。引擎會(huì)查找掃描中的新碰撞,并為這些碰撞計(jì)算碰撞時(shí)間(TOI)。物體會(huì)先被移動(dòng)到它們的第一個(gè) TOI,然后一直模擬到原時(shí)間步的結(jié)束。如果有必要這個(gè)步驟會(huì)重復(fù)執(zhí)行。一般 CCD 不會(huì)應(yīng)用于動(dòng)態(tài)物體之間,這是為了保持性能。在一些游戲環(huán)境中你需要在動(dòng)態(tài)物體上也使用 CCD,譬如,你可能想用一顆高速的子彈去射擊薄壁。沒(méi)有 CCD,子彈就可能會(huì)隧穿薄壁。 CCD 的成本是昂貴的,所以你可能不希望所有運(yùn)動(dòng)物體都成為子彈。所以 Box2D 默認(rèn)只在動(dòng)態(tài)物體和靜態(tài)物體之間使用 CCD,這是防止物體逃脫游戲世界的一個(gè)有效方法。然而,可能你有一些高速移動(dòng)的物體需要一直使用 CCD。 

       

       狀態(tài)信息:

      物體的狀態(tài)含有多個(gè)方面,通過(guò)這些函數(shù)你可以訪問(wèn)這些狀態(tài)數(shù)據(jù):
      復(fù)制代碼
      bool IsBullet() const;
      void SetBullet(bool flag);
      bool IsStatic() const;
      bool IsDynamic() const;
      bool IsFrozen() const;
      bool IsSleeping() const;
      void AllowSleeping(bool flag);
      void WakeUp(); 
      復(fù)制代碼

       

       

       力和沖量:

      你可以對(duì)一個(gè)物體應(yīng)用力,扭矩,以及沖量。當(dāng)應(yīng)用一個(gè)力或沖量時(shí),你需要提供一個(gè)世界位置。這常常會(huì)導(dǎo)致對(duì)質(zhì)心的一個(gè)扭矩。
      void ApplyForce(const b2Vec2& force, const b2Vec2& point);
      void ApplyTorque(float32 torque);
      void ApplyImpulse(const b2Vec2& impulse, const b2Vec2& point);
      應(yīng)用力,扭矩或沖量會(huì)喚醒物體,有時(shí)這是不合需求的。例如,你可能想要應(yīng)用一個(gè)穩(wěn)定的力,并允許物體休眠來(lái)提升性能。這時(shí),你可以使用這樣的代碼:
      if (myBody->IsSleeping() == false)
      {
          myBody->ApplyForce(myForce, myPoint);

       

        坐標(biāo)轉(zhuǎn)換:

      物體類包含一些工具函數(shù),它們可以幫助你在局部和世界坐標(biāo)系之間轉(zhuǎn)換點(diǎn)和向量。如果你不了解這些概念,請(qǐng)看 Jim Van Verth 和 Lars Bishop 的“Essential Mathematics for Games and Interactive Applications”。這些函數(shù)都很高效,所以可放心使用。
      b2Vec2 GetWorldPoint(const b2Vec2& localPoint);
      b2Vec2 GetWorldVector(const b2Vec2& localVector);
      b2Vec2 GetLocalPoint(const b2Vec2& worldPoint);
      b2Vec2 GetLocalVector(const b2Vec2& worldVector); 

       

       列表

      你可以遍歷一個(gè)物體的形狀,其主要用途是幫助你訪問(wèn)形狀的用戶數(shù)據(jù)。
      for (b2Shape* s = body->GetShapeList(); s; s = s->GetNext())
      {
          MyShapeData* data = (MyShapeData*)s->GetUserData();
          ... do something with data ...
      }

      你也可以用類似的方法遍歷物體的關(guān)節(jié)列表。 

       

       

       10、 形狀

       形狀就是物體上的碰撞幾何結(jié)構(gòu)。另外形狀也用于定義物體的質(zhì)量。也就是說(shuō),你來(lái)指定密度,Box2D 可以幫你計(jì)算出質(zhì)量。形狀具有摩擦和恢復(fù)的性質(zhì)。形狀還可以攜帶篩選信息,使你可以防止某些游戲?qū)ο笾g的碰撞。形狀永遠(yuǎn)屬于某物體,單個(gè)物體可以擁有多個(gè)形狀。形狀是抽象類,所以在 Box2D 中可以實(shí)現(xiàn)許多

      類型的形狀。如果你有勇氣,那便可以實(shí)現(xiàn)出自己的形狀類型(和碰撞算法)。

      形狀定義 :

      形狀定義用于創(chuàng)建形狀。通用的形狀數(shù)據(jù)會(huì)保存在 b2ShapeDef 中,特殊的形狀數(shù)據(jù)會(huì)保存在其派生類中。 

      1)摩擦和恢復(fù) 

       摩擦可以使對(duì)象逼真地沿其它對(duì)象滑動(dòng)。Box2D 支持靜摩擦和動(dòng)摩擦,但使用相同的參數(shù)。摩擦參數(shù)經(jīng)常會(huì)設(shè)置在 0 到 1 之間,0 意味著沒(méi)有摩擦,1 會(huì)產(chǎn)生強(qiáng)摩擦。當(dāng)計(jì)算兩個(gè)形狀之間的摩擦?xí)r,Box2D 必須聯(lián)合兩個(gè)形狀的摩擦參數(shù),這是通過(guò)以下公式完成的:

      float32 friction;
      friction = sqrtf(shape1->friction * shape2->friction);

       恢復(fù)可以使對(duì)象彈起,想象一下,在桌面上方丟下一個(gè)小球?;謴?fù)的值通常設(shè)置在 0 到 1 之間,0 的意思是小球不會(huì)彈起,這稱為非彈性碰撞;1 的意思是小球的速度會(huì)得到精確的反射,這稱為完全彈性碰撞。恢復(fù)是通過(guò)這樣的公式計(jì)算的:

      float32 restitution;
      restitution = b2Max(shape1->restitution, shape2->restitution);

       當(dāng)一個(gè)形狀發(fā)生多碰撞時(shí),恢復(fù)會(huì)被近似地模擬。這是因?yàn)?Box2D 使用了迭代求解器.

      2) 密度

      Box2D 可以根據(jù)附加形狀的質(zhì)量分配來(lái)計(jì)算物體的質(zhì)量以及轉(zhuǎn)動(dòng)慣量。直接指定物體質(zhì)量常常會(huì)導(dǎo)致不協(xié)調(diào)的模擬。因此,推薦的方法是使用b2Body::SetMassFromShape 來(lái)根據(jù)形狀設(shè)置質(zhì)量。 

       3) 篩選

      碰撞篩選是一個(gè)防止某些形狀發(fā)生碰撞的系統(tǒng)。 

      Box2D 支持 16 個(gè)種群,對(duì)于任何一個(gè)形狀你都可以指定它屬于哪個(gè)種群。你還可以指定這個(gè)形狀可以和其它哪些種群發(fā)生碰撞。例如,你可以在一個(gè)多人游戲中指定玩家之間不會(huì)碰撞,怪物之間也不會(huì)碰撞,但是玩家和怪物會(huì)發(fā)生碰撞。這是通過(guò)掩碼來(lái)完成的,例如:
      playerShapeDef.filter.categoryBits = 0x0002;
      monsterShapeDef.filter.categoryBits = 0x0004;
      playerShape.filter.maskBits = 0x0004;
      monsterShapeDef.filter.maskBits = 0x0002;

       

       碰撞組可以讓你指定一個(gè)整數(shù)的組索引。你可以讓同一個(gè)組的所有形狀總是相互碰撞(正索引)或永遠(yuǎn)不碰撞(負(fù)索引)。組索引通常用于一些以某種方式關(guān)聯(lián)的事物,就像自行車的那些部件。在下面的例子中,shape1 和 shape2 總是碰撞,而 shape3 和 shape4 永遠(yuǎn)不會(huì)碰撞。

      shape1Def.filter.groupIndex = 2;
      shape2Def.filter.groupIndex = 2;
      shape3Def.filter.groupIndex = -8;
      shape4Def.filter.groupIndex = -8;

       不同組索引之間形狀的碰撞會(huì)按照種群和掩碼來(lái)篩選。換句話說(shuō),組篩選比種群篩選有更高的優(yōu)選權(quán)。

      注意在 Box2D 中的其它碰撞篩選,這里是一個(gè)列表: 
      · 靜態(tài)物體上的形狀永遠(yuǎn)不會(huì)與另一個(gè)靜態(tài)物體上的形狀發(fā)生碰撞
      · 同一個(gè)物體上的形狀之間永遠(yuǎn)不會(huì)發(fā)生碰撞
      · 你可以有選擇地啟用或禁止由關(guān)節(jié)連接的物體上的形狀之間是否碰撞
      有時(shí)你可能希望在形狀創(chuàng)建之后去改變其碰撞篩選,你可以使用 b2Shape::GetFilterData 以及 b2Shape::SetFilterData 來(lái)存取已存在形狀之 b2FilterData 結(jié)構(gòu)。Box2D 會(huì)緩存篩選結(jié)果,所以你需要使用 b2World::Refilter 手動(dòng)地進(jìn)行重篩選。

       4)傳感器

       有時(shí)候游戲邏輯需要判斷兩個(gè)形狀是否相交,但卻不應(yīng)該有碰撞反應(yīng)。這可以通過(guò)傳感器(sensor)來(lái)完成。傳感器會(huì)偵測(cè)碰撞而不產(chǎn)生碰撞反應(yīng)。你可以將任一形狀標(biāo)記為傳感器,傳感器可以是靜態(tài)或動(dòng)態(tài)的。記得,每個(gè)物體上可以有多個(gè)形狀,并且傳感器和實(shí)體形狀是可以混合的。

       myShapeDef.isSensor = true;

       5) 圓形定義

      b2CircleDef 擴(kuò)充了 b2ShapeDef 并增加一個(gè)半徑和一個(gè)局部位置。
      b2CircleDef def;
      def.radius = 1.5f;
      def.localPosition.Set(1.0f0.0f); 

       6)多邊形定義

      b2PolyDef 用于定義凸多邊形。要正確地使用需要一點(diǎn)點(diǎn)技巧,所以請(qǐng)仔細(xì)閱讀。最大頂點(diǎn)數(shù)由 b2_maxPolyVertices 定義,當(dāng)前是 8。如果你需要更多頂點(diǎn),你必須修改 b2Settings.h 中的 b2_maxPolyVertices。當(dāng)創(chuàng)建多邊形定義時(shí),你需要給出所用的頂點(diǎn)數(shù)目。這些頂點(diǎn)必須按照相對(duì)于右手坐標(biāo)系之 z 軸逆時(shí)
      針(CCW)的順序定義。在你的屏幕上可能是順時(shí)針的,這取決于你的坐標(biāo)系統(tǒng)規(guī)則。多邊形必須是凸多邊形,也就是,每個(gè)頂點(diǎn)都必須指向外面。最后,你也不應(yīng)該重疊任何頂點(diǎn)。Box2D 會(huì)自動(dòng)地封閉環(huán)路。 

       這里是一個(gè)三角形的多邊形定義的例子:

      b2PolygonDef triangleDef;
      triangleDef.vertexCount = 3;
      triangleDef.vertices[0].Set(-1.0f0.0f);
      triangleDef.vertices[1].Set(1.0f0.0f);
      triangleDef.vertices[2].Set(0.0f2.0f);

       

       7)形狀工廠

       初始化一個(gè)形狀定義,而后將其傳遞給父物體;形狀就是這樣創(chuàng)建的。

      b2CircleDef circleDef;
      circleDef.radius = 3.0f;
      circleDef.density = 2.5f;
      b2Shape* myShape = myBody->CreateShape(&circleDef);

       

       

       11、關(guān)節(jié)

       關(guān)節(jié)的作用是把物體約束到世界,或約束到其它物體上。在游戲中的典型例子是木偶,蹺蹺板和滑輪。關(guān)節(jié)可以用許多種不同的方法結(jié)合起來(lái),創(chuàng)造出有趣的運(yùn)動(dòng)。

      有些關(guān)節(jié)提供了限制(limit),以便你控制運(yùn)動(dòng)范圍。有些關(guān)節(jié)還提供了馬達(dá)(motor),它可以以指定的速度驅(qū)動(dòng)關(guān)節(jié),直到你指定了更大的力或扭矩。
      1)關(guān)節(jié)定義
      各種關(guān)節(jié)類型都派生自 b2JointDef。所有關(guān)節(jié)都連接兩個(gè)不同的物體,可能其中一個(gè)是靜態(tài)物體。如果你想浪費(fèi)內(nèi)存的話,那就創(chuàng)建一個(gè)連接兩個(gè)靜態(tài)物體的關(guān)節(jié) 你可以為任何一種關(guān)節(jié)指定用戶數(shù)據(jù)。你還可以提供一個(gè)標(biāo)記,用于預(yù)防相連的物體發(fā)生碰撞。實(shí)際上,這是默認(rèn)行為,你可以設(shè)置 collideConnected 布爾值來(lái)允許相連的物體碰撞。很多關(guān)節(jié)定義需要你提供一些幾何數(shù)據(jù)。一個(gè)關(guān)節(jié)常常需要一個(gè)錨點(diǎn)(anchor point)來(lái)定義,這是固定于相接物體中的點(diǎn)。在 Box2D 中這點(diǎn)需要在局部坐標(biāo)系中指定,這樣,即便當(dāng)前物體的變化違反了關(guān)節(jié)約束,關(guān)節(jié)還是可以被指定 —— 在游戲存取進(jìn)度時(shí)這經(jīng)常會(huì)發(fā)生。另外,有些關(guān)節(jié)定義需要默認(rèn)的
      物體之間的相對(duì)角度。這樣才能通過(guò)關(guān)節(jié)限制或固定的相對(duì)角來(lái)正確地約束旋轉(zhuǎn)。初始化幾何數(shù)據(jù)可能有些乏味。所以很多關(guān)節(jié)提供了初始化函數(shù),消除了大部分工作。然而,這些初始化函數(shù)通常只應(yīng)用于原型,在產(chǎn)品代碼中應(yīng)該直接地定義幾何數(shù)據(jù)。這能使關(guān)節(jié)行為更加穩(wěn)固。其余的關(guān)節(jié)定義數(shù)據(jù)依賴于關(guān)節(jié)的類型。下面我們來(lái)介紹它們。 

       2)距離關(guān)節(jié)

       距離關(guān)節(jié)是最簡(jiǎn)單的關(guān)節(jié)之一,它描述了兩個(gè)物體上的兩個(gè)點(diǎn)之間的距離應(yīng)該是常量。當(dāng)你指定一個(gè)距離關(guān)節(jié)時(shí),兩個(gè)物體必須已在應(yīng)有的位置上。隨后,你指定兩個(gè)世界坐標(biāo)中的錨點(diǎn)。第一個(gè)錨點(diǎn)連接到物體 1,第二個(gè)錨點(diǎn)連接到物體 2。這些點(diǎn)隱含了距離約束的長(zhǎng)度。

       

       

       

       這是一個(gè)距離關(guān)節(jié)定義的例子。在此我們?cè)试S了碰撞。

      b2DistanceJointDef jointDef;
      jointDef.Initialize(myBody1, myBody2, worldAnchorOnBody1, 
      worldAnchorOnBody2);
      jointDef.collideConnected = true;

       3)旋轉(zhuǎn)關(guān)節(jié)

       一個(gè)旋轉(zhuǎn)關(guān)節(jié)會(huì)強(qiáng)制兩個(gè)物體共享一個(gè)錨點(diǎn),即所謂鉸接點(diǎn)。旋轉(zhuǎn)關(guān)節(jié)只有一個(gè)自由度:兩個(gè)物體的相對(duì)旋轉(zhuǎn)。這稱之為關(guān)節(jié)角。

       

       要指定一個(gè)旋轉(zhuǎn)關(guān)節(jié),你需要提供兩個(gè)物體以及一個(gè)世界坐標(biāo)的錨點(diǎn)。初始化函數(shù)會(huì)假定物體已經(jīng)在應(yīng)有位置了。在此例中,兩個(gè)物體被旋轉(zhuǎn)關(guān)節(jié)連接于第一個(gè)物體的質(zhì)心。

      b2RevoluteJointDef jointDef;
      jointDef.Initialize(myBody1, myBody2, myBody1->GetWorldCenter());

       

       這里是對(duì)上面旋轉(zhuǎn)關(guān)節(jié)定義的修訂;這次,關(guān)節(jié)擁有一個(gè)限制以及一個(gè)馬達(dá),后者用于模擬摩擦。

      復(fù)制代碼
      b2RevoluteJointDef jointDef;
      jointDef.Initialize(body1, body2, myBody1->GetWorldCenter());//使用 Initialize() 創(chuàng)建關(guān)節(jié)時(shí),旋轉(zhuǎn)關(guān)節(jié)角為 0,無(wú)論兩個(gè)物體當(dāng)前的角度怎樣。
      jointDef.lowerAngle = -0.5f * b2_pi; // -90 degrees最小角度
      jointDef.upperAngle = 0.25f * b2_pi; // 45 degrees最大角度
      jointDef.enableLimit = true;
      jointDef.maxMotorTorque = 10.0f;//馬達(dá)
      jointDef.motorSpeed = 0.0f;
      jointDef.enableMotor = true;
      復(fù)制代碼

      你可以訪問(wèn)旋轉(zhuǎn)關(guān)節(jié)的角度,速度,以及扭矩。 

      float32 GetJointAngle() const;  

      float32 GetJointSpeed() const;
      float32 GetMotorTorque() const;

      你也可以在每步中更新馬達(dá)參數(shù)。 

      void SetMotorSpeed(float32 speed);
      void SetMaxMotorTorque(float32 torque);  

       關(guān)節(jié)馬達(dá)有一些有趣的能力。你可以在每個(gè)時(shí)間步中更新關(guān)節(jié)速度,這可以使關(guān)節(jié)像正弦波一樣來(lái)回

      移動(dòng),或者按其它什么函數(shù)運(yùn)動(dòng)。
      // ... Game Loop Begin ...
      myJoint->SetMotorSpeed(cosf(0.5f * time));
      // ... Game Loop End ...
      你還可以使用關(guān)節(jié)馬達(dá)來(lái)追蹤某個(gè)關(guān)節(jié)角度。例如:
      // ... Game Loop Begin ...
      float32 angleError = myJoint->GetJointAngle() - angleTarget;
      float32 gain = 0.1f;
      myJoint->SetMotorSpeed(-gain * angleError);
      // ... Game Loop End ...
      通常來(lái)講你的增益參數(shù)不應(yīng)過(guò)大,否則你的關(guān)節(jié)可能會(huì)變得不穩(wěn)定。

       

      4)移動(dòng)關(guān)節(jié)

       移動(dòng)關(guān)節(jié)(prismatic joint)允許兩個(gè)物體沿指定軸相對(duì)移動(dòng),它會(huì)阻止相對(duì)旋轉(zhuǎn)。因此,移動(dòng)關(guān)節(jié)只有一個(gè)自由度。

       

      移動(dòng)關(guān)節(jié)的定義有些類似于旋轉(zhuǎn)關(guān)節(jié);只是轉(zhuǎn)動(dòng)角度換成了平移,扭矩?fù)Q成了力。以這樣的類比,我們來(lái)看一個(gè)帶有關(guān)節(jié)限制以及馬達(dá)摩擦的移動(dòng)關(guān)節(jié)定義: 
      復(fù)制代碼
      b2PrismaticJointDef jointDef;

      b2Vec2 worldAxis(1.0f0.0f);
      jointDef.Initialize(myBody1, myBody2, myBody1->GetWorldCenter(), 
      worldAxis);
      jointDef.lowerTranslation = -5.0f;
      jointDef.upperTranslation = 2.5f;
      jointDef.enableLimit = true;
      jointDef.motorForce = 1.0f;
      jointDef.motorSpeed = 0.0f;
      jointDef.enableMotor = true;

      復(fù)制代碼

       旋轉(zhuǎn)關(guān)節(jié)隱含著一個(gè)從屏幕射出的軸,而移動(dòng)關(guān)節(jié)明確地需要一個(gè)平行于屏幕的軸。這個(gè)軸會(huì)固定于兩個(gè)物體之上,沿著它們的運(yùn)動(dòng)方向。就像旋轉(zhuǎn)關(guān)節(jié)一樣,當(dāng)使用 Initialize() 創(chuàng)建移動(dòng)關(guān)節(jié)時(shí),移動(dòng)為 0。所以一定要確保移動(dòng)限制范圍內(nèi)包含了 0。移動(dòng)關(guān)節(jié)的用法類似于旋轉(zhuǎn)關(guān)節(jié),這是它的相關(guān)成員函數(shù): 

      float32 GetJointTranslation() const;
      float32 GetJointSpeed() const;
      float32 GetMotorForce() const;
      void SetMotorSpeed(float32 speed);

      void SetMotorForce(float32 force); 

       

       5)滑輪關(guān)節(jié)

       滑輪關(guān)節(jié)用于創(chuàng)建理想的滑輪,它將兩個(gè)物體接地(ground)并連接到彼此。這樣,當(dāng)一個(gè)物體升起時(shí),另一個(gè)物體就會(huì)下降。滑輪的繩子長(zhǎng)度取決于初始時(shí)的狀態(tài)。

      length1 + length2 == constant

       

       

       你還可以提供一個(gè)系數(shù)(ratio)來(lái)模擬滑輪組,這會(huì)使滑輪一側(cè)的運(yùn)動(dòng)比另一側(cè)要快。同時(shí),一側(cè)的約束力也比另一側(cè)要小。你也可以用這個(gè)來(lái)模擬機(jī)械杠桿(mechanical leverage)。length1 + ratio * length2 == constant 舉個(gè)例子,如果系數(shù)是 2,那么 length1 的變化會(huì)是 length2 的兩倍。另外連接 body1 的繩子的約束力將會(huì)是連接 body2 繩子的一半。當(dāng)滑輪的一側(cè)完全展開(kāi)時(shí),另一側(cè)的繩子長(zhǎng)度為零,這可能會(huì)出問(wèn)題。此時(shí),約束方程將變得奇異。因此,滑輪關(guān)節(jié)約束了每一側(cè)的最大長(zhǎng)度。另外出于游戲原因你可能也希望控制這個(gè)最大長(zhǎng)度。最大長(zhǎng)度能提高穩(wěn)定性,以及提供更多的控制。

      這是一個(gè)滑輪定義的例子:
      復(fù)制代碼
      b2Vec2 anchor1 = myBody1->GetWorldCenter();
      b2Vec2 anchor2 = myBody2->GetWorldCenter();
      b2Vec2 groundAnchor1(p1.x, p1.y + 10.0f);
       b2Vec2 groundAnchor2(p2.x, p2.y + 12.0f);
      float32 ratio = 1.0f;
      b2PulleyJointDef jointDef;
      jointDef.Initialize(myBody1, myBody2, groundAnchor1, groundAnchor2, 
      anchor1, anchor2, ratio);
      jointDef.maxLength1 = 18.0f;
      jointDef.maxLength2 = 20.0f;
      復(fù)制代碼

       滑輪關(guān)節(jié)提供了當(dāng)前長(zhǎng)度:

      float32 GetLength1() const;
      float32 GetLength2() const;  

       

       6) 齒輪關(guān)節(jié)

       如果你想要?jiǎng)?chuàng)建復(fù)雜的機(jī)械裝置,你可能需要齒輪。原則上,在 Box2D 中你可以用復(fù)雜的形狀來(lái)模擬輪齒,但這并不十分高效,而且這樣的工作可能有些乏味。另外,你還得小心地排列齒輪,保證輪齒能平穩(wěn)地嚙合。Box2D 提供了一個(gè)創(chuàng)建齒輪的更簡(jiǎn)單的方法:齒輪關(guān)節(jié)。

       

       

       齒輪關(guān)節(jié)需要兩個(gè)被旋轉(zhuǎn)關(guān)節(jié)或移動(dòng)關(guān)節(jié)接地(ground)的物體,你可以任意組合這些關(guān)節(jié)類型。另外,創(chuàng)建旋轉(zhuǎn)或移動(dòng)關(guān)節(jié)時(shí),Box2D 需要地(ground)作為 body1。類似于滑輪的系數(shù),你可以指定一個(gè)齒輪系數(shù)(ratio),齒輪系數(shù)可以為負(fù)。另外值得注意的是,當(dāng)一個(gè)是旋轉(zhuǎn)關(guān)節(jié)(有角度的)而另一個(gè)是移動(dòng)關(guān)節(jié)(平移)時(shí),齒輪系數(shù)是長(zhǎng)度或長(zhǎng)度分之一。coordinate1 + ratio * coordinate2 == constant這是一個(gè)齒輪關(guān)節(jié)的例子:

      復(fù)制代碼
      b2GearJointDef jointDef;
      jointDef.body1 = myBody1;
      jointDef.body2 = myBody2;
      jointDef.joint1 = myRevoluteJoint;
      jointDef.joint2 = myPrismaticJoint;
      jointDef.ratio = 2.0f * b2_pi / myLength; 
      復(fù)制代碼
      · 注意:齒輪關(guān)節(jié)總應(yīng)該先于旋轉(zhuǎn)或移動(dòng)關(guān)節(jié)被刪除,否則你的代碼將會(huì)由于齒輪關(guān)節(jié)中的無(wú)效關(guān)節(jié)
      指針而導(dǎo)致崩潰。另外齒輪關(guān)節(jié)也應(yīng)該在任何相關(guān)物體被刪除之前刪除。

      7)關(guān)節(jié)工廠

       關(guān)節(jié)是通過(guò)世界的工廠方法來(lái)創(chuàng)建和摧毀的,這引出了一個(gè)舊問(wèn)題: 

      · 注意:不要試圖在棧上創(chuàng)建物體或關(guān)節(jié),也不要使用 new 或 malloc 在堆上創(chuàng)建。物體以及關(guān)節(jié)必須要通過(guò) b2World 類的方法來(lái)創(chuàng)建或摧毀。
      這是一個(gè)關(guān)于旋轉(zhuǎn)關(guān)節(jié)生命期的例子:
      復(fù)制代碼
      b2RevoluteJointDef jointDef;
      jointDef.body1 = myBody1;
      jointDef.body2 = myBody2;
      jointDef.anchorPoint = myBody1->GetCenterPosition();
      b2RevoluteJoint* joint = myWorld->CreateJoint(&jointDef);
      // ... do stuff ...
      myWorld->DestroyJoint(joint);
      joint = NULL;
      復(fù)制代碼

       8)使用關(guān)節(jié)

       在許多模擬中,關(guān)節(jié)被創(chuàng)建之后便不再被訪問(wèn)了。然而,關(guān)節(jié)中包含著很多有用的數(shù)據(jù),使你可以創(chuàng)建出豐富的模擬。首先,你可以在關(guān)節(jié)上得到物體,錨點(diǎn),以及用戶數(shù)據(jù)。

      b2Body* GetBody1();
      b2Body* GetBody2();
      b2Vec2 GetAnchor1();
      b2Vec2 GetAnchor2();
      void* GetUserData();

       

       11、接觸

       接觸(contact)是由 Box2D 創(chuàng)建的用于管理形狀間碰撞的對(duì)象。接觸有不同的種類,它們都派生自 b2Contact,用于管理不同類型形狀之間的接觸。例如,有管理多邊形之間碰撞的類,有管理圓形之間碰撞的類。

      這里是 Box2D 中的一些與碰撞有關(guān)的術(shù)語(yǔ):

       觸點(diǎn)(contact point)

      兩個(gè)形狀相互接觸的點(diǎn)。實(shí)際上當(dāng)物體的表面相接觸時(shí)可能會(huì)有一定接觸區(qū)域,在 Box2D 則近似地
      以少數(shù)點(diǎn)來(lái)接觸。
      接觸向量(contact normal)
      從 shape1 指向 shape2 的單位向量。
      接觸分隔(contact separation)
      分隔相反于穿透,當(dāng)形狀相重疊時(shí),分隔為負(fù)??赡芤院蟮?Box2D 版本中會(huì)以正隔離來(lái)創(chuàng)建觸點(diǎn),所以當(dāng)有觸點(diǎn)的報(bào)告時(shí)你可能會(huì)檢查符號(hào)。
      法向力(normal force)
      Box2D 使用了一個(gè)迭代接觸求解器,并會(huì)以觸點(diǎn)保存結(jié)果。你可以安全地使用法向力來(lái)判斷碰撞強(qiáng)度。例如,你可以使用這個(gè)力來(lái)引發(fā)破碎,或者播放碰撞的聲音。

       切向力(tangent force)

      它是接觸求解器關(guān)于摩擦力的估計(jì)量。
      接觸標(biāo)識(shí)(contact ids)
      Box2D 會(huì)試圖利用一個(gè)時(shí)間步中的觸點(diǎn)壓力(contact force)結(jié)果來(lái)推測(cè)下一個(gè)時(shí)間步中的情況。接觸標(biāo)識(shí)用于匹配跨越時(shí)間步的觸點(diǎn),它包含了幾何特征索引以便區(qū)分觸點(diǎn)。 

       

       當(dāng)兩個(gè)形狀的 AABB 重疊時(shí),接觸就被創(chuàng)建了。有時(shí)碰撞篩選會(huì)阻止接觸的創(chuàng)建,有時(shí)盡管碰撞已篩選了 Box2D 還是須要?jiǎng)?chuàng)建一個(gè)接觸,這種情況下它會(huì)使用 b2NullContact 來(lái)防止碰撞的發(fā)生。當(dāng) AABB 不再重疊之后接觸會(huì)被摧毀。也許你會(huì)皺起眉頭,為了沒(méi)有發(fā)生實(shí)際碰撞的形狀(只是它們的 AABB)卻創(chuàng)建了接觸。好吧,的確是這樣的,這是一個(gè)“雞或蛋”的問(wèn)題。我們并不知道是否需要一個(gè)接觸,除非我們創(chuàng)建一個(gè)接觸去分析碰撞。如果形狀之間沒(méi)有發(fā)生碰撞,我們需要正確地刪除接觸,或者,我們可以一直等到 AABB 不再重疊。Box2D 選擇了后面這個(gè)方法。

       1)接觸監(jiān)聽(tīng)器
       通過(guò)實(shí)現(xiàn) b2ContactListener 你就可以接受接觸數(shù)據(jù)。當(dāng)一個(gè)觸點(diǎn)被創(chuàng)建時(shí),當(dāng)它持續(xù)超過(guò)一個(gè)時(shí)間步時(shí),以及當(dāng)它被摧毀時(shí),這個(gè)監(jiān)聽(tīng)器(listener)就會(huì)發(fā)出報(bào)告。請(qǐng)留意兩個(gè)形狀之間可能會(huì)有多個(gè)觸點(diǎn)。
       class MyContactListener : public b2ContactListener
      {
      public:
       void Add(const b2ContactPoint* point)
       {
       // handle add point
       }
       void Persist(const b2ContactPoint* point)
       {
       // handle persist point
       }
       void Remove(const b2ContactPoint* point)
       {
       // handle remove point
       }
       void Result(const b2ContactResult* point)
       {
       // handle results
       }
      };
       2)接觸篩選
       通常,你不希望游戲中的所有物體都發(fā)生碰撞。例如,你可能會(huì)創(chuàng)建一個(gè)只有某些角色才能通過(guò)的門。這稱之為接觸篩選,因?yàn)橐恍┙换ケ缓Y選出了。
      通過(guò)實(shí)現(xiàn) b2ContactFilter 類,Box2D 允許定制接觸篩選。這個(gè)類需要一個(gè) ShouldCollide 函數(shù),用于接收兩個(gè) b2Shape 的指針,如果應(yīng)該碰撞那么就返回 true。默認(rèn)的 ShouldCollide 實(shí)現(xiàn)使用了 6 形狀 中的 b2FilterData。
      復(fù)制代碼
      bool b2ContactFilter::ShouldCollide(b2Shape* shape1, b2Shape* shape2)
      {
       const b2FilterData& filter1 = shape1->GetFilterData();
       const b2FilterData& filter2 = shape2->GetFilterData();
       if (filter1.groupIndex == filter2.groupIndex && filter1.groupIndex != 0)
       {
       return filter1.groupIndex > 0;
       }
       bool collide = (filter1.maskBits & filter2.categoryBits) != 0 && 
      (filter1.categoryBits & filter2.maskBits) != 0;
       return collide;
      復(fù)制代碼
       12、雜項(xiàng)
       1)
      你可以實(shí)現(xiàn)一個(gè) b2BoundaryListener,這樣當(dāng)有物體超出世界的 AABB 時(shí) b2World 就能通知你。當(dāng)你得到回調(diào)時(shí),你不應(yīng)該試圖刪除物體;取而代之的是,你可以為角色做個(gè)刪除或錯(cuò)誤處理標(biāo)記,在物理時(shí)間步之后再進(jìn)行這個(gè)事件的處理。
      class MyBoundaryListener : public b2BoundaryListener
      {
       void Violation(b2Body* body)
       {
       MyActor* myActor = (MyActor*)body->GetUserData();
       myActor->MarkForErrorHandling();
       }
      };
      隨后你可以在世界對(duì)象中注冊(cè)你的邊界監(jiān)聽(tīng)器實(shí)例,這應(yīng)該安排在世界初始化過(guò)程中。
      myWorld->SetListener(myBoundaryListener);
       2)隱式摧毀
      如果你摧毀一個(gè) Box2D 實(shí)體,你應(yīng)該保證所有到它的引用都刪除了。如果你只有實(shí)體的單個(gè)引用的話,那就簡(jiǎn)單了。但如果你有很多個(gè)引用,你可能要考慮實(shí)現(xiàn)一個(gè)處理類來(lái)封裝原始指針。通常使用 Box2D 時(shí)你需要?jiǎng)?chuàng)建并摧毀許多物體,形狀還有關(guān)節(jié)。管理這些實(shí)體有些自動(dòng)化,如果你摧毀一個(gè)物體,所有它的形狀,關(guān)節(jié),以及接觸都會(huì)摧毀,這稱為隱式摧毀。任何連接于這些關(guān)節(jié)或接觸之一的物體將被喚醒,通常這是便利的。然而,你應(yīng)該意識(shí)到了一個(gè)關(guān)鍵問(wèn)題: 
      Box2D 提供了一個(gè)名為 b2WorldListener 的監(jiān)聽(tīng)器類,你可以實(shí)現(xiàn)它并提供給世界對(duì)象,隨后當(dāng)關(guān)節(jié)將被隱式摧毀時(shí)世界對(duì)象就會(huì)提醒你。
      你可以實(shí)現(xiàn)一個(gè) b2DestructionListener,這樣當(dāng)一個(gè)形狀或關(guān)節(jié)隱式摧毀時(shí) b2World 就能通知你,這可以幫助你預(yù)防訪問(wèn)無(wú)效指針。
      class MyDestructionListener : public b2DestructionListener
      {
       void SayGoodbye(b2Joint* joint)
       {
       // remove all references to joint.
       }
      };
      隨后你可以注冊(cè)它,這應(yīng)該在世界初始化過(guò)程中。
      myWorld->SetListener(myDestructionListener);

       

       

       

       

       

       

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多