官术网_书友最值得收藏!

9.4 Body和Shape

Body表示在物理世界中的一個對象,往往也對應游戲世界中的一個對象,物體具有位置、角度、質量、速度等屬性,每個剛體都包含一個形狀列表,這意味著一個剛體可以由很多個形狀組成,如由兩個圓形加一個長方形組成一個啞鈴,剛體總共可以分為靜態、動態以及動力學3種。

? 靜態剛體永遠不會移動,不管其他剛體以多大的力量推動它,它總是巋然不動,也不會與其他靜態剛體碰撞。

? 動態剛體表示場景中可以運動的對象,可以和任何剛體發生碰撞。撞到動力學剛體和撞到靜態剛體都會被彈開,撞到動態剛體,會互相作用,也就是可能互相彈開,或者其中一個撞飛另外一個。

? 動力學剛體可以移動,但不受任何力的影響,動態剛體對其施加的力,或者ApplyForce對其施加的力都無效,和靜態剛體不會發生碰撞,動力學剛體之間,也不會發生碰撞,但是動力學剛體的運動,可以對動態剛體產生力的作用

9.4.1 剛體的碰撞

在筆者的測試代碼中,一個向上移動的動力學剛體,碰到動態剛體,會將動態剛體往上頂起,碰到其他的動力學剛體,會穿過,而碰到靜態剛體,也是直接穿過!動力學剛體并不會和靜態剛體發生碰撞!當地面上有個動態剛體時,這時候一個動力學剛體從正上方往下運動,會將動態剛體緩緩壓入地面。

由于動力學剛體不受力或沖量的作用,所以只能通過Body->SetLinearVelocity設置線性速度或者關節的馬達驅動,來使其移動。如圖9-2~圖9-4演示了動力學剛體與各種剛體碰撞時的表現。

圖9-2 動力學剛體和動力學剛體互相穿透

圖9-3 動力學剛體和動態剛體互相碰撞

圖9-4 動力學剛體和靜態剛體互相穿透

如表9-1總結了各種剛體的碰撞情況,如果讀者覺得動力學剛體難以理解,可以想一想在超級瑪麗等游戲中可以跳上去的那些來回移動的平臺,它可以托著游戲者移動,但卻可以不受游戲者的影響。現實生活中的電梯也勉強可以理解為動力學剛體。

表9-1 各種剛體的碰撞情況

在游戲中經常會碰到一些單面墻壁,例如,是男人就上100層這樣的游戲中,游戲者從下往上跳時可以穿過平臺,而從上往下掉落時卻會被平臺擋住,這就需要使用到Box2d的碰撞監聽了。當監聽到碰撞事件時,判斷角色運動的方向是向上還是向下,根據判斷的結果來決定是否禁用此次碰撞。

9.4.2 創建剛體

要創建一個Body需要傳入一個物體的定義,b2BodyDef是一個內容豐富的結構,其默認構造函數如下,一般在填充完剛體描述對象的type和position之后,就會調用World的CreateBody接口來創建一個新的Body。

        b2BodyDef()
        {
            userData = NULL;                    //默認沒有額外數據
            position.Set(0.0f, 0.0f);           //默認的位置和旋轉角度
            angle = 0.0f;
            linearVelocity.Set(0.0f, 0.0f);     //線性加速度和角速度等
            angularVelocity = 0.0f;
            linearDamping = 0.0f;
            angularDamping = 0.0f;
            allowSleep = true;
            awake = true;                       //一開始就是醒著的狀態
            fixedRotation = false;
            bullet = false;                     //當物體需要在高速運動中進行碰撞,開啟它
            type = b2_staticBody;               //默認是一個靜態物體
            active = true;
            gravityScale = 1.0f;
        }

剛體的大致結構如圖9-5所示,每個剛體都會有其對應的一些形狀,在Box2d中通過Fixture來描述這些形狀,以及它們的密度、摩擦、彈性等。

圖9-5 剛體的組成

使用Body的CreateFixture可以為剛體設置一個新的形狀,也可以為剛體設置很多形狀,通過Body的SetGravityScale還可以設置剛體的重力縮放,某些物體可以讓其不受重力的影響。

物體的摩擦系數是一個0~1之間的數,0表示非常光滑,1表示非常粗糙。物體的彈性系數(恢復系數)也是一個0~1之間的數,0表示沒有彈性,1表示沒有能量損失的反彈。密度也是一個必須要設置的數據,假設將密度設置為0,物體仍然會往下掉落,但是沒有任何重量的物體堆疊起來就會變成如圖9-6所示。

圖9-6 密度為0的堆箱子

在Box2d里可以創建的形狀包含Circle圓形、Edge邊界線、Polygon多邊形以及Chain鏈條。多邊形是一個閉合的多邊形,而Chain是一系列點,可以理解為一個不閉合的多邊形。形狀主要是用于物理模擬中的碰撞檢測,在創建完Body之后,對Body進行設置。下面看一下如何創建多邊形。

        b2CircleShape circle;                   //圓形
        circle.m_radius = 1.0f;                 //半徑為1

        b2EdgeShape edge;
        edge.Set(b2Vec2(-100.0f, 0.0f),         //創建一條平行于x軸的邊
            b2Vec2(100.0f, 0.0f))

        b2PolygonShape polygon;                 //創建一個封閉的多邊形
        polygon.SetAsBox(5.0f, 5.0f);           //創建一個長和寬都為10的正方形

        b2ChainShape shape;                     //鏈形
        b2Vec2* arr = new b2Vec2[5];
        arr[0] = b2Vec2(0.0f, 0.0f);
        arr[1] = b2Vec2(10.0f, 10.0f);
        arr[2] = b2Vec2(20.0f, 0.0f);
        arr[3] = b2Vec2(30.0f, 10.0f);
        arr[4] = b2Vec2(40.0f, 0.0f);           //數組描述了一個’W’形狀
        shape.CreateChain(arr, 5);              //傳入一系列點來確定形狀
        delete[] arr;

在創建閉合多邊形的時候,也可以使用Set()函數,像Chain一樣,傳入一個頂點數組來創建形狀,在為Body創建Fixture時,將shape對象的指針賦值給b2FixtureDef對象的shape變量即可。

上面的Edge常用于創建世界的邊界,其確實很適合做這個工作,而且做得要比Polygon要好。至于Chain,感覺像是一系列連續的Edge。

SetAsBox是個很好用的接口,可以節省代碼,需要注意的一點是,傳入的參數是寬和高的一半,函數會以當前位置為中心,創建一個四邊形

填充好Shape數據之后,需要把它賦給對應的Fixture,同時為Fixture填充彈性、摩擦力、質量之類的屬性。最后調用Body的CreateFixture,綁定到剛體之上。

主站蜘蛛池模板: 敖汉旗| 淮北市| 荔浦县| 和静县| 绥德县| 资中县| 尉氏县| 根河市| 廉江市| 西青区| 靖边县| 离岛区| 临武县| 闽清县| 万州区| 凤山市| 阿拉善右旗| 汤阴县| 湾仔区| 新民市| 安阳市| 平江县| 石嘴山市| 安达市| 会昌县| 比如县| 商河县| 佛坪县| 镇宁| 玉田县| 通河县| 莆田市| 杭锦后旗| 磐安县| 东丰县| 黄石市| 邵武市| 东海县| 法库县| 西宁市| 麻城市|