2014-02-24 28 views
4

因此,我有一個球員身體+夾具等,它本質上是一個球,反彈周圍。如何檢查身體是否幾乎停止移動在libgdx + box2d

我想檢測它何時「非常」完成移動。

目前,我這樣做:

public Boolean isStopped() { 
    return body.getLinearVelocity().x <= 0.3f && body.getLinearVelocity().y <= 0.3f; 
} 

這主要工作,是當玩家碰到什麼問題,有一個瞬間,其中它的速度是0,所以返回true。我真正想要的是在基本完成時才返回true。最好在我可以設置的任何範圍內調整我的遊戲世界的物理。

我不能用它來檢查它是否在睡覺,因爲那太遲了,直到它停止了部隊的作用之後纔會睡覺,我之前需要。

我可以只存儲停止的時間/停止的步數,但我希望能有一個很好的預先存在的方法,我錯過了。

任何想法?

回答

4

你可以保持最近的運動軌跡和當前速度中的每一步中帶點混合更新:

float speedNow = body.getLinearVelocity().len(); 
recentSpeed = 0.1 * speedNow + 0.9 * recentSpeed; 
if (recentSpeed < someThreshold) 
    ... do something ... 

您需要設置recentSpeed到一個適當的高值,首先,否則它可能低於第一個時間段的閾值。

+0

是的,我想到了這些線之前。我確實在尋找一些已經在身體課程中出現的東西,我錯過了文檔中的錯誤或誤解。如果我要走這樣的路線,我會(現在已經)只是將時間增量作爲參數加入,以檢測它停止了多久。這是有效的,但它只是覺得應該有更好的東西。 –

+0

嘿,儘管我最終使用了三角洲方法,但我已經接受了您的答案,因爲它至少向我展示了另一種選擇。從看你的代碼,我認爲我可以改變我的isMoving支票_Math.abs(body.getLinearVelocity()。len())> = 0.25f_? Math.abs對.len()甚至是必需的嗎? 非常感謝您的答覆! –

+0

哦,我剛剛意識到我在哪裏知道iforce2d!我使用你的RUBE編輯器來創建我的關卡。加上rubeloader讓我的生活變得更加輕鬆。非常值得的錢。 –

0

最後,我只是將每個呈現調用的delta值傳遞給isStopped()方法。

public Boolean isStopped(float delta) { 
    boolean isMoving = (
      Math.abs(body.getLinearVelocity().x) >= 0.25f || Math.abs(body.getLinearVelocity().y) >= 0.25f); 
    if(isMoving) { 
     timeStopped = 0f; 
     return false; 
    } else { 
     timeStopped += delta; 
     return timeStopped >= 0.3f; 
    } 
} 

timeStopped只是一個以零開始的類屬性。這在遊戲開始時(在用戶做出動作之前)是真的,但在我的應用程序中是絕對正確的。除此之外,說在這種情況下停止是正確的。

我仍然喜歡看到一種方法來做到這一點,而不會存儲額外的垃圾,因爲我猜測box2d必須有這個信息的某處,以便弄清楚零速度的物體是否沒有力量作用於或如果它只是在衝擊後改變方向。

1

看到您如何確定您的誤報是由身體與另一個人接觸導致的,爲什麼不在您的ContactListener的beginContact方法中添加幾行,將身體的當前速度存儲在其用戶數據中?然後,您可以在isStopped方法中檢查速度。如果存儲速度並且當前速度不大,這意味着身體正在反彈的過程中:忽略。如果存儲的速度和當前的速度更大,球已經反彈並正在朝着一個新的方向前進:清除存儲的速度。如果沒有存儲的速度並且當前的速度低於您的閾值,您已經檢測到所尋找的情況。

在你ContactListener:

public void beginContact(Contact contact) { 
    Body a = contact.getFixtureA().getBody(); 
    Body b = contact.getFixtureB().getBody(); 

    if (a == mBall) { 
     a.setUserData(a.getLinearVelocity().len()); 
    } else if (b == mBall) { 
     b.setUserData(b.getLinearVelocity().len()); 
    } 
} 

並在您檢查isStopped:

public Boolean isStopped() { 
    float storedSpd = (Float) body.getUserData(); 
    float currentSpd = body.getLinearVelocity().len(); 

    if ((storedSpd > Float.MIN_VALUE) && (currentSpd > storedSpd)) { 
     body.setUserData(Float.MIN_VALUE); 
     return false; 
    } else { 
     return (currentSpd < THRESHOLD); 
    } 
} 

這是未經測試,但你的想法。另外,請記得初始設置用戶數據爲Float.MIN_VALUE。