Jbox2d實踐應(yīng)用

開門見山脸候,一針見血~~先來一張圖片再說!

前言

JBox2D是開源的物理引擎Box2D的Java版本绑蔫,可以直接用于Android运沦。由于JBox2D的圖形渲染使用的是Processing庫,因此在Android平臺上使用JBox2D時配深,圖形渲染工作只能自行開發(fā)茶袒。該引擎能夠根據(jù)開發(fā)人員設(shè)定的參數(shù),如重力凉馆、密度、摩擦系數(shù)和彈性系數(shù)等,自動地進(jìn)行2D剛體物理運動的全方位模擬澜共。

開發(fā)前準(zhǔn)備

首先我們得上github上下載對應(yīng)的jbox2d庫向叉,具體鏈接github.com/jbox2d/jbox2d,我們發(fā)現(xiàn)下載下來的是zip包嗦董,我們可是要的jar包啊母谎。。ok京革,這里我們就先自行解壓再說奇唤。解壓完畢發(fā)現(xiàn)它是一個maven工程,全部是源碼匹摇,我擦嘞咬扇,這可咋辦,不是gradle結(jié)構(gòu)的廊勃。好這里我們就要使用gradle命令把maven工程轉(zhuǎn)成gradle結(jié)構(gòu)懈贺,這里我們需要自己編譯jar包。

方法一:用gradle編譯maven工程

1.先cmd進(jìn)入到剛下載解壓出來的jbox2d文件目錄坡垫,執(zhí)行maven工程轉(zhuǎn)gradle工程命令 gradle init --type pom

2.接著我們進(jìn)去編譯好的工程目錄梭灿,進(jìn)入路徑 jbox2d-master\gradle\wrapper,里面有個gradle-wrapper.properties文件冰悠,在這里堡妒,我們打開并修改自己gradle已經(jīng)緩存有的版本,這里我修改成distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip溉卓,不然是編譯不了的皮迟。

3.ok,接下來我們導(dǎo)入工程的诵。我們需要編譯給我們自己用的jar也是通過這里的jbox2d-library進(jìn)行編譯的万栅,我們在右邊的gradle選項卡中找到對應(yīng)的jbox2d-library/Task/build/assemble,雙擊進(jìn)行編譯。如下圖:


心里喜滋滋的準(zhǔn)備生成jar包....居然提示報錯了西疤,關(guān)鍵是沒有提示報錯的內(nèi)容烦粒。這里十分抓狂,github上down下來的難道沒有維護(hù)和更新嗎代赁?扰她。。這里我們上去看了看最近都有人在更新芭碍,這咋辦....不知道如何下手徒役,很多人都在這里放棄了,不要灰心窖壕,我們來看第四步忧勿。

4.我們用命令行看看報錯內(nèi)容杉女。

這里window使用命令是:gradlew :jbox2d-library(模塊名稱):assemble(任務(wù))

mac命令為:gradle :jbox2d-library(模塊名稱):assemble(任務(wù))

5.好這里可以看到報的什么錯,結(jié)果只是一個簡單的錯誤鸳吸,包名引用錯誤熏挎,自行改一下源碼,重新編譯即可打包出jar晌砾。

方法二:用maven命令直接編譯maven工程

1.首先在本機環(huán)境安裝maven :maven.apache.org/download.cgi#坎拐,并配置環(huán)境

2.在cmd的命令行的輸入mvn install (注:這里是在jbox2d-master目錄下執(zhí)行的命令)

好吧,maven就兩個步驟就可以了.......


前方高能預(yù)警~GO!GO!GO!開始擼碼

我們來先了解一下Jbox2d基本概念:

1. 剛體(rigid body)/物體(body)

一塊十分堅硬的物質(zhì)养匈,它上面的任何兩點之間的距離是完全不變的哼勇。它們就像鉆石那樣的堅硬。

2. 形狀(shape)

一塊嚴(yán)格依附于物體的 2D碰撞幾何結(jié)構(gòu)呕乎,形狀具有摩擦和恢復(fù)的材料性質(zhì)积担。

3.固定裝置(fixture):

fixture綁定一個形狀到物體,增加材料屬性楣嘁,例如密度磅轻,摩擦,恢復(fù)逐虚。

4.約束

一個約束就是消除物體自由度的物理連接聋溜,在2D中,一個物體有3個自由度(水平叭爱,垂直撮躁,旋轉(zhuǎn)),比如秒針买雾,固定后把曼,消除了想x,y的自由度漓穿,只剩下旋轉(zhuǎn)一個自由度

5.世界 world

一個物理世界就是物體嗤军,形狀和約束相互作用的集合。Box2D支持創(chuàng)建多個世界晃危,但這通常是不必要的叙赚。

思路:

1.創(chuàng)建一個JboxImpl類,專門用于管理剛體和世界的創(chuàng)建和邏輯計算

2.自定義一個view僚饭,這里為了方便直接繼承FrameLayout震叮,并且在真實屏幕中將JboxImpl中計算出剛體運動的坐標(biāo)綁定給真實的view(也就是這里的image),根據(jù)重力感應(yīng)不停的回調(diào)繪制鳍鸵。

3.MainActivity中做重力感應(yīng)的注冊苇瓣,回調(diào)的變化傳遞到j(luò)boxView進(jìn)行界面重繪。

JboxView類

將屏幕的寬高傳遞給世界

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

jboxImpl.setWorlSize(w,h);

}

初始化世界與創(chuàng)建剛體

@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

super.onLayout(changed, left, top, right, bottom);

jboxImpl.createWorld();

//子viwe創(chuàng)建tag 設(shè)置body

int childCount = getChildCount();

for (int i =0; i< childCount; i++) {

View view = getChildAt(i);

//body為空時創(chuàng)建剛體

if (!jboxImpl.isBodyView(view) || changed) {

jboxImpl.creatBody(view);

}

}

}

開啟世界與做剛體運動的view繪制

@Override

protected void onDraw(Canvas canvas) {

jboxImpl.startWorld();

int childCount = getChildCount();

for (int i =0; i< childCount; i++) {

View view = getChildAt(i);

if (jboxImpl.isBodyView(view)) {

view.setX(jboxImpl.getViewX(view));

view.setY(jboxImpl.getViewY(view));

view.setRotation(jboxImpl.getViewRotaion(view));

}

}

invalidate();

}

JboxImpl類

創(chuàng)建世界

public void createWorld() {

if (mWorld == null) {

mWorld = new World(new Vec2(0, 10.0f));

//創(chuàng)建左右邊界靜止剛體

updateVertiacalBounds();

//創(chuàng)建上下邊界靜止剛體

updateHorizontalBounds();

}

}

開始世界

public void startWorld(){

if (mWorld != null) {

mWorld.step(dt, mVelocityIterations, mPosiontIterations);

}

}

創(chuàng)建世界的上下邊界偿乖,這里上下邊界是一個靜止的剛體

private void updateHorizontalBounds() {

BodyDef bodyDef = new BodyDef();

//創(chuàng)建靜止剛體

bodyDef.type = BodyType.STATIC;

//定義的形狀

PolygonShape box = new PolygonShape();

float boxWidth = switchPositionToBody(mWidth);

//設(shè)置邊界高度為1

float boxHeight = switchPositionToBody(mRatio);

box.setAsBox(boxWidth, boxHeight); //確定為矩形

FixtureDef fixtureDef = new FixtureDef();

fixtureDef.shape = box;

fixtureDef.density = mDesity;

fixtureDef.friction = 0.8f;//摩擦系數(shù)

fixtureDef.restitution = 0.5f; //補償系數(shù)

bodyDef.position.set(0, -boxHeight);

Body topBody = mWorld.createBody(bodyDef); //創(chuàng)建一個真實的上邊 body

topBody.createFixture(fixtureDef);

bodyDef.position.set(0, switchPositionToBody(mHeight) + boxHeight);

Body bottomBody = mWorld.createBody(bodyDef);//創(chuàng)建一個真實的下邊 body

bottomBody.createFixture(fixtureDef);

}

創(chuàng)建運動剛體

public void creatBody(View view) {

BodyDef bodyDef = new BodyDef();

bodyDef.setType(BodyType.DYNAMIC);

bodyDef.position.set(switchPositionToBody( view.getX() + (view.getWidth() / 2) )

,switchPositionToBody(view.getY() + (view.getHeight() / 2))? );

Shape shape = null;

Boolean isCircle = (Boolean) view.getTag(R.id.dn_view_circle_tag);

if (isCircle != null && isCircle) {

shape = craeteCircleShape( switchPositionToBody(view.getWidth() / 2) );

} else {

Log.i("kaka","createBody veiw tag is not circle!!!");

return;

}

FixtureDef fixtureDef = new FixtureDef();

fixtureDef.setShape(shape);

fixtureDef.friction = 0.8f;//摩擦系數(shù)

fixtureDef.density = mDesity;

fixtureDef.restitution = 0.5f;//補償系數(shù)

Body body = mWorld.createBody(bodyDef);

body.createFixture(fixtureDef);

view.setTag(R.id.dn_view_body_tag, body);

body.setLinearVelocity(new Vec2(mRandom.nextFloat(), mRandom.nextFloat()));

}

MainActivity類

主要實現(xiàn)SensorEventListener接口

@Override

public void onSensorChanged(SensorEvent event) {

if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

float x = event.values[0];

float y = event.values[1] * 2.0f;

jboxView.onSensorChanged(-x, y);

}

}


總結(jié):

其實jbox2d提供的接口運用起來并不是很難击罪,難的物理學(xué)部分計算都在jbox2d中計算好了哲嘲,他會返回給我們坐標(biāo)值,這里的坐標(biāo)值是世界中的坐標(biāo)值外邓。我們需要將它轉(zhuǎn)化成真實屏幕的坐標(biāo)值重繪就ok了撤蚊。一個view對應(yīng)世界中的一個剛體。

代碼地址:github.com/kakaandfigo/Jbox2dProject


好了今天先寫到這里损话。~~~~~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市槽唾,隨后出現(xiàn)的幾起案子丧枪,更是在濱河造成了極大的恐慌,老刑警劉巖庞萍,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拧烦,死亡現(xiàn)場離奇詭異,居然都是意外死亡钝计,警方通過查閱死者的電腦和手機恋博,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來私恬,“玉大人债沮,你說我怎么就攤上這事”久” “怎么了疫衩?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長荣德。 經(jīng)常有香客問我闷煤,道長,這世上最難降的妖魔是什么涮瞻? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任鲤拿,我火速辦了婚禮添瓷,結(jié)果婚禮上踏幻,老公的妹妹穿的比我還像新娘。我一直安慰自己腋妙,他們只是感情好艇抠,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布幕庐。 她就那樣靜靜地躺著,像睡著了一般家淤。 火紅的嫁衣襯著肌膚如雪异剥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天絮重,我揣著相機與錄音冤寿,去河邊找鬼歹苦。 笑死,一個胖子當(dāng)著我的面吹牛督怜,可吹牛的內(nèi)容都是我干的殴瘦。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼号杠,長吁一口氣:“原來是場噩夢啊……” “哼蚪腋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起姨蟋,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤屉凯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后眼溶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悠砚,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年堂飞,在試婚紗的時候發(fā)現(xiàn)自己被綠了灌旧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡绰筛,死狀恐怖枢泰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情别智,我是刑警寧澤宗苍,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站薄榛,受9級特大地震影響讳窟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜敞恋,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一丽啡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧硬猫,春花似錦补箍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至衬横,卻和暖如春裹粤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蜂林。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工遥诉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拇泣,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓矮锈,卻偏偏與公主長得像霉翔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子苞笨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

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