Як змусити об'єкт втратити меншу швидкість, оскільки швидкість його збільшується


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

Реституція підстрибує. Що реально.
Martijn Courteaux

30

ті системи, які ви та інші описуєте, не породжуватимуть справжню фізику. основна формула полягає в зменшенні на 0,5 * m * v ^ 2 (кінематична енергія) на постійне значення, коли предмет кудись потрапляє.

тож якщо об’єкт вагою 2 кг потрапить на якийсь блок, якому потрібна енергія 16 Дж, перш ніж він зламається: швидкість руху об'єкта зміниться відповідно до цієї таблиці:

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

7
Це слід прийняти - це правильно, реалістично, легко здійснити і буде обробляти всі випадки об'єкта та блокувати масу та швидкість.
Тессерекс

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

Я думаю, ви можете використовувати просто простий поділ на швидкість. Наприклад: втрачено = 3 000 / міВ швидкість. Коли швидкість становить 300, ви втратите 10, коли - 200, - втратите 15. Вибирати правильні константи.

Якщо ви хочете, ви можете використовувати більш складні формули, наприклад: константа / (константа2 * швидкість ^ 2 + константа3 * швидкість). Знову ж таки - просто вибирайте константи, які вам підійдуть.


це повністю відмінено того, що він просив, і що відбувається в реальній фізиці.
Ali1S232

Я вас не розумію. Що обернено?
zacharmarz

Напевно, я неправильно зрозумів, що ти відповідаєш, моя погана.
Ali1S232
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.