Как проверить, что тело почти перестало двигаться в libgdx + box2d

Итак, у меня есть тело игрока + приспособление и т. д., по сути, это шар, который подпрыгивает.

Я хочу определить, когда он "в значительной степени" закончил движение.

На данный момент я делаю это:

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

Это в основном работает, проблема в том, что когда игрок что-то нажимает, есть доля секунды, где его скорость равна 0, так что это возвращает true. Что я действительно хотел, так это просто вернуть true, когда оно в основном закончено. Предпочтительно в пределах диапазона, который я могу установить на то, что мне нравится, когда я изменяю физику моего игрового мира.

Я не могу проверить, спит ли он или нет, так как он приходит слишком поздно, он не спит, пока не перестанет действовать на него силой, мне нужно только раньше.

Я мог бы просто сохранить, как долго он был остановлен /количество остановленных шагов, но я надеялся, что будет хороший уже существующий метод, который я пропустил.

Есть идеи?

4 голоса | спросил Tom Manterfield 25 FebruaryEurope/MoscowbTue, 25 Feb 2014 01:59:56 +0400000000amTue, 25 Feb 2014 01:59:56 +040014 2014, 01:59:56

3 ответа


0

Вы можете отслеживать недавнее движение и обновлять его, смешивая немного текущей скорости с каждым шагом:

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

Для начала вам нужно установить для recentSpeed подходящее высокое значение, иначе оно может быть ниже порогового значения в первый раз шаг.

ответил iforce2d 25 FebruaryEurope/MoscowbTue, 25 Feb 2014 05:56:49 +0400000000amTue, 25 Feb 2014 05:56:49 +040014 2014, 05:56:49
0

Видя, как вы определили, что ваши ложные срабатывания вызваны контактом тела с другим, почему бы не добавить пару строк в метод beginContact вашего ContactListener, сохраняя текущую скорость тела в его пользовательских данных? Затем вы можете проверить эту скорость в вашем методе 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.

ответил Emil Fors 27 FebruaryEurope/MoscowbThu, 27 Feb 2014 18:23:40 +0400000000pmThu, 27 Feb 2014 18:23:40 +040014 2014, 18:23:40
0

В конце я просто передал дельту из каждого вызова рендеринга в метод 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 - это просто свойство класса, которое начинается с нуля. Это возвращает true для начала игры (до того, как пользователь сделал ход), но в моем приложении это абсолютно нормально. Кроме того, это правда, что это прекратилось в этих обстоятельствах.

Я все еще хотел бы увидеть способ сделать это без сохранения дополнительного дерьма, так как я предполагаю, что box2d должен где-то иметь эту информацию, чтобы выяснить, не действует ли на тело с нулевой скоростью сила или если просто меняет направление после удара.

ответил Tom Manterfield 27 FebruaryEurope/MoscowbThu, 27 Feb 2014 16:53:22 +0400000000pmThu, 27 Feb 2014 16:53:22 +040014 2014, 16:53:22

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132