Box2d預(yù)覽

初始化box2d

這篇應(yīng)該是box2d的一個(gè)整體的說(shuō)明锌杀,它有哪些功能,還有一些總體的概括逝钥。

參數(shù)

積分步

Box2D是由一些代碼構(gòu)成的積分器澄耍,積分器在離散點(diǎn)上做模擬物理運(yùn)算,它將與游戲動(dòng)畫(huà)循環(huán)一同運(yùn)行(時(shí)間步的作用)
物理的計(jì)算需要60幀

約束器晌缘,用于求解器解決模擬中的約束齐莲,一次一個(gè),的那個(gè)約束會(huì)被求解磷箕,但是在求解一個(gè)的時(shí)候會(huì)耽誤另一個(gè)选酗。
處理辦法:迭代多次 box2D建議是10次
少的迭代會(huì)增加性能降低精度 一個(gè)時(shí)間步遍歷10次約束。

Api

公差保證其工作 Box2D可以處理0.1到10米之間的移動(dòng)物體,

  • body創(chuàng)建過(guò)程
BodyDef bodyDef = new BodyDef();
bodyDef.type = this.type;
bodyDef.position.set(position.x,position.y);
Body body = Constant.world.createBody(bodyDef);
if (shape == null){
    PolygonShape polygonShape = new PolygonShape();
    polygonShape.setAsBox(width, height);
    shape = polygonShape;
}
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
if (categoryBits != -1){
    fixtureDef.filter.categoryBits = categoryBits;
}
if (maskBits != -1) {
    fixtureDef.filter.maskBits = maskBits;
}
body.createFixture(fixtureDef);
shape.dispose();

世界刷新

Constant.world.step(1/60f, 6, 2);
Constant.renderer.render(Constant.world,Constant.combined);

角度轉(zhuǎn)換

float degrees = (float) Math.toDegrees(body.getAngle());

如果和精靈綁定岳枷,如果需要旋轉(zhuǎn)芒填,需要設(shè)置旋轉(zhuǎn)的位置中心點(diǎn)呜叫。

ApplyForce

ApplyForce方法會(huì)在剛體上施加力

F = ma 使得物體存在加速度

ApplyMpulse

不會(huì)產(chǎn)生力,直接影響速度 會(huì)使得速度疊加殿衰,產(chǎn)生新速度

setLineVelocity

它會(huì)將速度變?yōu)楫?dāng)前速度朱庆。調(diào)用之前需要wakeup()

//給一個(gè)力     f = ma
if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
    body.applyForce(new Vector2(100,0), body.getWorldCenter(),true);
}

//疊加
if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
    body.applyLinearImpulse(new Vector2(-100,0), body.getWorldCenter(),true);
}

//設(shè)置
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
    body.setLinearVelocity(new Vector2(-100,0));
}

多邊形

  • 組合 通過(guò)多個(gè)組合出一個(gè)完整的

  • 原生

PolygonShape shape = new PolygonShape();
Vector2 [] vertices = new Vector2[4];
vertices[0] = new Vector2();
vertices[0].set(50, 50);
vertices[1] = new Vector2();
vertices[1].set(200, 50);
vertices[2] = new Vector2();
vertices[2].set(100, 200);
vertices[3] = new Vector2();
vertices[3].set(200, 200);
shape.set(vertices);

對(duì)于凹多邊形會(huì)出現(xiàn)錯(cuò)誤。

b2Separator但是java框架並麼有找到闷祥。 ……

存儲(chǔ)數(shù)據(jù)

BodyDef bodyDef1 = new BodyDef();
bodyDef1.position.set(230, 130);//記得米和像素的轉(zhuǎn)換關(guān)系
//2.Box2D世界工廠更具需求創(chuàng)建createBody()生產(chǎn)剛體
body=Constant.world.createBody(bodyDef1);

FixtureDef shapeRequest1 = new FixtureDef();
shapeRequest1.density = 3;
shapeRequest1.friction = 0.3F;
shapeRequest1.restitution = 0.2F;

PolygonShape shape1 = new PolygonShape();
shape1.setAsBox(50,50);

FixtureDef bgDef1 = new FixtureDef();
bgDef1.shape = shape1;
body.createFixture(bgDef1);

Image image = new Image(new Texture("1.png"));
image.setSize(100,100);

body.setUserData(image);

將數(shù)據(jù)存儲(chǔ)在body里面娱颊,需要屬于到時(shí)候在將值取出來(lái)。一般可以將紋理存儲(chǔ)在剛體中凯砍,使用的時(shí)候從剛體中取出箱硕,然后渲染。

移動(dòng)鼠標(biāo)(這個(gè)demo沒(méi)有弄好,沒(méi)寫出來(lái))

MouseJointDef def = new MouseJointDef();
def.bodyA :一個(gè)
def.bodyB :另一個(gè)
def.maxForce : 限制鼠標(biāo)關(guān)節(jié)上的最大的力 這里通常需要乘以剛體的
質(zhì)量multiplier * mass * gravity

自定義重力

重力是一個(gè)向下的力悟衩,但是熱氣球可以在空中剧罩。

實(shí)現(xiàn)方法有兩種:一、加減法抵消重力座泳;二惠昔、重置重力。下面我們來(lái)詳細(xì)一下這兩種方法挑势。簡(jiǎn)單說(shuō)就是將力消除掉舰罚。

有方向 有大小的力 重力 = 質(zhì)量 * 重力加速度

得到身體的總質(zhì)量。 * @返回質(zhì)量薛耻,通常以千克(kg)為單位营罢。
body.getMass();

//獲取身體的質(zhì)量數(shù)據(jù)。 * @返回包含身體質(zhì)量饼齿,慣性和中心的結(jié)構(gòu)
body.getMassData();

public class MassData {
    /** The mass of the shape, usually in kilograms. **/
    public float mass;

    /** The position of the shape's centroid relative to the shape's origin. **/
    public final Vector2 center = new Vector2();

    /** The rotational inertia of the shape about the local origin. **/
    public float I;  //慣性
}

給重力一個(gè)反作用力

body.ApplyForce(new b2Vec2(0, -10*body.GetMass()),body.GetWorldCenter());

Box2D中的Dynamics包下有一個(gè)b2Island類饲漾,類中有一個(gè)Solve方法,這方法通過(guò)gravity形參對(duì)剛體進(jìn)行模擬缕溉。

監(jiān)聽(tīng)撞擊

分類 和 掩碼

分類: 分類我是誰(shuí)
掩碼: 我撞擊誰(shuí)

public class WorldContactListener implements ContactListener{
   @Override
    public void beginContact(Contact contact) {
        Fixture fixtureA = contact.getFixtureA();
        Fixture fixtureB = contact.getFixtureB();
        if (fixtureA.getFilterData().categoryBits == Constant.PILL_BIT ||
                fixtureB.getFilterData().categoryBits == Constant.PILL_BIT) {
            // pill
            if (fixtureA.getFilterData().categoryBits == Constant.PLAYER_BIT) {
            }else{
            }
        }
    }
    @Override
    public void endContact(Contact contact) {
    }
    @Override
    public void preSolve(Contact contact, Manifold oldManifold) {
    }
    @Override
    public void postSolve(Contact contact, ContactImpulse impulse) {
    }
}

存儲(chǔ)數(shù)據(jù)

body.setUserData(object);

獲取數(shù)據(jù)

Object userData = body.getUserData();
float density = -1;     密度
float friction = -1;    摩擦力
float restitution = -1; 反饋

像素

Box2D使用MKS單位和弧度表示角度考传,通常使用像素作為單位的力图,只需要使用openGl視口縮放世界縮放的屏幕空間棋枕。

float lowerX=-25.0f, upperX=25.0f, lowerY=-5.0f, upperY=25.0f;
gluOrtho2D(lowerX, upperX, lowerY, upperY);

如果游戲?yàn)橄袼鼐珧迹敲醇凹揖邚南袼剞D(zhuǎn)換為米墓造,同時(shí),將Box2D接收到的值從米轉(zhuǎn)換為像素速缆。

xMeters=0.02f*xPixels;yMeters=0.02f*yPixels;
xPixels=50.0華氏度 *xMeters;yPixels=50.0華氏度 *yMeters;

Fixture

body.createFixture(shape, 1.0f);
body.createFixture (FixtureDef def)

認(rèn)識(shí)

Box2d是通過(guò)b2AABB表示的
Box2D中的大小是通過(guò)設(shè)置兩個(gè)對(duì)角頂點(diǎn)upperBound和lowerBound實(shí)現(xiàn)的
對(duì)于靜止不動(dòng)的就設(shè)置睡著规哪。

(二)

Box 2D計(jì)量單位米

模擬的時(shí)長(zhǎng) 碰撞后檢測(cè)的運(yùn)行次數(shù)

Constant.world.step(1/60f, 6, 2);
Constant.renderer.render(Constant.world,Constant.combined);

剛體創(chuàng)建可以看作是一個(gè)工廠烁落,創(chuàng)建步驟:

  • 創(chuàng)建剛體鸟蜡,需要提供位置 角度
  • 定義剛體形狀
    a) density:質(zhì)量
    b) friction:表面摩擦力
    c) restitution:表面張力膜赃,這個(gè)值越大,剛體越硬
    d) SetAsBox:設(shè)置剛體為矩形

步驟 :

  • 創(chuàng)建世界

那條線可以可以標(biāo)示圓形剛體的角度揉忘,灰色表示剛體靜止跳座,不參與Box2D模擬計(jì)算端铛,紅色表示剛體
為運(yùn)動(dòng)的,要進(jìn)行物理模擬計(jì)算疲眷,專業(yè)分類可以節(jié)省CPU開(kāi)支禾蚕。

關(guān)節(jié)

創(chuàng)建實(shí)例

Body body1 = createBody(600);
Body body2 = createBody(0);

//關(guān)節(jié)
WeldJointDef def = new WeldJointDef();
def.collideConnected = false;
def.initialize(body1,body2,new Vector2(0,0));
Constant.world.createJoint(def);

必須要是他的子類

public Joint createJoint (JointDef def) {
long jointAddr = createProperJoint(def);
Joint joint = null;
if (def.type == JointType.DistanceJoint) joint = new DistanceJoint(this, jointAddr);
if (def.type == JointType.FrictionJoint) joint = new FrictionJoint(this, jointAddr);
if (def.type == JointType.GearJoint) joint = new GearJoint(this, jointAddr, ((GearJointDef) def).joint1, ((GearJointDef) def).joint2);
if (def.type == JointType.MotorJoint) joint = new MotorJoint(this, jointAddr);
if (def.type == JointType.MouseJoint) joint = new MouseJoint(this, jointAddr);
if (def.type == JointType.PrismaticJoint) joint = new PrismaticJoint(this, jointAddr);
if (def.type == JointType.PulleyJoint) joint = new PulleyJoint(this, jointAddr);
if (def.type == JointType.RevoluteJoint) joint = new RevoluteJoint(this, jointAddr);
if (def.type == JointType.RopeJoint) joint = new RopeJoint(this, jointAddr);
if (def.type == JointType.WeldJoint) joint = new WeldJoint(this, jointAddr);
if (def.type == JointType.WheelJoint) joint = new WheelJoint(this, jointAddr);
if (joint == null) throw new GdxRuntimeException("Unknown joint type: " + def.type); 

兩個(gè)剛體保持一致,做某種運(yùn)動(dòng)

DistanceJointDef

Body body1 = createBody(800);
Body body2 = createBody(188);
DistanceJointDef  jointDef = new DistanceJointDef();
jointDef.bodyA = body1;
jointDef.bodyB = body2;
jointDef.initialize(body1,body2,new Vector2(Constant.width/2-100,500),new Vector2(Constant.width/2,500));

這個(gè)可以用自行車的前后輪胎進(jìn)行類比

馬達(dá)關(guān)節(jié)

計(jì)算路徑

提前知道剛體運(yùn)動(dòng)的路徑

a)剛體的位置,n個(gè)timestep后,剛體的位置,用于小鳥(niǎo)的軌跡.
b)計(jì)算剛體的最大高度,初始速度v0飛出后,可以到達(dá)的最大高度;
c)計(jì)算剛體到達(dá)某個(gè)位置需要的初始速度.

計(jì)算剛體位置

s = 1/2 * a * t * t;

實(shí)際

數(shù)列的總和

間距 1/2 * n * (a1 + an)

1/2 * n (a1 + a1 + an) =

最大高度

u = u0 + at

計(jì)算初始速度

剛體的Box2D縮放

更改形狀

//得到剛體,然后重新設(shè)置形狀
PolygonShape shape = (PolygonShape) body.getFixtureList().get(0).getShape();
Vector2[] vertices1 = new Vector2[3];
vertices1[0] = new Vector2(20, 0);
vertices1[1] = new Vector2(20, 40);
vertices1[2] = new Vector2(0, 0);
polygonShape.set(vertices1);

獲取碰撞點(diǎn)

得到碰撞點(diǎn)的位置 通過(guò)b2Contact對(duì)象 得到碰撞信息

GetManifold()獲取相對(duì)于剛體的碰撞點(diǎn)本地坐標(biāo)
GetWorldManifold()舞臺(tái)碰撞點(diǎn)的全局坐標(biāo)

WorldManifold worldManifold = contact.getWorldManifold();
Vector2 point = worldManifold.getPoints()[0];
System.out.println(point.x+"-----------"+point.y);

BeginContact:當(dāng)碰撞發(fā)生時(shí)觸發(fā)該方法
EndContact:當(dāng)碰撞結(jié)束時(shí)觸發(fā)該方法

燈具開(kāi)始時(shí)調(diào)用
public void beginContact(Contact contact) {
   //得到stage的坐標(biāo)
    WorldManifold worldManifold = contact.getWorldManifold();
    Vector2 point = worldManifold.getPoints()[0];
    System.out.println(point.x+"-----------"+point.y);
}

停止時(shí)調(diào)用
public void endContact(Contact contact) {

}

contact更新之后執(zhí)行的方法  
public void preSolve(Contact contact, Manifold oldManifold) {
    //得到stage的坐標(biāo)
    WorldManifold worldManifold = contact.getWorldManifold();
    Vector2 point = worldManifold.getPoints()[0];
    System.out.println(point.x+"-----------"+point.y);
}

@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
}

Contact:管理兩個(gè)形狀之間的接觸。每個(gè)重疊AABB都有一個(gè)觸點(diǎn),因此可能存在沒(méi)有接觸點(diǎn)的接觸對(duì)象

無(wú)阻尼勻速運(yùn)動(dòng)

Box2D物理引擎默認(rèn)情況下狂丝,對(duì)世界b2World里的剛體都是模擬自由落體運(yùn)動(dòng)换淆,并且因?yàn)槟Σ亮Φ挠绊懀?br> 剛體會(huì)慢慢的停下來(lái)(在物理學(xué)上也叫做有阻尼運(yùn)動(dòng))

world = world = new b2World(new b2Vec2(0,0), true); 無(wú)重力
給一個(gè)反作用的力 消除重力

SetLinearVelocity()設(shè)置速度 ,但是存在阻力

不斷的調(diào)整速度大小 不包括方向

isSensor屬性創(chuàng)建感應(yīng)區(qū)域

設(shè)置剛體是不是參與物理模擬美侦。

  • false (default) 碰撞后進(jìn)行反彈 或者 變向運(yùn)動(dòng)
  • truw 只會(huì)進(jìn)行碰撞檢測(cè),并不會(huì)進(jìn)行碰撞后的物理運(yùn)動(dòng)魂奥。

比如下落菠剩,并不會(huì)撞擊了地面就停止,而是撞擊了地面會(huì)檢測(cè)到耻煤,然后穿過(guò)去 只檢測(cè)不執(zhí)行

碰撞進(jìn)行分類

Filter是”過(guò)濾”的意思
FilterData可以簡(jiǎn)單的理解成用來(lái)過(guò)濾碰撞剛體(比如接下來(lái)哦我么要實(shí)現(xiàn)的矩形只與矩形剛體碰撞具壮,圓形只與
圓形剛體碰撞)。
FilterData有3個(gè)屬性:groupIndex哈蝇、categoryBits和maskBits

groupIndex : 剛體屬于哪一個(gè)組 只與同組的發(fā)生碰撞
categoryBits : 必須是2的 n次方

maskBits:掩碼就是我需要去注意誰(shuí)

Box2DDebugRenderer

Box2DebugRenderer 這個(gè)類除了不繪制AABB,其他都繪制棺妓。

浮力效果

剛開(kāi)始接觸的時(shí)候給一個(gè)浮力,占用的體力越大炮赦,浮力就越大怜跑,還會(huì)出現(xiàn)旋轉(zhuǎn)的現(xiàn)象。

ApplyForce No

BuoyancyController

···有空補(bǔ)···

鏡頭跟隨

方式一:

一個(gè)物體最左邊吠勘,相機(jī)性芬,背景不動(dòng),到達(dá)屏幕中央剧防,相機(jī)開(kāi)始跟隨運(yùn)動(dòng)

方式二:

螞蟻?zhàn)叩阶雷又醒氲臅r(shí)候植锉,桌子開(kāi)始左邊移動(dòng)

剛體碰撞處理函數(shù)

Fixture fixtureA = contact.getFixtureA();
Fixture fixtureB = contact.getFixtureB();
short categoryBits = fixtureA.getFilterData().categoryBits;
short categoryBits1 = fixtureB.getFilterData().categoryBits;
if (categoryBits == Constant.BUTT_BIT){
    if (categoryBits1 == Constant.BLACK_BIT) {
        fixtureA.getBody().setLinearVelocity(0, -71);
    }else if (categoryBits1 == Constant.BUTTOM_BIT){
        fixtureA.getBody().setLinearVelocity(0, 71);
    }
}else if (categoryBits1 == Constant.BUTT_BIT){
    if (categoryBits == Constant.BLACK_BIT) {
        fixtureB.getBody().setLinearVelocity(0, -71);
    }else if (categoryBits == Constant.BUTTOM_BIT){
        fixtureB.getBody().setLinearVelocity(0, 71);
    }
}

我們并不知道對(duì)方是誰(shuí),誰(shuí)是我峭拘,需要不停的判斷俊庇,所有可以自定義外部函數(shù)

修改源碼,在body源碼加入方法

/**
 *  add myself kw
    */
interface Handler{
    public void beginContactHanlder();
}

private Handler handler;

public void setHandler(Handler handler) {
    this.handler = handler;
}

public void handler(){
    if (handler != null){
        handler.beginContactHanlder();
    }
}

剛體碰撞檢測(cè)

Box2D中獲取碰撞對(duì)象的方法有兩種鸡挠。

  • 一個(gè)是通過(guò)world.GetContactList().bodyA和bodyB來(lái)獲取碰撞雙方辉饱;
  • 另外一個(gè)是自定義Box2D.Dynamics下的b2ContactListener類,偵聽(tīng)碰撞后的事件拣展,然后做進(jìn)一步的處理鞋囊。
Array<Contact> contactList = Constant.world.getContactList();
System.out.println("====>>>>>");
Fixture fixtureA = contactList.get(0).getFixtureA();
Fixture fixtureB = contactList.get(0).getFixtureB();

關(guān)節(jié)

box2d會(huì)通過(guò)關(guān)節(jié)將兩個(gè)剛體綁在一起,使得兩個(gè)剛體運(yùn)動(dòng)在關(guān)節(jié)的作用下相互制約相互影響形成有規(guī)律的運(yùn)動(dòng)瞎惫。
box2Joint的創(chuàng)建方法

  • 創(chuàng)建def對(duì)象溜腐,通過(guò)設(shè)置屬性進(jìn)行創(chuàng)建
RevoluteJointDef def = new RevoluteJointDef();
def.initialize(box2DImage,body1,new Vector2(10,100));
Constant.world.createJoint(def);

說(shuō)明:Joint and JointDef不會(huì)直接創(chuàng)建译株,它們是虛擬的抽象類,作為父類代碼的多態(tài)和重構(gòu)挺益。

屬性:

  • BodyA
  • BodyB
  • CollideConnected:表示關(guān)節(jié)鏈接的兩個(gè)物體之間是否可以發(fā)生碰撞模擬歉糜,默認(rèn)為false,不發(fā)生碰撞,可以穿透

關(guān)節(jié)的屬性

  • enableMotor:是否開(kāi)啟馬達(dá)屬性 默認(rèn)false
  • motorSpeed:在剛體運(yùn)懂情況下望众,可以到達(dá)的最大線速度和最大角速度匪补。
  • maxMotorTorque:關(guān)節(jié)可以施加最大的力。

這個(gè)過(guò)程中烂翰,剛體的角速度和線速度會(huì)一直增加夯缺,直到motorSpeed屬性
另一個(gè)屬性可以作為旋轉(zhuǎn)摩檫力使用,設(shè)置motorspeed屬性值為0甘耿,maxMotorTorque作用會(huì)阻止剛體在原來(lái)的狀態(tài)踊兜,直到外力大于maxMotorToorque屬性

彈簧屬性:

  • frequencyHz和damping屬性,運(yùn)行剛體在運(yùn)動(dòng)時(shí)偏離節(jié)點(diǎn)佳恬,偏移后會(huì)收到一個(gè)力捏境,使得它可以回到原來(lái)的位置。所以這兩個(gè)屬性就會(huì)在影響它毁葱。
  • frequencyHz:彈簧系統(tǒng)的震動(dòng)頻率垫言,可以看作時(shí)彈簧的彈性系數(shù),系數(shù)越大倾剿,回歸的系數(shù)就越大筷频。
  • dempingRaio:剛體回歸節(jié)點(diǎn)收到的阻尼,0~1前痘,值越大截驮,阻力越大。

不常使用的

  • GetReactionForce()
  • GetReactionTorque()

鼠標(biāo)關(guān)節(jié)

和鼠標(biāo)是有關(guān)聯(lián)的际度,可以實(shí)現(xiàn)鼠標(biāo)的拖拽

  • bodyA:一個(gè)空剛體
  • bodyB:另一個(gè)
  • target:創(chuàng)建關(guān)節(jié)時(shí)葵袭,target時(shí)bodyB被拖動(dòng)收到前置的本地錨點(diǎn),bodyB可以繞著旋轉(zhuǎn)乖菱,他是目標(biāo)位置坡锡,
  • maxForce:鼠標(biāo)關(guān)節(jié)拖拽bodyB時(shí),施加最大的作用力

PrismaticJointDef

vector2 axis = new Vector2(6, 0);
//            axis.nor();
//bodyA 固定轉(zhuǎn)軸
//bodyB 運(yùn)動(dòng)的
//開(kāi)始位置
//方向    axis的值窒所,確定了從開(kāi)始到結(jié)束的夾角
pjd.initialize(ground, body, new Vector2(0, 0), axis);

pjd.motorSpeed = 10.0f;
pjd.maxMotorForce = 10000.0f;
pjd.enableMotor = true;
pjd.lowerTranslation = 0;
pjd.upperTranslation = 20.0f;
pjd.enableLimit = true;
m_joint = (PrismaticJoint)world.createJoint(pjd);

夾角的確定

axis點(diǎn)和anchor的夾角鹉勒,作用只的大小沒(méi)有太大意義的。

內(nèi)部做了許多的計(jì)算 模擬 所以值比較大容易造成抖動(dòng)

解決方法:將axis直接做成夾角就可以了 axis.nor();轉(zhuǎn)換為向量吵取。
夾角與固定的保持不變禽额,也就是bodyA保持相對(duì)不變,bodyA變化了,夾角也會(huì)隨著變化脯倒。

上面主要對(duì)角度進(jìn)行了控制实辑,下來(lái)我們對(duì)他的范圍也進(jìn)行控制,axis指定了角度藻丢,然后按照角度會(huì)不斷的延申剪撬,為了不超出去

  • enablLimit:對(duì)剛體移動(dòng)范圍是否進(jìn)行約束,默認(rèn)為false,true就表示將范圍限制在

    • lowerTranslation
    • upperTranlation

要求:upper大于lower

使用場(chǎng)景

固定路徑悠反,比如一個(gè)人從橋的這一頭走到下一頭残黑。

線性關(guān)節(jié)

LineJoint他是一個(gè)特殊的平行關(guān)節(jié),他的特爾二叔之處就是可以繞著anchorB進(jìn)行旋轉(zhuǎn)斋否。

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

旋轉(zhuǎn)關(guān)節(jié)梨水,可以看作一個(gè)軸,繞著軸旋轉(zhuǎn)的車輪茵臭,這個(gè)關(guān)節(jié) 也有限制疫诽,比如最大角度,還有夾角笼恰。其次還有一些其他的函數(shù)踊沸。

  • 角速度:JointSpeed
  • 關(guān)節(jié)的旋轉(zhuǎn)角:JointAngle
  • 當(dāng)前關(guān)節(jié)的扭矩力:MotorTorque

通過(guò)限制歇终,可以做成蹺蹺板

作用

可以在游戲里面作為車輪社证。

蹺蹺板

DistanceJoint

距離關(guān)節(jié):包含兩個(gè)節(jié)點(diǎn),分別對(duì)應(yīng)兩個(gè)剛體评凝,使得各自繞著各自的軸轉(zhuǎn)動(dòng)追葡,這個(gè)兩個(gè)的距離不變

WeldJoint粘貼關(guān)節(jié)

將兩個(gè)剛體,連接成一個(gè)剛體奕短。這個(gè)節(jié)點(diǎn)就是將它們死死的連接在一起宜肉。兩個(gè)剛體是一樣的,但是受到節(jié)點(diǎn)限制翎碑,使得兩個(gè)保持不變谬返,看起來(lái)像一個(gè)整體,如果將節(jié)點(diǎn)刪除日杈,會(huì)將兩個(gè)分開(kāi)遣铝。分別各自的速度,角速度莉擒。

使用

那個(gè)一個(gè)圓旋轉(zhuǎn)的游戲就可以使用它酿炸。

滑輪節(jié)點(diǎn)

滑輪作用:牽引負(fù)載 改變施加力 方向

柔體實(shí)現(xiàn)

weldJoint來(lái)實(shí)現(xiàn)

補(bǔ)充

獲取局部點(diǎn)的世界速度。 *請(qǐng)注意涨冀,每次調(diào)用此方法時(shí)填硕,都會(huì)返回相同的Vector2實(shí)例。

getLinearVelocityFromLocalPoint (Vector2 localPoint)

x y z 坐標(biāo)鹿鳖,以剛體自身建立坐標(biāo)系扁眯,剛體自身的方向位移

public int direction() {
    final float tolerance = 0.2f;
    if (getLocalVelocity().y < -tolerance) {
        return DIRECTION_BACKWARD;
    } else if (getLocalVelocity().y > tolerance) {
        return DIRECTION_FORWARD;
    } else {
        return DIRECTION_NONE;
    }
}

獲取公差的方式:

  • 獲取局部點(diǎn)的世界速度壮莹。 *請(qǐng)注意,每次調(diào)用此方法時(shí)恋拍,都會(huì)返回相同的Vector2實(shí)例
  • 給定世界向量垛孔,獲取局部向量。 *請(qǐng)注意施敢,每次調(diào)用此方法時(shí)周荐,都會(huì)返回相同的Vector2實(shí)例。
    worldVector世界坐標(biāo)中的向量僵娃,返回相應(yīng)的局部向量概作。
  • getLocalVector 給定世界向量求局部向量
 mBody.getLocalVector(mBody.getLinearVelocityFromLocalPoint(new Vector2(0, 0)));

根據(jù)局部坐標(biāo)得到世界坐標(biāo)

getWorldVector

摩檫力和阻尼區(qū)別

摩擦與速度無(wú)關(guān),阻尼與速度有關(guān),力的大小是速度的函數(shù)

銷毀

設(shè)置位置

this.body.setTransform(new Vector2(20,20),10);

碰撞

box2D碰撞可以實(shí)現(xiàn)碰撞檢測(cè)默怨,實(shí)現(xiàn)反彈/變向等碰撞模擬讯榕。碰撞之后如何處理,比如粘貼匙睹,消失等愚屁,或者碰撞點(diǎn)的發(fā)一些特效。

什么是碰撞

兩個(gè)接觸或者部分重疊痕檬,box2d分為兩種一種是形狀發(fā)生的重疊接觸霎槐,另一種是最小包圍盒發(fā)生的接觸和重疊,所引發(fā)的碰撞梦谜。QueryAABB和FattenAABB丘跌,后者的范圍要大,不需要考慮形狀唁桩。

碰撞結(jié)束之后的處理闭树。

  • 一種是獲得Contact列表
  • ContactListener

ContactList()獲取列表

得到的是Contact列表,但是需要區(qū)分World中的ContactList()和body中的ContactList()

ContactListener

沒(méi)有事件處理委派機(jī)制荒澡,僅僅提供一些函數(shù)报辱,分別表示碰撞的不同階段,Contact表示當(dāng)前處理函數(shù)的對(duì)象单山。

一般常用的是這個(gè)監(jiān)聽(tīng)函數(shù)碍现。

我們可以通過(guò)Contact對(duì)其 做一些操作,比如規(guī)避碰撞或者是對(duì)碰撞做一些操作(恢復(fù))饥侵。

Contact的生命周期:從開(kāi)始潛在碰撞開(kāi)始鸵赫,一直到最小包圍盒不在重疊 銷毀
碰撞發(fā)生之后,我們只能看到

FixtureA和FixtureB

返回兩個(gè)碰撞形狀的對(duì)應(yīng)的對(duì)象躏升。但是我們順利獲取碰撞對(duì)象辩棒。AB無(wú)法區(qū)分信息,我們可以使用setUserData()添加信息,

getManiFold()

保存碰撞點(diǎn)信息一睁,是本地系統(tǒng)坐標(biāo)钻弄,用于內(nèi)部?jī)?yōu)化使用,實(shí)際應(yīng)用中都是用的是全局坐標(biāo)者吁,并設(shè)置一些碰撞效果窘俺。

WorldManifold worldManifold1 = contact.getWorldManifold();
//碰撞點(diǎn)對(duì)應(yīng)邊對(duì)應(yīng)的法向量
Vector2 normal = worldManifold.getNormal();
//碰撞點(diǎn)的坐標(biāo)
Vector2[] points = worldManifold.getPoints();
//碰撞點(diǎn)鼠
int numberOfContactPoints = worldManifold.getNumberOfContactPoints();

isTouching()

重疊為true 沒(méi)有重疊為false;

setEnable()和IsEnable()

游戲進(jìn)行的某個(gè)時(shí)刻,不需要模擬复凳,可以將設(shè)置able狀態(tài)瘤泪。false:關(guān)閉,忽略當(dāng)前碰‘

這狀態(tài)只會(huì)保持一個(gè)step(),所以需要長(zhǎng)時(shí)間的育八,就需要持續(xù)設(shè)置对途。

但是這樣也是不可以的,因?yàn)橐呀?jīng)完成了 模擬髓棋。

正確的處理方式:

在b2ConListener中對(duì)象或者子類中preSovle函數(shù)調(diào)用setEnable()实檀。

step的執(zhí)行過(guò)程

  • contact開(kāi)啟
  • presolve
  • 碰撞模擬

所以在碰撞模擬之前就將其禁用了,進(jìn)而就會(huì)忽略當(dāng)前的碰撞按声。

setEnable只會(huì)就會(huì)不在派發(fā)postSolve事件膳犹。

setSensor()

對(duì)象不會(huì)進(jìn)行碰撞模擬,可以直接穿過(guò)签则。這是fixture,

bContact也有一個(gè)须床,可以在setSensor傳入true,作為感應(yīng)區(qū)怀愧,不會(huì)進(jìn)行碰撞模擬

setFriction

摩檫力侨颈,執(zhí)行了這個(gè)方法之后余赢,需要將數(shù)據(jù)恢復(fù)resetFriction()

setTangenSpeed

碰撞時(shí)芯义,在碰撞面的切線方向,為碰撞剛體添加一個(gè)線性速度speed妻柒,實(shí)現(xiàn)類似傳送帶的效果

碰撞偵聽(tīng)器

剛體碰撞可以發(fā)生多次的step操作扛拨,但是beginContact只會(huì)執(zhí)行一次,endContact也是举塔。

postSolve函數(shù)每次碰撞都會(huì)進(jìn)行模擬绑警,直到分離抵代。在碰撞修復(fù)階段執(zhí)行

preSolve:從兩個(gè)形狀A(yù)ABB接觸開(kāi)始胖眷,到AABB分開(kāi),每次都會(huì)執(zhí)行

參數(shù)

public void preSolve(Contact contact, Manifold oldManifold)
Manifold:用來(lái)記錄上一次物理模擬之前碰撞點(diǎn)信息
public void postSolve(Contact contact, ContactImpulse impulse)
impulse:記錄碰撞產(chǎn)生的沖量
impulse.getNormalImpulses();  //垂直碰撞面
impulse.getTangentImpulses();  //平行碰撞面

游戲碰撞

萬(wàn)有引力

撞擊傷害

撞擊需要一次或者多次藏杖,撞擊的時(shí)候會(huì)有一個(gè)垂直于碰撞邊的沖量芽丹,保存在ContactImpulse中北启,將沖量作為撞擊產(chǎn)生的傷害
并且值只會(huì)在恢復(fù)的時(shí)候產(chǎn)生。PostSolve

單邊

比如向上跳躍沒(méi)有任何影響,下落過(guò)程中可以接住下裸體

使用的位置咕村,是模擬之前场钉,postSolve是每次都進(jìn)行調(diào)用的,所以在beginContact中使用懈涛,但是每次調(diào)用step的時(shí)候逛万,會(huì)設(shè)置回去,所以需要修改源碼批钠,關(guān)閉Contact自動(dòng)開(kāi)啟

碰撞粘貼

碰撞之后會(huì)粘貼在一起宇植,一起運(yùn)動(dòng)

畫(huà)線

 public Game08(){
        setSize(Constant.width,Constant.hight);
        utils = new Utils();
        utils.createBox(50,90,1,1,false);


        BodyDef bodyRequest = new BodyDef();
        bodyRequest.type = BodyDef.BodyType.StaticBody;
        bodyRequest.position.set(0 ,0);//記得米和像素的轉(zhuǎn)換關(guān)系
        //2.Box2D世界工廠更具需求創(chuàng)建createBody()生產(chǎn)剛體
        Body body=Constant.world.createBody(bodyRequest);
        //3.創(chuàng)建敢提形狀需求b2ShapeDef的子類
        //創(chuàng)建矩形剛體形狀需求
        FixtureDef fixtureRequest = new FixtureDef();
        fixtureRequest.density = 3;
        fixtureRequest.friction = 0.3F;
        fixtureRequest.restitution = 0.2F;

        addListener(new ClickListener(){
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                array.clear();
                prePoint.set(x,y);
                return super.touchDown(event, x, y, pointer, button);
            }

            @Override
            public void touchDragged(InputEvent event, float x, float y, int pointer) {
                super.touchDragged(event, x, y, pointer);
                Vector2 curren = new Vector2();
                curren.set(x,y);
                float dst = prePoint.dst(curren);
                if (dst > 1){

                    Vector2 middle = prePoint.add(curren);
                    middle.set(middle.x / 2,middle.y/2);

                    System.out.println(dst);
                    bean b = new bean();
                    b.x=x;
                    b.y=y;
                    b.len = curren.dst(prePoint);
                    b.angle = curren.angle(prePoint);
                    array.add(b);
                    prePoint.set(x,y);
                    fixtureRequest.shape = createDemo(b);
                    body.createFixture(fixtureRequest);
                }
            }

            @Override
            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                super.touchUp(event, x, y, pointer, button);
                //1.創(chuàng)建剛體需求b2BodyDef

//segment.length /2/ 30, 2 / 30, new b2Vec2(segment.centerX/30, segment.centerY/30), segment.rotation

//                for (Vector2 vector2 : array) {
//                    PolygonShape polygonShape = new PolygonShape();
//                    polygonShape.setAsBox(1,1,vector2,4);
//                    fixtureRequest.shape = polygonShape;
//                    body.createFixture(fixtureRequest);
//                }

                for (bean bean : array) {

                }
            }
        });



    }

    public PolygonShape createDemo(bean bean){
        //設(shè)置中心
        //旋轉(zhuǎn)
        PolygonShape polygonShape = new PolygonShape();
//        polygonShape.setAsBox(bean.len,1,new Vector2(bean.x/2,bean.y/2),0);
        polygonShape.setAsBox(bean.len,0.3F,new Vector2(bean.x,bean.y),bean.angle);
        return polygonShape;
    }

    @Override
    public void act(float delta) {
        super.act(delta);
        Constant.world.step(1/60F,40,40);
        Constant.renderer.render(Constant.world,Constant.combined);
    }

    class bean{
        float len;
        float x;
        float y;
        float angle;
    }
}

github地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市埋心,隨后出現(xiàn)的幾起案子当纱,更是在濱河造成了極大的恐慌,老刑警劉巖踩窖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坡氯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡洋腮,警方通過(guò)查閱死者的電腦和手機(jī)箫柳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)啥供,“玉大人悯恍,你說(shuō)我怎么就攤上這事』锖” “怎么了涮毫?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)贷屎。 經(jīng)常有香客問(wèn)我罢防,道長(zhǎng),這世上最難降的妖魔是什么唉侄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任咒吐,我火速辦了婚禮,結(jié)果婚禮上属划,老公的妹妹穿的比我還像新娘恬叹。我一直安慰自己,他們只是感情好同眯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布绽昼。 她就那樣靜靜地躺著,像睡著了一般须蜗。 火紅的嫁衣襯著肌膚如雪硅确。 梳的紋絲不亂的頭發(fā)上肿孵,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音疏魏,去河邊找鬼停做。 笑死,一個(gè)胖子當(dāng)著我的面吹牛大莫,可吹牛的內(nèi)容都是我干的蛉腌。 我是一名探鬼主播只厘,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼烙丛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了羔味?” 一聲冷哼從身側(cè)響起河咽,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赋元,沒(méi)想到半個(gè)月后忘蟹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搁凸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年媚值,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片护糖。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡褥芒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嫡良,到底是詐尸還是另有隱情锰扶,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布寝受,位于F島的核電站坷牛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏羡蛾。R本人自食惡果不足惜漓帅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一锨亏、第九天 我趴在偏房一處隱蔽的房頂上張望痴怨。 院中可真熱鬧,春花似錦器予、人聲如沸浪藻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)爱葵。三九已至施戴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間萌丈,已是汗流浹背赞哗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辆雾,地道東北人肪笋。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像度迂,于是被迫代替她去往敵國(guó)和親藤乙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容