天天看點

libgdx, mouse 關節

滑鼠與body的互動就靠這個mouse 關節了。

在使用中:主要分成3步:

步1:mousedown : 這個時期,調用world->queryaabb。它有一個回調接口,并根據滑鼠指針指定一個aabb的極小區域。

有3個細節需注意:

細節1:滑鼠的xy值是螢幕坐标系統的,要轉換成stage坐标系統(stage->screentostagecoordinates),然後再轉成box2d的機關xy值;

細節2:aabb極小區域是多小?當然是越小越好(比如:0.001f ,機關是米的,或者1個像素的差)x-0.001f, y-0.001f, x+0.001f,y+0.001f。這樣就形成了一個極小區域。但實際測試時發現,回調函數被調用時,滑鼠距離我們的目标body還有3-5個像素,這可能會造成視覺上的困惑。為解決這個問題,我一般在回調函數中再對其進行“(滑鼠)點的測試”,即fixture->testpoint(x,y)方法。用它來實作測試我們的fixture是否被擊中,以嚴格的擊中測試來定位fixture擊中與否,以此來建立滑鼠關節會更符合視覺習慣。

細節3:bodyb是操作目标,bodya一般是靜态body;我第一次使用時将這兩個搞混了,結果發生崩潰異常。(參見後面的圖1)

步2:mousedrag:在這個時間,隻是簡單設定目标位置就行。注意坐标的轉換與機關的轉換。

步3:mouseup:這個時間是銷毀滑鼠關節。一般要注意将關節對象的引用置空(=null)。

最後還要根據執行個體的body屬性,特别調節如下參數,以保證mouse關節行為不是那麼怪異!

mousejointdef.dampingratio = 1;

mousejointdef.frequencyhz = 60; 、、調大些,會使用命中時顯的更靈敏。

mousejointdef.maxforce = 5000;、、力要足夠大,否則可能因為幹不過重力而出現不期望的效果,比如“向下掉”。

mousejointdef.collideconnected = true;、、一般都設定為true,連接配接的body也要有碰撞,預設值為false,如果為false,它可能會“向下掉,且掉到地闆下面去了”。

下圖是圖1:

libgdx, mouse 關節

代碼參考:

   @override

    public boolean reportfixture(fixture fixture) {

        // 如果不是這個類型,直接轉換會抛異常

//        kwletter kwletter = (kwletter)fixture.getbody().getuserdata();

        // 修改成如下代碼

        object object = fixture.getbody().getuserdata();

        if (object instanceof kwletter) {

            kwletter kwletter = (kwletter)object;

            if (null == m_mousejoint && kwletter.hit(m_mousex2d, m_mousey2d)) {

                gdx.app.debug("reportfixture", "kwletter="+kwletter);

                mousejointdef mousejointdef = new mousejointdef();

//                mousejointdef.dampingratio = 1;

//                mousejointdef.frequencyhz = 1;

//                mousejointdef.maxforce = 5;

                mousejointdef.target.set(new vector2(m_mousex2d, m_mousey2d));

                mousejointdef.bodya = m_kwground.getbody();

                mousejointdef.bodyb = kwletter.getbody();//目标

                m_mousejoint = (mousejoint)m_world.createjoint(mousejointdef);

            }

        }

        return false;

    }

    public boolean hit(float x2d, float y2d)

    {

        return m_fixture.testpoint(x2d, y2d);