国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

Box2d

2019-11-09 15:47:40
字體:
供稿:網(wǎng)友

一、概述

1、關(guān)于

Box2D是個二維剛體仿真庫, 用于編寫游戲。程序員可以使用它, 讓游戲中的物體運動起來更真實, 讓 游戲世界更具交互性。以游戲的角度來看,物理引擎只是個程序性動畫系統(tǒng)。(PRocedural animation)做動畫常有兩種方法, 一種是預(yù)先準(zhǔn)備好動畫所需的數(shù)據(jù),比如圖片,再一幀一幀地播放。另 一種是以一定方法,動態(tài)計算出動畫所需的數(shù)據(jù),根據(jù)數(shù)據(jù)再進行繪圖。 從這種角度看,預(yù)先準(zhǔn)備的,可稱為數(shù)據(jù)性動畫,動態(tài)計算的可稱為程序性動畫。這個區(qū)別,就類似以前我們做歷史題和數(shù)學(xué)題,做歷史題,記憶很重要,也就是答案需要預(yù)先準(zhǔn)備好的。做數(shù)學(xué)題,方法就很重要,答案是需要用方法推導(dǎo)出來的。 Box2D就是用物理學(xué)的方法,推導(dǎo)出那游戲世界物體的位置,角度等數(shù)據(jù)。而Box2D也僅僅推導(dǎo)出數(shù) 據(jù),至于得到數(shù)據(jù)之后怎么處理就是程序員自己的事情了。)Box2D用可移植的C++來寫成,它定義的大部分類型都有b2前綴, 希望這能有效消除Box2D和你自己 的游戲引擎之間的名字沖突。

2、概念

形狀(shape): 2D幾何對象, 比如圓形(circle)或多邊(polygon)。剛體(rigid body): 十分堅硬的物質(zhì), 堅硬得像鉆石,它上面任意兩點之間的距離都保持不變。在后面的討論中,我們用 物體(body)來代替剛體。夾具(fixture): fixture將形狀綁定到物體之上, 并有一定的材質(zhì)屬性, 比如密度(density), 摩擦(friction)和恢復(fù) (restitution)。約束(constraint): 約束是個物理連接, 用于消除物體的自由度。在2D中, 物體有3個自由度(水平,垂直,旋轉(zhuǎn))。如果我 們把一個物體釘在墻上(像鐘擺那樣), 那就把它約束到了墻上。這個時候,此物體就只能繞著釘子旋轉(zhuǎn) , 所以這個約束消除了它2個自由度。(注:簡單的說, 需要用幾個參數(shù)來確定物體的空間狀態(tài), 這個物體就有幾個自由度。在二維中,完全 沒有約束的條件下, 我們要確定物體的狀態(tài), 要有x坐標(biāo), y坐標(biāo), 旋轉(zhuǎn)角這三個參數(shù), 所以自由度為3。 如果物體被釘在墻上, 只要有旋轉(zhuǎn)角,就可以完全確定物體的狀態(tài),有了釘子這個約束,物體自由度 就變成了1。)接觸約束(contact constraint): 一種特殊的約束, 設(shè)計的目的是為了防止剛體被穿透, 也用于模擬摩擦和恢復(fù)。接觸約束不用你來創(chuàng) 建, 它們會自動被Box2D生成。關(guān)節(jié)(joint): 關(guān)節(jié)就是種約束, 用于將兩個或多個body固定到一起。Box2D支持不同的關(guān)節(jié)類型:轉(zhuǎn)動(revolute),棱 柱(prismatic),距離(distance)等。一些關(guān)節(jié)可以有限制(limits)和馬達(motors)。關(guān)節(jié)限制(joint limit) : 關(guān)節(jié)限制限定了一個關(guān)節(jié)的運動范圍。例如人類的胳膊肘只能在某一角度范圍內(nèi)運動。關(guān)節(jié)馬達(joint motor): 根據(jù)關(guān)節(jié)的自由度, 關(guān)節(jié)馬達可以驅(qū)動關(guān)節(jié)所連接的物體。例如, 你可以使用一個馬達來驅(qū)動一個 肘的旋轉(zhuǎn)。世界(world): 一個物理世界就是各種, 剛體(bodies), 夾具(fixtures), 約束(constraints)相互作用的集合。 Box2D支持創(chuàng) 建多個世界, 但這通常沒有必要。

3、單位

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

二、應(yīng)用

1、創(chuàng)建物理世界

1、創(chuàng)建世界: 每個Box2D程序開始時都會創(chuàng)建一個b2World對象。b2World是物理樞紐(physics hub), 用于管理內(nèi)存 、對象和模擬。根據(jù)自己的實際情況, 你可以在棧, 堆或數(shù)據(jù)區(qū)中創(chuàng)建出world。 創(chuàng)建Box2D的world很簡單。首先, 我們要定義重力矢量,另外還要告訴world是否允許body在靜止時 休眠。休眠中的body不需要任何模擬。 b2Vec2 gravity; //重力 gravity.Set(0.f, -20.f);//豎直向下 現(xiàn)在可以創(chuàng)建world對象了。注意,在這里我們是在棧中創(chuàng)建world, 所以world不能離開它的作用域。 world = new b2World(gravity);//創(chuàng)建一個物理世界 world->SetAllowSleeping(true);//允許睡眠 world->SetContinuousPhysics(true);//允許碰撞2、創(chuàng)建地面盒 2.1: 用位置(position), 阻尼(damping)等來定義body 2.2:通過world對象來創(chuàng)建body 2.3:用形狀(shape), 摩擦(friction), 密度(density)等來定義 fixture 2.4:在body上來創(chuàng)建fixture //創(chuàng)建剛體定義 b2BodyDef groundBodyDef;//創(chuàng)建地面 groundBodyDef.position.Set(0.0f, 0.0f);//原點 剛體定義中位置設(shè)置 //創(chuàng)建剛體 world創(chuàng)建剛體 b2Body* groundBody = world->CreateBody(&groundBodyDef); b2EdgeShape groundBox; //依次定義盒子的邊界 //下 groundBox.Set(b2Vec2(-visabliSize.width / PTM_RATIO, 0.7), b2Vec2(2 * visabliSize.width / PTM_RATIO, 0.7)); groundBody->CreateFixture(&groundBox, 0); //上 groundBox.Set(b2Vec2(-visabliSize.width / PTM_RATIO, visabliSize.height / PTM_RATIO), b2Vec2(2 * visabliSize.width / PTM_RATIO, visabliSize.height / PTM_RATIO)); groundBody->CreateFixture(&groundBox, 0); //左 groundBox.Set(b2Vec2(0 / PTM_RATIO, 0), b2Vec2(0 / PTM_RATIO, visabliSize.height / PTM_RATIO)); groundBody->CreateFixture(&groundBox, 0); //右 groundBox.Set(b2Vec2(visabliSize.width / PTM_RATIO, 0), b2Vec2(visabliSize.width / PTM_RATIO, visabliSize.height / PTM_RATIO)); groundBody->CreateFixture(&groundBox, 0);

2、創(chuàng)建動態(tài)剛體,并綁定精靈

1、創(chuàng)建精靈 auto sp = Sprite::create("1.png"); sp->setPosition(240,160); this->addChild(sp); 2、創(chuàng)建剛體,綁定精靈 b2BodyDef ballBodydef; ballBodydef.type = b2_dynamicBody; //動態(tài)剛體 ballBodydef.position.Set(sp->getPosition().x / PTM_RATIO, sp->getPosition().y / PTM_RATIO); //設(shè)置剛體的位置 ballBodydef.userData = sp; //綁定精靈 b2Body * ballBody = world- >CreateBody(&ballBodydef); //創(chuàng)建剛體 //我們創(chuàng)建一個多邊形shapde, 并將它附加到fixture定義上。我們先創(chuàng)建一個box shape: b2PolygonShape blockShape; blockShape.SetAsBox(0.3f, 0.3f); //接下來我們使用box創(chuàng)建一個fixture定義 b2FixtureDef ballShapeDef; ballShapeDef.shape = &blockShape; ballShapeDef.density = 50.0f; //設(shè)置密度 ballShapeDef.friction = 0.5f; //設(shè)置摩擦 ballShapeDef.restitution = 0.2f; //設(shè)置恢復(fù) //剛體添加夾具 ballBody->CreateFixture(&ballShapeDef);

3、模擬(Box2d的)世界

Box2D使用了一個叫積分器(integrator)的數(shù)值算法。 積分器在離散的時間點上模擬連續(xù)的物理方程。 它與傳統(tǒng)的游戲動畫循環(huán)一同運行。我們需要為Box2D選取一個時間步。通常來說用于游戲的物理 引擎需要至少 60Hz 的速度,也就是 1/60 的時間步。你可以使用更大的時間步,但是你必須更加小心地 為你的世界調(diào)整定義。我們也不喜歡時間步變化得太大,所以不要把時間步關(guān)聯(lián)到幀頻(除非你真的 必須這樣做)。直截了當(dāng)?shù)?這個就是時間步: float32 timeStep = 1.0f / 60.0f; 除積分器外,Box2D代碼還使用了約束求解器(constraint solver)。約束求解器用于解決模擬中的所有約束,一次一個。單個的約束會被完美的求解,然而當(dāng)我們求解一個約束的時候,我們就會稍微耽誤另一 個。要得到良好的解,我們需要多次迭代所有約束。 約束求解有兩個階段:速度、位置。在速度階段,求解器會計算必要的沖量,使得物體正確運動。而在位置階段,求解器會調(diào)整物體的位置,減少物體之間的重疊。每個階段都有自己的迭代計數(shù)。此外,如果誤差已足夠小的話,位置階段的迭代可能會提前退出。 對于速度和位置,建議的Box2D迭代次數(shù)都是10次。你可以按自己的喜好去調(diào)整這個數(shù)字,但要記 得它是性能與精度之間的折中。更少的迭代會增加性能但降低精度,同樣地,更多的迭代會降低性 能但能提高模擬質(zhì)量。對于這個簡單示例,我們不需要多次迭代。這是我們選擇的迭代次數(shù)。 int32 velocityIterations = 10; int32 positionIterations = 10; 完整代碼如下: void Box2DTest::update(float dt){ float timeStep = 1.0f / 60.0f;//更新時間(物理世界刷新次數(shù)) int32 velocityIterations = 10;//速度迭代次數(shù) int32 positionIterations = 10;//位置迭代次數(shù) //刷新 world->Step(timeStep, velocityIterations, positionIterations); //遍歷物理世界中的剛體 for (b2Body *b = world->GetBodyList(); b; b = b->GetNext()) { if (b->GetUserData()!=nullptr) { //獲取剛體綁定的精靈 auto sprite = (Sprite*)b->GetUserData(); //更新剛體綁定的精靈的位置 sprite->setPosition( Vec2( b->GetPosition().x *PTM_RATIO, b->GetPosition().y * PTM_RATIO) ); sprite->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) ); } }}

4、剛體碰撞的監(jiān)聽

代碼如下: .h文件:#include <iostream>#include "Box2D/Box2D.h"#include "cocos-ext.h"#include "cocos2d.h"using namespace std;USING_NS_CC_EXT;USING_NS_CC;class MyContactListener:public b2ContactListener{public: b2World* _world; Layer* _layer; MyContactListener(); MyContactListener(b2World* w,Layer* c); ~MyContactListener(); virtual void BeginContact(b2Contact* contact);//碰撞開始 virtual void EndContact(b2Contact* contact);//碰撞結(jié)束 virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);//持續(xù)接觸時響應(yīng) //b2Manifold結(jié)構(gòu)含有一個法向量和最多兩個的接觸點。向量和接觸點都是相對于局部坐標(biāo)系。為方便接觸求解器處理,每個接觸點都存儲了法向沖量和切向(摩擦)沖量。 virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);//持續(xù)接觸時響應(yīng),調(diào)用完preSolve后調(diào)用}; .cpp文件:#include "MyContactListener.hpp"MyContactListener::MyContactListener(){}MyContactListener::MyContactListener(b2World* w,Layer* c){ _world = w; _layer = c;}MyContactListener::~MyContactListener(){}void MyContactListener::BeginContact(b2Contact *contact){ log("BegainContact");}void MyContactListener::EndContact(b2Contact* contact){ log("EndContact");}void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold){ log("PreSolve");}void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse){ log("PostSolve"); //Solve計算完成后調(diào)用的函數(shù) float force = impulse->normalImpulses[0];//受到的力 if (force>2) { b2Body* bodyA = contact->GetFixtureA()->GetBody(); b2Body* bodyB = contact->GetFixtureB()->GetBody(); auto spriteA = (Sprite*)bodyA->GetUserData(); auto spriteB = (Sprite*)bodyB->GetUserData(); if (spriteA != nullptr && spriteB != nullptr) { spriteA->setTag(4); spriteB->setTag(4); } }}最后給物理世界設(shè)置碰撞監(jiān)聽:listener=new MyContactListener(world,this);world->SetContactListener(listener);
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 芦山县| 邵武市| 洪泽县| 浦县| 筠连县| 黄山市| 碌曲县| 福海县| 牡丹江市| 白城市| 龙南县| 宜都市| 景谷| 磐安县| 双鸭山市| 泊头市| 托里县| 元谋县| 宜兰市| 玛曲县| 麻江县| 封开县| 山阴县| 贵州省| 菏泽市| 漠河县| 磐安县| 张家界市| 海林市| 桓台县| 黎川县| 灵丘县| 阿巴嘎旗| 垦利县| 黔西| 罗江县| 岳阳市| 颍上县| 伊宁市| 珲春市| 齐河县|