初始化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;
}
}