Страницы

Поиск по вопросам

Показаны сообщения с ярлыком физика. Показать все сообщения
Показаны сообщения с ярлыком физика. Показать все сообщения

среда, 4 марта 2020 г.

Написать движок игры на java [закрыт]

#java #аудио #движок #физика #визуализация


        
             
                
                    
                        
                            Закрыт. Данный вопрос необходимо конкретизировать. Ответы
на него в данный момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Переформулируйте вопрос,
чтобы он был сосредоточен только на одной проблеме, отредактировав его.
                        
                        Закрыт 2 года назад.
                                                                                
           
                
        
Допустим захотел я написать движок для игр, зная только Java.
Как это возможно реализовать?


Нужно написать отображение картинки ("звуковоиспроведение" / физику).


Реализация:
На ум приходит только создание библиотеки основанной на аплете, или JavaFX, или JavaEE
(в последнем случае логика и отображение получаются сильно (слишком) взаимосвязаны).



Возможно ли это сделать на чистом JavaSE?
    


Ответы

Ответ 1



Разумеется можно, Майнкрафт подтвердит. См. этот список, берите нужный фреймворк и делайте игры. Либо берете фреймворк с открытым кодом и смотрите как все там реализовано. P.S. Проблема может быть с производительностью, если вы планируете сложную графику, все-таки С/С++/Rast и т.п. быстрее работают как числодробилки.

вторник, 28 января 2020 г.

Отскок мяча от земли

#анимация #алгоритм #javascript #физика


У нас есть холст высотой my и шириной mx, на котором мы рисуем окружность с центром
в точке (x;y) радиуса r, на расстоянии h "от земли". (h = my - y).
Начальная скорость падения окружности вниз равна 0. Будем считать, что масса окружности
прямо пропорциональна радиусу, то есть масса m = r.
Каждый кадр мы рассчитываем координаты окружности и затем прорисовываем ее. Допустим,
в более сложном случае окружность может падать не строго вниз, а под углом и с какой-то
начальной скоростью. 
var obj = {
    x: x,
    y: y,
    radius: radius,
    x_: 0,
    y_: 0,
    speed: Math.sqrt(Math.pow(this.x_, 2) + Math.pow(this.y_, 2)),
    angle: Math.atan2(this.y_, this.x_),
    time: 0,
    h: my - y
};

Пусть x__ и y__ - скорости (проекции скоростей) на оси Ох и Оу соответственно. Пусть
g = 9.8. Каждый шаг я буду изменять координаты шарика
obj.time += 0.0051;
obj.y_ = (g * Math.pow(obj.time, 2))/2;
obj.speed = Math.sqrt(Math.pow(obj.x_, 2) + Math.pow(obj.y_, 2)); // * (-1)
obj.angle = Math.atan2(obj.y_, obj.x_);
obj.y -= obj.speed * Math.sin( obj.angle );

Ввожу вектор, т.к. возможно в будущем сделаю анимацию более сложной.
Вопрос:
Как поступать, когда мяч прилетел на землю? Как перенаправить вектор, чтобы шар отскочил
обратно вверх? Как привязать сопротивление воздуха и массу шарика (чтобы большой мяч
летел быстрее или медленнее)? Как сделать так, чтобы шар в конце концов остановился?
Желательно сделать все как можно ближе к настоящим законам физики.
Куда копать? Пожалуйста, разъясните поподробней этот вопрос.
И что можно почитать на эту тему, чтобы я потом не создавал вопрос о том, как сделать
то же самое с какой-то неправильной фигурой (и т.д.)?    


Ответы

Ответ 1



Для начала почитайте школьную механику. Если мяч несжимаемый, при касании мячом земли vy=-vy; Мгновенно. Если сжимаемый, то при касании появляется сила упругости, которая добавляет ускорение. В простейшем случае Fупр = -kdy,// где dy - смещение по y. Эта сила сначала уменьшит скорость y до 0, потом возвратит к первоначальной величине с обратным знаком. Сопротивление воздуха F = Cx((pV^2)*S)/2 Cx - коэффициент лобового сопротивления. Для шара примерно 0.5 p - плотность среды. Для воздуха - 1.3кг/m^3 S - площадь сечения шара. pi*r*r V - скорость (ПОЛНАЯ, не только по y!!!), относительно воздуха. Не забудте, что эта сила ВСЕГДА направлена против движения. Далее. Если пол шершавый, а касание не единомоментно, мячик будет подкручиваться. Инерция вращающегося шара - что-то типа (2/5)mR^2, то есть в вашем случае (2/5)r^3 Вам пока хватит. Точно хватит. =) P.S. Ах, да. Еще учтите силу архимеда для мячика: p_воздуха*Объем_мяча

Ответ 2



круто весь мир описать наверное и знать при этом всю физику да ещё и математику, но к счастью, а быть может и нет, достаточно создавать иллюзии тех или иных проявлений посредством программинга ибо это и есть симулятор(тобиш иллюзия). и если нет готового движка(которых уже достаточно) ябы это решил функцией падения с эффектом рикошета. тоесть пишем функцию допустим func(int x, int y, int x_destination, int y_destination, int speed) как-то так.. и алгоритм примерно такой: при столкновении с землей вектор на +-180градусов, если движение на 90градусов(перпендикулярно земле) +90градусов, если точка отсчета(старта) больше точки достижения земли по оси Х и У -90градусов, если точка отсчета(старта) меньше точки достижения земли по оси Х и больше по оси У уменьшаем скорость и меняем x_destination, y_destination допустим на отрезок 1/5 от начального при достижении новой точки назначения на +-180градусов и опять к земле и так пока скорость превышает допустим 1 конечно это только набросок и на идеал никоим образом не претендует, только чтобы подсказать направление

Ответ 3



Когда то простую симуляцию отскока мяча (тогда не нужна была оптимизация ) я реализовывал рекурсивно. Каждый отскок будто новый бросок под уголом к горизонту с соответствующим изменением скорости и угла. Базовым случаем являлось условие равенства скорости нулю.

суббота, 4 января 2020 г.

Угол между шарами одинаковой массы после столкновения (упругого)

#физика #2d


Симулирую столкновения шаров в 2D, сделал столкновения о стенки, теперь встал перед
проблемой определения угла между ними после нецентрального удара. Пусть векторы скоростей
шаров соответственно равны v1, и v2. Иза за одинаковой массы, как объясняется в матчасти,
следует, что шары после столкновения, в этом случае просто обменяются скоростями, а
угол между ними всегда будет прямым (как я понял, это угол между направляющими линиями(векторами)
шаров после удара). Мне не понятно почему говорится ВСЕГДА этот угол будет прямым ???
Везде даются картинки и пояснения когда этот угол выходит точно в 90 градусов.
Сомневаясь до отчаяния, нашёл таки пример удара когда угол не прямой. Например здесь
можно построить подобный удар. На рисунках показаны результаты до и после удара.

До удара:



после

Так что же тут происходит ?? Какой тут угол будет всегда прямым ?? Я не вижу тут
никаких прямых углов! Что я не понимаю ?? Поясните пожалуйста поподрбней.
    


Ответы

Ответ 1



В моём понимании задачки подобного рода решаются очень просто. На рисунке вверху два изображения. До удара (слева) и после удара (справа). Исходные вектора скоростей взяты произвольно. Кратко разъясню суть. Шары как-то движутся. Шары ударяются. В момент удара шары деформируются в месте контакта. Энергия деформации на все 100% переходит в кинетическую энергию шаров. Работает закон сохранения импульса и закон сохранения энергии. Что касается импульса - это величина векторная. Поэтому её(как и скорость) можно разложить на две составляющие. Ось ОХ совмещается с линией, которая соединяет центры шаров. Ось OY ⊥ OX. Вертикальная(OY) составляющая импульса на удар влияния не оказывает. Поэтому она остается неизменной. А горизонтальными составляющими импульса шары просто обмениваются. Итого: V2OY = V2*OY V1OY = V1*OY V2OX = V1*OX V1OX = V2*OX А под 90 градусов шары разлетятся в случае если один из шаров неподвижен.

воскресенье, 8 декабря 2019 г.

Алгоритм для гравитационной задачи N тел

#алгоритм #физика #численные_методы #моделирование


К своему стыду очень слаб в численных методах.
Суть задачи в том, чтобы смоделировать движение тел с течением времени под воздействием
силы гравитации друг на друга в количестве >= 3.

В данный момент проект готов. Работает он следующим образом: за атомарную единицу
времени принимается N микросекунд и считается, что в течении этого времени все тела
двигались линейно, линейно же воздействуя друг на друга.

В определенный момент при слишком сильном гравитационном воздействии (высокая масса
+ маленькое расстояние) точность сильно теряется. Можно уменьшать значение атома времени
и таким образом повышать точность, но сильно теряется эффективность (ведь когда тела
имеют низкое воздействие - не обязательно так часто высчитывать расстояние).

Предположительное решение: для каждой пары тел высчитывать своё значение атома времени
в зависимости от силы притяжения. Но у этого подхода есть ряд проблем, которым мне
не удаётся придумать решение.


Например тела А и В имеют такое влияние друг на друга, что их атом времени составляет
5 секунд. При этом атом тел А и С составляет 1 / 1000000 секунды. Во время течения
атома A-B из-за гравитационного маневра тело А начало стремительное движение в сторону
тела В. В этот момент надо менять атом времени между A и В, иначе они пролетят мимо
друг друга. Получается нужна реактивность: при изменении стейта тела необходимо менять
атомы времени всех его связей с другими телами. Я правильно рассуждаю?
Должна ли при регулировке атома времени учитываться скорость сближения объектов?
Ведь два объекта могут быть достаточно далеко друг от друга чтобы не оказывать практически
никакое влияние друг на друга, но двигаться на сближение с огромной скоростью. Атом
времени между ними может оказаться настолько большим, что они сначала пролетят мимо
друг друга, и только потом высчитается их гравитационное влияние.


Сломал голову придумывая алгоритм реализации. Может быть есть у кого-нибудь пример
решения такой задачи: с радостью бы посмотрел код. А может-быть я услышу волшебное
"почитай про метод Вальфгауна-Штауца" и уйду гуглить в правильном направлении.

P.S. Для того чтобы немного поднять интерес прикреплю GUI существующего проекта.
Практической ценности к вопросу не несет никакого:)

https://makarov-andrey.github.io/n-body-problem/
    


Ответы

Ответ 1



Задача трех тел, есть частный случай задачи Коши для обыкновенных дифференциальных уравнений: дан вектор начального состояния и функция который вычисляет производную это вектора по времени (т.н. "функция правой части"). (Гуглить "численное решение задачи Коши".) Выделение подсистемы тесно взаимодействующих объектов практикуется только когда объектов очень много. Для случая трех тел это явно ненужно. Т.е. вычислив характерное время взаимодействия для всех пар тел, берем минимальное из времен и считаем эволюцию всей системы на этом времени. Т.е. шаг по времени один для всей системы. Типичный подход для оценки шага по времени (кроме привлечения физических соображений) такой: из начального состояния делаем шаг длинной t запоминаем результат. из начального состояния делаем два шага длинной t/2 запоминаем результат. если результаты (1) и (2) отличаются меньше чем заданный пользователем параметр "точность на шаге", то принимаем этот шаг если больше то возвращаемся к начальному состоянию и пытаемся сделать шаг меньшего размера. Насколько изменить шаг при пересчете шага, и как выбрать начально приближение для следующего шага - зависит от выбранного метода решения. Для метода Ньютона, который ты реализовал, чаще всего, делят или умножают длину шага на 2. Некоторые методы решения задачи Коши, содержат процедуру управления длинной шага внутри себя. Например метод Розенброка делает сразу два шага подшага методами Руге-Кутты разных порядков и сравнивает результаты. Важное замечание: задача трех - задача с разбеганием траекторий. Т.е. невозможно заранее сказать с какой точностью нужно было посчитать решение для момента t1, чтобы на его основании можно было получить решение для t2 с заданной точностью, пока не посчитаем t2. Т.е. невозможно заранее сказать какая "точность на шаге" нужна для того чтобы получить решение в момент t с заданной точностью. Типичный подход: задачу Коши решают несколько раз, решают несколько раз, увеличивая "точность на шаге", пока результаты решений в конечной точке по времени не будут отличаться друг от друга меньше чем заданная точность интегрального решения. Если цель изучения численных методов, рекомендую взять готовую библиотеку решения задачи Коши. Для C++/C/fortran рекомендую: SUNDIALS https://computation.llnl.gov/projects/sundials Несколько самых простых методов, также реализованы в boost https://www.boost.org/doc/libs/1_64_0/libs/numeric/odeint/doc/html/index.html (она попроще в использовании, но и методы послабее.) Ключевые слова для поиска библиотек для других языков: метод Ньютона, метод Эйлера, метод Розенброка, Stiffl, DASKR. Если цель изучить численные методы и построение солверов ОДУ, рекомендую книжку Э.Хайрер, С.Нёрсет Г.Ваннер "Решение обыкновенных дифференциальных уравнений". (Поскольку система уравнений в задаче трех тел - жесткая, тебе потребуются методы из начала 2-го тома: "Жесткие и дифференциально-алгебраические задачи", но без первого тома его читать бесполезно.)

воскресенье, 1 декабря 2019 г.

Как правильно обрабатывать столкновения движущейся окружности и нескольких линий?

#алгоритм #разработка_игр #физика


Есть работающий алгоритм, обрабатывающий столкновения движушейся окружности и линии
(сегмента линии). Столкновения определяются и разрешаются корректно. Но если окружность
"одновременно" касается 2 линий (т. е. очень быстро касается то одной, то другой) -
возникает нереалистичная ситуация. Причем, корректная для каждой пары "окружность-линия".

Окружность "падает" на две, расположенные под углом линии (изображение 1). В момент
контакта со второй линией она начинает двигаться вниз как и должна. Но в определенный
момент останавливается, не касаясь другой линии (изображение 3).
Похоже, разрешение столкновений в этом кадре происходит следующим образом.
Окружность выталкивается в сторону первой линии и контактирует с ней (4). Потом выталкивается
в сторону второй линии (5), контактирует с ней и вторая линия выталкивает ее так же,
но без контакта с первой (6). Кадр завершается, окружность видна на экране в этой позиции.
Потом эта же ситуация повторяется снова и снова и окружность "зависает".
Как можно исправить? Чтобы окружность скатилась в самый низ и уперлась в обе линии?
Если угол достаточно острый - так и происходит (за счет множественного разрешения столкновений
в одном кадре) (7).


    


Ответы

Ответ 1



Похоже, используется подход - каждый квант времени проверять, не случилось ли чего, и предпринимать какие-то действия (менять скорости и т.п.) . Но он далеко не всегда хорошо работает при расчёте столкновений и прочей кинематики. Вместо этого лучше рассчитывать - какое событие случится в какой момент времени, и выполнять действия для самого раннего события. просчитать траекторию tau = Min(из событий, которые изменят траекторию) while (t < tau) осуществлять движение по траектории отрисовать кадр для времени t t++ отрисовать кадр для времени tau (иначе может получится визуальный ляп) всё сначала Получается, что не нужно обсчитывать столкновения часто. И редко не надо и вообще на регулярные расчеты каждые n микросекунд не полагаемся. Только когда одно столкновение случается, тогда и обсчитывается движение до того, как последующее столкновение случится.

Ответ 2



Мне непонятны направления синих стрелoк на рисунках 2, 4, 5 и 6. Это вектора скорости (или направления движения) круга - тогда они неправильные, или что-то другое? Точка, в которй будет находиться центр круга в момент касания обеих линий, находится как пересечение прямых параллельных линиям 1 и 2 и отстoящих от этих линий на расстояние равное радиусу круга. Причем, все такие точки и, соответственно, соединяющие их отрезки, по которым может двигаться круг, можно найти заранее аналитически.

Ответ 3



Вам надо перейти от обсчёта времени к обсчёту событий. Иными словами, вам надо отказаться от покадровой проверки пересечений окружности с прямыми, и вместо этого определять когда и через какой момент времени произойдёт столкновение, то есть точный момент пересечения непрерывной кривой-траектории с какой-нибудь из прямых. Всё, до этого момента мы можем ничего не делать и просто визуализировать движение окружности по этой траектории, рассчитаной при предыдущем столкновении. Причём визуализацию можно проводить с любой кадровой частотой, так как на физику мы никак при этом не влияем. Когда же очередной кадр «перешагнёт» предсказанное событие, надо определить новую траекторию, получившуюся после этого события, и место следующего столкновения. Может так случиться, что между двумя соседними кадрами произойдёт больше одного столкновения (например, окружность с малой массой влетает в острый угол на большой скорости и начинает очень часто переотражаться). Поэтому определение и обработку событий надо производить в цикле перед собственно визуализацией текущего кадра, пока кадр по хронометражу вновь не начнёт отставать от очередного события — это событие и станет следующим. К слову, в качестве события стоит взять момент пересечения окружностью очередной прямой в направлении снаружи внутрь. Это позволит окружности немного пролететь по инерции сквозь прямую, если она до этого имела большой импульс (мы же не можем согнуть прямую вслед за окружностью, так?). Иными словами, событийная модель позволяет выполнять рассчёты только при смене траектории под влиянием внешних сил. Если столкновений мало, то частота пересчёта траектории будет значительно меньше кадровой частоты (FPS). Если же мы попадаем в плотную группу объектов — частота обработки событий начинает значительно превышать кадровую. При этом скачки FPS не влияют на точность физики. Теперь перейдём к определению траектории после очередного столкновения. Так как при столкновении окружности придаётся ускорение, то траектория будет представлять собой кривую вида p = p0tloc + v0tloc + (a2 / 2)tloc, где: p — точка на траектории в определённый момент времени. Является вектором, то есть парой координат (x и y). p0 — точка столкновения, от которой и пошла текущая траектория. v0, a — скорость и ускорение окружности, получившиеся после его соударения с прямой. Также являются векторами. Так как событие попадает точно на момент соударения с поверхностью, нам не надо непрерывно симулировать выталкивание окружности из этой поверхности. Просто пересчитываем ускорение с учётом направления переотражения и гравитации. И да, стоит также учитывать упругость (т. е. поглощение энергии), чтобы окружность не скакала постоянно по сцене. Скорость при этом берём ту, какая была на момент пересечения точки x0. tloc — относительная временна́я отметка. Считается в секундах виртуального мира, отсчитывается от момента нахождения в точке x0. Однако данный подход хорош только при единомоментных соударениях. Что же делать при скольжении по прямой, когда окружность постоянно стремится уйти под поверхность? Тут, увы, придётся пожертвовать реалистичностью (которая, впрочем, вам и так не важна), чтобы не считать эффекты, связанные с упругими микроотскоками. Также уберём вращение окружности (т. е. как бы сделаем прямые идеально скользкими). Тогда получится, что окружность честно сделает первые несколько отскоков, которые благодаря упругости относительно быстро сойдутся к нулю, а затем просто начнёт скользить. И чтобы у нас действительно было скольжение (без событий пересечения), необходимо перед определением дальнейшей траектории проверять скорость вдоль перпендикуляра к прямой-поверхности. Если скорость не превышает некий малый порог (так как абсолютного нуля мы никогда не достигнем), значит при расчёте траектории направляем ускорение в нижнюю часть сцены вдоль прямой. В противном случае переходим к обработке соударения. При этом стоит дополнительно проверить, не закончится ли эта прямая раньше, чем произойдёт какое-то пересечение. Если да, то в качестве следующего события берём не соударение, а соскок с поверхности, во время которого надо заменить вектор ускорения на ускорение свободного падения. Без этого сфера продолжит скользить по поверхности, которая уже закончилась.

понедельник, 4 февраля 2019 г.

Угол между шарами одинаковой массы после столкновения (упругого)

Симулирую столкновения шаров в 2D, сделал столкновения о стенки, теперь встал перед проблемой определения угла между ними после нецентрального удара. Пусть векторы скоростей шаров соответственно равны v1, и v2. Иза за одинаковой массы, как объясняется в матчасти, следует, что шары после столкновения, в этом случае просто обменяются скоростями, а угол между ними всегда будет прямым (как я понял, это угол между направляющими линиями(векторами) шаров после удара). Мне не понятно почему говорится ВСЕГДА этот угол будет прямым ??? Везде даются картинки и пояснения когда этот угол выходит точно в 90 градусов. Сомневаясь до отчаяния, нашёл таки пример удара когда угол не прямой. Например здесь можно построить подобный удар. На рисунках показаны результаты до и после удара.
До удара:
после
Так что же тут происходит ?? Какой тут угол будет всегда прямым ?? Я не вижу тут никаких прямых углов! Что я не понимаю ?? Поясните пожалуйста поподрбней.


Ответ

В моём понимании задачки подобного рода решаются очень просто. На рисунке вверху два изображения. До удара (слева) и после удара (справа). Исходные вектора скоростей взяты произвольно. Кратко разъясню суть.
Шары как-то движутся. Шары ударяются. В момент удара шары деформируются в месте контакта. Энергия деформации на все 100% переходит в кинетическую энергию шаров.
Работает закон сохранения импульса и закон сохранения энергии. Что касается импульса - это величина векторная. Поэтому её(как и скорость) можно разложить на две составляющие. Ось ОХ совмещается с линией, которая соединяет центры шаров. Ось OY ⊥ OX.
Вертикальная(OY) составляющая импульса на удар влияния не оказывает. Поэтому она остается неизменной. А горизонтальными составляющими импульса шары просто обмениваются. Итого:
V2OY = V2*OY V1OY = V1*OY V2OX = V1*OX V1OX = V2*OX
А под 90 градусов шары разлетятся в случае если один из шаров неподвижен.