Решение проблемы с обработкой столкновений |
Как-то раз я задался вот таким вопросом: viewtopic.php?f=7&t=1127
На что никто не дал ответа. Что ж... мне это было необходимо, поэтому я всерьез озадачился. Долгое время казалось, что это невозможно, но...
Начнем с маленькой теории. Как С2 обрабатывает столкновения?
И так, допустим у нас есть пуля, размер которой составляет 4х4 пикселя.
Есть стена ширина которой 2 пикселя (т.е. в 2 раза меньше ширины пули).
Есть событие, что если пуля сталкивается со стеной - она останавливается.
При этом скорость пули составляет 100 пикселей в секунду.
Допустим, скорость игры составляет 60 кадров в секунду.
Давайте посчитаем, сколько пикселей пролетит пуля за 1 кадр (за 1 тик)?
100/60 = 1,6
Теперь вспоминаем нашу ситуацию. Ширина стены = 2 пикселя, Ширина пули = 4. Скорость пули за 1 кадр = 1,6. 1,6 меньше, чем 2, а 4 больше чем 2. Значит при частоте кадров в 60 fps, при скорости 100 пикселей/сек наша пуля ГАРАНТИРОВАННО воткнется в стену.
А что если кадров меньше? Намного меньше! 10 fps. Считаем:
100/10 = 10. Т.е. прикиньте, за 1 кадр пуля перемещается на 10 пикселей.
10 больше чем 2 и даже больше чем ширина пули. В этом случае пуля с 90% вероятностью просто перепрыгнет мимо стены и полетит дальше!!! Почему не со 100% вероятностью? Просто это зависит от расстояния между пулей и стеной... если это расстояние равно 10и - то тогда да, врубится.
Почему? Потому, что С2 проверяет все события только кадр за кадром, тик за тиком!
Один кадр - это один шаг в игре. Не шаг персонажа, не шаг пули, а вообще шаг всей игры.
Если в игре мы задали скорость пули в 100 пикселей в секунду - так и будет, каждую секунду она перемещается на 100 пикселей, вот только проверяться условия будут лишь максимум 60 раз в секунду, а не 100 и не 1000. То есть когда придет пора проверить столкновение - пуля уже может переместиться на приличное число пикселей дальше объекта и движок подумает, что столкновения не произошло.
Эти 60 кадров не просто то, что мы видим, это 60 проверок событий в секунду! Поэтому если события тяжелые или их очень много - то процессор не успевает... и на проверку одного тика(кадра) требуется больше времени, что приводит к понижению FPS.
Частота кадров зависит не только от игры, но и от системы в целом. Некоторые могут играть и при этом рендерить видео на 3D-Max и их fps может отличаться от fps игры на свободной от лишних просчетов машине.
Поэтому частота кадров - это штука непредсказуемая. У кого-то пуля всегда врубится в стену, а у кого-то она всегда будет лететь мимо. Что делать в данном случае? Смотрите исходник!
На что никто не дал ответа. Что ж... мне это было необходимо, поэтому я всерьез озадачился. Долгое время казалось, что это невозможно, но...
Начнем с маленькой теории. Как С2 обрабатывает столкновения?
И так, допустим у нас есть пуля, размер которой составляет 4х4 пикселя.
Есть стена ширина которой 2 пикселя (т.е. в 2 раза меньше ширины пули).
Есть событие, что если пуля сталкивается со стеной - она останавливается.
При этом скорость пули составляет 100 пикселей в секунду.
Допустим, скорость игры составляет 60 кадров в секунду.
Давайте посчитаем, сколько пикселей пролетит пуля за 1 кадр (за 1 тик)?
100/60 = 1,6
Теперь вспоминаем нашу ситуацию. Ширина стены = 2 пикселя, Ширина пули = 4. Скорость пули за 1 кадр = 1,6. 1,6 меньше, чем 2, а 4 больше чем 2. Значит при частоте кадров в 60 fps, при скорости 100 пикселей/сек наша пуля ГАРАНТИРОВАННО воткнется в стену.
А что если кадров меньше? Намного меньше! 10 fps. Считаем:
100/10 = 10. Т.е. прикиньте, за 1 кадр пуля перемещается на 10 пикселей.
10 больше чем 2 и даже больше чем ширина пули. В этом случае пуля с 90% вероятностью просто перепрыгнет мимо стены и полетит дальше!!! Почему не со 100% вероятностью? Просто это зависит от расстояния между пулей и стеной... если это расстояние равно 10и - то тогда да, врубится.
Почему? Потому, что С2 проверяет все события только кадр за кадром, тик за тиком!
Один кадр - это один шаг в игре. Не шаг персонажа, не шаг пули, а вообще шаг всей игры.
Если в игре мы задали скорость пули в 100 пикселей в секунду - так и будет, каждую секунду она перемещается на 100 пикселей, вот только проверяться условия будут лишь максимум 60 раз в секунду, а не 100 и не 1000. То есть когда придет пора проверить столкновение - пуля уже может переместиться на приличное число пикселей дальше объекта и движок подумает, что столкновения не произошло.
Эти 60 кадров не просто то, что мы видим, это 60 проверок событий в секунду! Поэтому если события тяжелые или их очень много - то процессор не успевает... и на проверку одного тика(кадра) требуется больше времени, что приводит к понижению FPS.
Частота кадров зависит не только от игры, но и от системы в целом. Некоторые могут играть и при этом рендерить видео на 3D-Max и их fps может отличаться от fps игры на свободной от лишних просчетов машине.
Поэтому частота кадров - это штука непредсказуемая. У кого-то пуля всегда врубится в стену, а у кого-то она всегда будет лететь мимо. Что делать в данном случае? Смотрите исходник!
speed.capx
- (176.59 КБ) Скачиваний: 121
Последний раз редактировалось virusfun 26 янв 2020, 21:18, всего редактировалось 1 раз.
Пути геймдева неисповедимы!
-
- Сообщений: 916
- Я тут с 23 сен 2012
- Откуда: Хабаровск
- Двиг: Construct 2/3
- Лицензия: Personal
- VK: vk.com/virusfun
- Репутация 153 [ ? ]
Что я могу сказать))
Гений!!!
Кстати, не думаю что нужны запредельные скорости. Я обычно редко использовал больше 1000
Гений!!!
Кстати, не думаю что нужны запредельные скорости. Я обычно редко использовал больше 1000
alhimera писал(а):Гений
Это просто. Всё гениальное - просто

alhimera писал(а):Я обычно редко использовал больше 1000
Смотря где. Да даже если скорость 500... при хаотичном ФПС - будут хаотичные результаты. Меня это критически достало, что и сподвигло на изучение вопроса.
Были у меня, да и есть еще и другие варианты, но все они либо имеют кучу событий, либо сильно тормозят систему за счет наличия кучи imagepoint'ов и прочей невидимой шняги. Это к сожалению самое простое и универсальное решение))) Я готов даже символически заплатить тому, кто найдет решение еще проще и лучше!
Пути геймдева неисповедимы!
-
- Сообщений: 916
- Я тут с 23 сен 2012
- Откуда: Хабаровск
- Двиг: Construct 2/3
- Лицензия: Personal
- VK: vk.com/virusfun
- Репутация 153 [ ? ]
Занимательно) Правда у меня проблема иного характера - метеориты в игре летят со скоростью 50-70 пикселей в секунду, моя стенка(астероид) имеет от 400 пикселей в ширину (пролететь мимо такого объекта на столь малой скорости даже при 10фпс я считаю маловероятным), но тем не менее и при 60фпс как минимум 1 из 100 как ни в чем не бывало пролетает насквозь
медленно, но упрямо - насквозь...

mef1sto, интересно....
То есть по идее метеорит должен просто упасть на астероид, но примерно 1 из 100 просто пролетает его насквозь? Не резко и без каких-либо аномалий... Просто продолжает лететь с заданной скоростью, как будто перед ним нет преград?
Всё верно?
То есть по идее метеорит должен просто упасть на астероид, но примерно 1 из 100 просто пролетает его насквозь? Не резко и без каких-либо аномалий... Просто продолжает лететь с заданной скоростью, как будто перед ним нет преград?
Всё верно?
Пути геймдева неисповедимы!
-
- Сообщений: 916
- Я тут с 23 сен 2012
- Откуда: Хабаровск
- Двиг: Construct 2/3
- Лицензия: Personal
- VK: vk.com/virusfun
- Репутация 153 [ ? ]
На СС иной раз тоже проявлялись такие случаи, приходилось применять вместо коллизии оверлап.
virusfun писал(а):Просто продолжает лететь с заданной скоростью, как будто перед ним нет преград?
Именно так... причем это один и тот же метеорит, который при коллизии с астероидом должен был перенестись вверх по координатам...
mef1sto писал(а):причем это один и тот же метеорит
хм.. может быть в этом и причина?
Типа он уже врубился и где-то это отметилось. Обычно такое бывает при использовании Trigger while...
Пути геймдева неисповедимы!
-
- Сообщений: 916
- Я тут с 23 сен 2012
- Откуда: Хабаровск
- Двиг: Construct 2/3
- Лицензия: Personal
- VK: vk.com/virusfun
- Репутация 153 [ ? ]
virusfun писал(а):хм.. может быть в этом и причина?
Типа он уже врубился и где-то это отметилось. Обычно такое бывает при использовании Trigger while...
Хм, ну вот кусок кода от огненного метеорита(самый массовый и за ним косяк наблюдаю чаще):
И свернул то что выше в For Each, ниже то, что не влезло:
Фз конечно, но для меня косяк в коде пока неочевиден...

Если подробней:
Летит метеорит. Коллизирует с землей/персонажем, включается анимация взрыва+отключаются коллизии(чтоб остатком анимации не зацепило персонажа). Анимация доходит до N-кадра, метеорит переносится наверх, устанавливается дефолтная анимация, скорость+угол буллета, включаются коллизии(возможно тут не всегда срабатывает?)
Ну и там страховка: если метеорит пролетает за пределы игрового поля по Y - телепортируется наверх + наверху немного тормозится по скорости, чуток выглядывая - иначе игрок не успеет сориентироваться...
Летит метеорит. Коллизирует с землей/персонажем, включается анимация взрыва+отключаются коллизии(чтоб остатком анимации не зацепило персонажа). Анимация доходит до N-кадра, метеорит переносится наверх, устанавливается дефолтная анимация, скорость+угол буллета, включаются коллизии(возможно тут не всегда срабатывает?)
Ну и там страховка: если метеорит пролетает за пределы игрового поля по Y - телепортируется наверх + наверху немного тормозится по скорости, чуток выглядывая - иначе игрок не успеет сориентироваться...
Сообщений: 23
• Страница 1 из 3 • 1, 2, 3
Вернуться в Другие уроки по Construct 2
Сейчас эту тему просматривают
Зарегистрированные пользователи: нет зарегистрированных пользователей