Как заставить объект терять меньше скорости при увеличении скорости

11

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

Мой объект летит со скоростью, Xи мой объект может столкнуться с камнями. Когда он сталкивается с камнем, мне нужен мой объект, чтобы разбить камень и продолжить, но с меньшей скоростью. Легко написать код и написать что-то вроде:, myVelocity -= 10;но моя главная проблема в том, что я хочу, чтобы он терял скорость меньше, чем выше начальная скорость.

Например: если скорость равна 300, я хочу, чтобы она потеряла 10, а если она была 200, я хочу, чтобы она потеряла 20.

Можно ли это сделать с помощью какой-то формулы?

Афра
источник
1
Как насчет чего-то простого log(myVelocity + 1) * N?
Джонатан Коннелл

Ответы:

6

Я бы инвертировал скорость и умножил бы на что-нибудь, что тебе нравится:

float velocity = 300.0f;
float collisionEffect = 3000.0f / velocity;
if (collisionEffect > velocity)
{
    // Choose which one you like: with or without restitution

    // No restitution
    collisionEffect = velocity;

    // Restitution
    collisionEffect = velocity + (collisionEffect - velocity) * 0.3f;
}
velocity -= collisionEffect;

Этот пример дает следующие эффекты:

400 loses 7.5
300 loses 10
200 loses 15
100 loses 30
 50 loses 50  // Using no restitution
 50 loses 53  // Using restitution
 20 loses 20  // Using no restitution
 20 loses 59  // Using restitution
Мартейн Курто
источник
Что такое "реституция"?
jprete
Реституция подпрыгивает. Что реально.
Мартин Курто
30

та система, которую вы и другие описываете, не создаст физически выглядящую физику. основная формула состоит в уменьшении 0,5 * m * v ^ 2 (кинематическая энергия) на постоянное значение всякий раз, когда объект попадает куда-либо.

поэтому, если объект весом 2 кг попадает в какой-то блок, которому требуется 16j энергии, прежде чем он сломается: скорость движения объекта изменится в соответствии с этой таблицей:

4  m/s -> the block will not break
5  m/s -> 3   m/s
6  m/s -> 4.4 m/s
7  m/s -> 5.7 m/s
8  m/s -> 6.9 m/s
9  m/s -> 8   m/s
10 m/s -> 9.1 m/s
Ali1S232
источник
7
Это должно быть принято - это правильно, реалистично, легко реализуемо и будет обрабатывать все случаи объекта и массы блока и скорости.
Tesserex
3
Если у вас нет определенного эффекта «физики мультфильмов», которого вы надеетесь достичь, переход на более реалистичную систему почти всегда является хорошей идеей; Есть несколько лучших способов гарантировать, что вы не получите потенциально передовые случаи.
Стивен Стадницки
1
Этот ответ был хорош, я знаю. Но моя игра разворачивается в мире мультфильмов, и она не должна быть реалистичной. Я должен был быть более конкретным, когда задавал вопрос.
Афра
1
это общественный проект, люди были здесь, чтобы ответить на вопрос, и на заданный вопрос это лучший ответ. Тот факт, что вы предпочитаете хакерское решение для вашего конкретного случая, не означает, что этот ответ не лучший. Выбрав хакерский ответ в качестве решения, когда кто-то ищет на сайте ответ на этот вопрос, он будет считать, что нереалистичный ответ - лучший.
Ричард Фабиан
1
@Richard Другое решение не является хакерским просто потому, что в нем не используется реалистичная физика. Тетрис хакерский, потому что блоки не падают плавно? Если люди считают, что принятый ответ является «лучшим», вместо того, чтобы предполагать, что ответ удовлетворяет спрашивающего, то это их вина. Все ответы и голоса все еще очевидны.
CiscoIPPhone
2

Вы на самом деле не дали достаточно информации, чтобы сказать, какой диапазон вам нужен, то есть ли он ограничен, хотите ли вы геометрическую прогрессию и т. Д.

Первое, что вы хотите сделать, это получить число, пропорциональное величине скорости, которую вы хотите потерять (она не должна быть такой же, но она должна уменьшаться с увеличением скорости, чтобы сделать ее пропорциональной вашей потере). Стандартный способ сделать это - взять ответное :

temp = 1 / currentVelocity;

Теперь для 100 у вас будет 0,01, для 200 - 0,005, для 300 - 0,0033 и так далее.

Теперь вам просто нужно настроить это число на то, что вы действительно хотите, умножив его. Так

k = 3000;
newVelocity = temp * k;

даст вам 20 за 300, но это даст вам 15 за 200, а не 10. Это может быть хорошо для вас, в этом случае вам не нужно читать дальше. Вы можете настроить k так, как вам нравится, но вы не можете получать числа так, как вам нравится, если вы не сделаете немного больше, например, реализуете геометрическую прогрессию или измените базу для увеличения. Я не буду вдаваться в геометрические прогрессии здесь, но если вы хотите изменить базу, вы делаете это следующим образом:

base = 100;
temp = 1 / (currentVelocity - base);
if (temp < 0) temp = 0; //adjust temp so never less than zero, cannot gain force!

k = 2000;
velocityLoss= temp * k;
if (velocityLoss > currentVelocity) //(1) or make currentVelocity an unsigned int
    velocityLoss = currentVelocity; //(2)

Это предоставит вам диапазон, который вы изначально запрашивали в своем вопросе, 300 -> потеря 10, 200 -> потеря 20. FYI 100 -> потеря 40, и 50 -> потеря 80 (!), Что означает, что вы нужно ограничить вычитание - это то, что я сделал в строках (1) и (2).

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

инженер
источник
0

Я думаю, вы можете использовать просто деление по скорости. Например: lost = 3 000 / myVelocity. Когда скорость равна 300, вы потеряете 10, а если 200, то потеряете 15. Выбор за вами правильных констант зависит от вас.

Если вы хотите, вы можете использовать более сложную формулу, например: постоянная / (постоянная2 * скорость ^ 2 + постоянная3 * скорость). Опять же - просто выберите константы, которые вам подойдут.

zacharmarz
источник
это полностью противоположно тому, что он просил, и что происходит в реальной физике.
Ali1S232
Я вас не понимаю Что восстанавливается?
zacharmarz
Наверное, я неправильно понял ваш ответ, мой плохой.
Ali1S232