Физика взрыва Box2D
| |
Renus | Дата: Воскресенье, 03 Августа 2014, 21:13 | Сообщение # 1 |
почетный гость
Сейчас нет на сайте
| Постепенно прорабатывая макет TDS пришел к вопросу как физически правильно и красиво реализовать взрывы(эффект ударной волны), на данный момент работает упрощенная модель она толкает объекты от точки взрыва, но сила прикладывается к центру масс, следовательно вращения не происходит, ящики летят как то статично и уныло((( Вот екзешник, погоняйте, посмотрите: http://rghost.ru/57250224 ракета правой кнопкой, добавить ящики - пробел.
Вернемся к нашим баранам)) Вот наглядная ситуация:
Сила ударной волны угасает с расстоянием, следовательно давление на объект в точке А будет больше чем в точке Б, а значит объект приобретет вращение по часовой стрелке. Ну и если совсем уже придираться то ударная волна имеет скорость распространения, а значит и к точке А она придет быстрее, из чего опять следует что объект будет вращаться... Вот как то это все и надо грамотно организовать, иначе зачем игре физика если нет взрывов?
У меня есть один вариант решения, его я выложу позже, боюсь что он будет хорошо грузить ЦП... Ваши мнения господа, кто уже с таим сталкивался и как решил, прошу помощи... С уважением.
|
|
| |
OpenGOO | Дата: Воскресенье, 03 Августа 2014, 23:08 | Сообщение # 2 |
почти ветеран
Сейчас нет на сайте
| Цитата Renus ( ) Сила ударной волны угасает с расстоянием, следовательно давление на объект в точке А будет больше чем в точке Б, а значит объект приобретет вращение по часовой стрелке. Ну и если совсем уже придираться то ударная волна имеет скорость распространения, а значит и к точке А она придет быстрее, из чего опять следует что объект будет вращаться... Зачем так сложно, ведь нужно только добиться визуального эффекта.
Мои проекты: - Свободный и открытый клон World Of Goo - TrueEngine2D (2D игровой фреймворк основанный на FreeBASIC)
[GameMaker: Studio v1.4.9999]
|
|
| |
Renus | Дата: Воскресенье, 03 Августа 2014, 23:52 | Сообщение # 3 |
почетный гость
Сейчас нет на сайте
| OpenGOO, скачайте демку постреляйте, посмотрите, там есть визуальный эффект, мне не нравиться как разлетаются ящики...( От этого же зависит динамика игры как никак.
|
|
| |
OpenGOO | Дата: Понедельник, 04 Августа 2014, 13:10 | Сообщение # 4 |
почти ветеран
Сейчас нет на сайте
| Посмотрел. По мне от такого взрыва ящики вообще должны разлетаться на части.
Может трение ящиков об пол сделать выше, а то скользят как будто они стоят на льду.
Забыл что у тебя ящики на самом деле не скользят по полу, а парят в воздухе в состоянии невесомости, значит damping надо подбирать.
Если подумать, то у тебя нет гравитации, нет трения, то зачем тогда физика.
Мои проекты: - Свободный и открытый клон World Of Goo - TrueEngine2D (2D игровой фреймворк основанный на FreeBASIC)
[GameMaker: Studio v1.4.9999]
Сообщение отредактировал OpenGOO - Понедельник, 04 Августа 2014, 18:12 |
|
| |
Renus | Дата: Понедельник, 04 Августа 2014, 22:47 | Сообщение # 5 |
почетный гость
Сейчас нет на сайте
| OpenGOO, Вы не правы))) Трение есть, я его сам написал, потому как Box2D не порадовал меня такой функций, он может только ящики об ящики "тереть" ))) А дампинги этот совсем другое, это как написано в мануале - сопротивление среды, а сила сопротивления среды зависит от скорости движения объекта(как в аэродинамике). Сила трения скольжения же не зависит скорости, она постоянна, как и ее момент при вращении...
Пришлось взяться за этот вопрос самому, физика, двойные интегралы и форумы для ботанов мне помогли Вот как я моделирую трение объектов об плоскость(при учете что правильно соблюден масштаб пикселей к метрам, для реальных сил). В Create: Код //Константы fric = 0.4; //коэффициент трения скольжения g = 9.8 //ускорение свободного падения
d = 0.8; //диаметр эквивалентного круга
В step: Код if(!phy_sleeping) //Только если не спит! { //Сила трения скольжения Ff = fric * phy_mass * g; direction = point_direction(phy_position_x, phy_position_y, phy_position_xprevious, phy_position_yprevious); xFf = lengthdir_x(Ff, direction); yFf = lengthdir_y(Ff, direction); if (phy_speed_ms(phy_speed) > (Ff / phy_mass) / 60) { physics_apply_force(x, y, xFf, yFf); } else { phy_speed_x = 0; phy_speed_y = 0; } //Момент трения вращения s = (pi * power(d, 2))/4; //площадь эквивалентного круга q = (phy_mass * g) / s; //давление на опору(для круга) Mf = (pi/12) * q * fric * power(d, 3); if (abs(phy_angular_velocity) > radtodeg((Mf / phy_inertia) / 60)) { physics_apply_torque(sign(phy_angular_velocity) * -Mf); } else { phy_angular_velocity = 0; } }
Как по мне гораздо реалистичней чем с родными дампингами...
А про коэффициент трения вы правильно заметили, у меня стоит 0.4 а для дерева по бетону обычно берут 0.6, поэтому они так и катаются легко. И кстати я почти сделал предварительный вариант правильного физического взрыва, но пока что он сильно грузит пой проц на ноуте, буду оптимизировать, потом выложу)))
|
|
| |
Raven84 | Дата: Вторник, 05 Августа 2014, 01:09 | Сообщение # 6 |
старожил
Сейчас нет на сайте
| В библиотеке Extreme Physics для GM шёл пример с взрывами. Я однажды брал его на вооружение. Там при взрыве в точке (центре) взрыва создаётся несколько частиц,который с большой скорость разлетаются в разные стороны.Они и воздействовали на предметы,т.к.уних были свои физ.хар-ки:масса и т.д. Я делал игру про взрывы,на основе этого примера.Систему она не грузила,но если на экране одновременно было с десяток взрывов,то fps просядал. И во-вторых из центра эти частицы летели в рандомных направлениях,а не так как у вас на рисунке:чётко через одинаковые расстояния на все 360. Так было реалистичные.Хотя не проблема сделать и ваш вариант.
Добавлено (05.08.2014, 00:58) --------------------------------------------- Вот кстати откопал тему с игрой.Там на 1 и 2 страницах есть пара видео. Игра со взрывами Все записывалось при помощи программы захвата видео,по этому fps не высокий.В реале все плавно шло. Возьми такой способ как вариант.Если ничего другого не придумаешь.
Добавлено (05.08.2014, 01:09) --------------------------------------------- И еще: в моем примере эти частицы видимые и отрисовываются в виде полупрозрачных спрайтов звезд. Можно и это убрать (т.е. сделать их невидимыми),чтобы еще снизить нагрузку.
Super Knight Story (в разработке) Idolzzz - игра доступна в Steam и Play Market Oliver's Adventures in the Fairyland
Сообщение отредактировал Raven84 - Вторник, 05 Августа 2014, 01:09 |
|
| |
Renus | Дата: Понедельник, 11 Августа 2014, 13:43 | Сообщение # 7 |
почетный гость
Сейчас нет на сайте
| Raven84, да я думал о таком варианте, но мне он показался не реалистичным, ваши видео я посмотрел, у вас все симпатично получилось, мне понравилось))) Тем более как я понял это игра на мобильное устройство, там производительность превыше всего...
Я думал-думал, перебирал варианты и таки написал что то годное и более менее оптимизированное(хотя я знаю как еще, но пока лень), как по мне все весьма реалистично(единственное в реале ударная волна угасает кубически от расстояния, а у меня квадратически, так как то симпатичнее). На моем ноуте подтармаживает когда начинаешь все взрывать, падает на 5 фпс, на стационарном думаю все норм будет.
Вот екзешник: http://rghost.ru/57407126 Кому интересно и не влом, посмотрите)
А вот код снаряда: В Create: Код phy_bullet = true; //Режим физической пули P = 50; //Сила взрыва Imin = 0.5 //Минимальный импульс ударной волны, до которого считать
//Параметры траектории direction = point_direction(xstart, ystart, mouse_x, mouse_y); phy_rotation = -1*direction; physics_apply_local_impulse(0, 0, 10, 0);
В столкновении: Код distmax = P / Imin; //Максимальный радиус расчета взрыва
//Перебираем объекты with (dynamic_obj) { //Проверяем на попадние в зону взрыва if rectangle_in_circle(bbox_left, bbox_top, bbox_right, bbox_bottom, other.x, other.y, other.distmax) > 0 { //Перебираем линии ang0 = point_direction(other.x, other.y, x, y); //устанавливаем угол на объект ang = ang0; cw_flag = false; acw_flag = false; while (!cw_flag || !acw_flag) { collision = false; //Определяем точку попадания for(dist = 1; dist <= other.distmax; dist += 2) { xcol = other.x + lengthdir_x(dist, ang); ycol = other.y + lengthdir_y(dist, ang); if collision_point(xcol, ycol, id, true, false) { I = other.P / dist; xI = lengthdir_x(I, ang); yI = lengthdir_y(I, ang); collision = true; physics_apply_impulse(xcol, ycol, xI, yI); //effect_create_above(ef_spark, xcol, ycol, 0, c_yellow); //светим попадание break; } } if(collision) { if(!cw_flag) {ang -= 1;} else {ang += 1;} } else { if(!cw_flag) { cw_flag = true; ang = ang0 + 1; } else {acw_flag = true;} } } } }
effect_create_above(ef_explosion, x, y, 0, c_white); audio_play_sound(snd_boom1, 1, 0); instance_destroy();
|
|
| |
|