Комментарии 59
Я правильно понимаю, что в статье описывается поддержка объектов исключительно в форме круга? Мне было бы интересно работать с объектом произвольной формы, заданной, например растром. И с возможностью поворота.
нет, увы, понимаете не совсем правильно.
Я просто рассмотрел пример с кругом, хотя сам объект может быть любой формы (той, что Вы запихнете в object.buffer).
Соответственно после этого немного изменится просчет «нормали», поэтому объект себя будет вести, опять же, более или менее правдоподобно.
Вот так может считаться «нормаль» при форме, отличной от круга:

Я просто рассмотрел пример с кругом, хотя сам объект может быть любой формы (той, что Вы запихнете в object.buffer).
Соответственно после этого немного изменится просчет «нормали», поэтому объект себя будет вести, опять же, более или менее правдоподобно.
Вот так может считаться «нормаль» при форме, отличной от круга:

То как обьект выглядит это одно, то как работает физика — совсем другое.
Для физики нужно использовать физ движки или если так хочется изобретать велосипед — писать свой физический движок.
Но нельзя мешать в одну кучу рисование и физическое поведение.
Для физики нужно использовать физ движки или если так хочется изобретать велосипед — писать свой физический движок.
Но нельзя мешать в одну кучу рисование и физическое поведение.
не спорю, поэтому и пишу:
«более или менее правдоподобно», а не «как надо»
«более или менее правдоподобно», а не «как надо»
А зачем писать топик о том, как НЕнадо делать? Ктото возьмет и сделает, все будет дико тормозить, человек потратит кучу времени, играть будет невозможно…
Вообще-то иногда другого варианта и нет. С другой стороны, такой вариант — не всегда плохой.
Что, если надо обрабатывать столкновения со спрайтом, когда мы не знаем, какая фигура в нём? Или это какая-то хитрая фигура. С чего вы взяли, что решить её математически будет дешевле, чем решить графически?
Согласен, возможно, такой подход не совсем по феншую, но это зависит от условий.
И да, я думаю, что в тех же Worms столкновения просчитываются подобным образом.
Что, если надо обрабатывать столкновения со спрайтом, когда мы не знаем, какая фигура в нём? Или это какая-то хитрая фигура. С чего вы взяли, что решить её математически будет дешевле, чем решить графически?
Согласен, возможно, такой подход не совсем по феншую, но это зависит от условий.
И да, я думаю, что в тех же Worms столкновения просчитываются подобным образом.
другой вариант есть всегда. И дело в том, что «правильный» вариант будет проще для написания.
отделение даных от представления — физика здесь даные, графика — представление. Их нельзя мешать. Будет куча проблем позже.
«решить графически» — графически итак ничего не решается. Зато немеряно процессорного времени теряется на выгребание пикселей из канваса.
как считают в вормсах ни я не вы не знаем, но подозреваю там считают какраз по феншую
отделение даных от представления — физика здесь даные, графика — представление. Их нельзя мешать. Будет куча проблем позже.
«решить графически» — графически итак ничего не решается. Зато немеряно процессорного времени теряется на выгребание пикселей из канваса.
как считают в вормсах ни я не вы не знаем, но подозреваю там считают какраз по феншую
Ну в математике ведь некоторые задачи решаются графическим методом ;)
Я согласен, что отделение логики от представления — это правильно.
Выгребание небольшого количества пикселей из канваса — не трудоёмкая операция.
Я согласен, что отделение логики от представления — это правильно.
Выгребание небольшого количества пикселей из канваса — не трудоёмкая операция.
графический метод решения — например рисуете две прямые и «на глаз» смотрите где они пересекаются.
Подходит для человека, так как даже простейшие арифметические операции человек в уме (и на бумаге) решает с громадным трудом.
Вы действительно думаете, что «графический» метод подходит для компьютера?
Подходит для человека, так как даже простейшие арифметические операции человек в уме (и на бумаге) решает с громадным трудом.
Вы действительно думаете, что «графический» метод подходит для компьютера?
Когда точность — не критична, то вполне может подходить.
???
Для того чтоб найти пересечение аналитически — достаточно функции в 2 строчки.
Для того чтоб найти графически надо нарисовать 2 прямые в памяти, что уже тяжелая операция, пробежать по пикселам и посмотреть закрашены ли пиксели в обоих прямых.
Результат — хуже точность, в 10 раз больше кода, на многие порядки больше нагрузка на проц, используется куча памяти. Профит? Сделать себе больно?
Для того чтоб найти пересечение аналитически — достаточно функции в 2 строчки.
Для того чтоб найти графически надо нарисовать 2 прямые в памяти, что уже тяжелая операция, пробежать по пикселам и посмотреть закрашены ли пиксели в обоих прямых.
Результат — хуже точность, в 10 раз больше кода, на многие порядки больше нагрузка на проц, используется куча памяти. Профит? Сделать себе больно?
Для двух прямых — не подходит) Для сложной фигуры, которая отрисовывается один раз и много раз считывается — подходит)
для сложной фигуры тоже можно считать просто. Но если месье любит писать в 10 раз больше кода, который при этом будет тормозитб, то не мне ему советовать.
Простите, как посчитать пересечение фигуры слева и фигуры справа? Или даже фигуры справа с точкой. У меня с алгоритмами плохо, если расскажете — буду рад услышать:


Разбить на полигоны.
А вы думаете метод указаный в статье будет адекватно просчитывать физику для этих двух фигур? Вы очень ошибаетесь. Тот метод и для материальной точки очень плохо считает, что можно увидеть ниже в коментах.
А вы думаете метод указаный в статье будет адекватно просчитывать физику для этих двух фигур? Вы очень ошибаетесь. Тот метод и для материальной точки очень плохо считает, что можно увидеть ниже в коментах.
Просто как факт. Во флеше для подобных изображений используется именно попиксельное сравнение на базе BitmapData и hitTest ;) Это называется "Pixel-level collision detection".
для точки он вообще не работает… а «баги» всплывают, как я сказал ниже, изза того, что я пытаюсь работать с фигурой как с точкой (для увеличения быстродействия)
На счёт другого варианта. Допустим, пользователь присылает картинку, нарисованную в фотошопе, а мы по ней должны прыгать шариком. Есть ли метод нахождения коллизий кроме графического? ;)
под словами «не надо» подразумевалось не «тормознутость» алгоритмов или еще что-либо, а всего-навсего банальная неточность в определении направления отскока.
Вот пример:
если мы считаем полет ракеты, или еще что-нибудь важное, то не будем производить рассчеты «на глаз», так ведь?
верно и обратное, зачем нам знать точное направление отскока мячика, если необходимо всего лишь показать «видимость» правильного движения? (как в случае с данным примером)
Я показал всего лишь одну из возможных реализаций… использовать ее или нет — дело каждого. Лично меня она пока что устраивает.
Но за замечание спасибо, высказывание «Способ 2. Неправильный» действительно может ввести в заблуждение. Исправлюсь :)
Вот пример:
если мы считаем полет ракеты, или еще что-нибудь важное, то не будем производить рассчеты «на глаз», так ведь?
верно и обратное, зачем нам знать точное направление отскока мячика, если необходимо всего лишь показать «видимость» правильного движения? (как в случае с данным примером)
Я показал всего лишь одну из возможных реализаций… использовать ее или нет — дело каждого. Лично меня она пока что устраивает.
Но за замечание спасибо, высказывание «Способ 2. Неправильный» действительно может ввести в заблуждение. Исправлюсь :)
Это круто, жду от автора еще чего нить про физику в канвасе и все такое.
“угол падения равен углу отражения”
Обычно говорят «угол отражения равен углу падения», ибо иначе немного нелогично.
Перезалейте фото с дропбокса пожалуйста.
У меня от стенок отскакивает замечательно, а вот от «горки» с глюками и некрасиво, проваливаясь до центра в препятствие…
Особенно скользящие столкновения
да, я знаю о подобной проблеме.
попробую доходчиво объяснить, в чем ее суть:
после определения касания, шарик необходимо «выдвинуть» за пределы ландшафта.
Сейчас я это делаю так:
while(imgData[3] != 0) {
toX = (toX — stepX);
toY = (toY — stepY);
imgData = where.ctx.getImageData(toX,toY, 1,1).data;
}
то есть выгоняю только центр объекта за пределы ландшафта. Это неправильно. Как избавиться? есть 2 варианта:
1) более точно считать касание (а не по 1 пикселю как сейчас).
2) сильнее «выдвигать» объект из препятствия.
при первом способе мы теряем быстродействие. При втором шарик будет «дергаться» при каждом отскоке.
Оперируя этими двумя способами можно добиться желаемого эффекта. У каждого этот «желаемый эффект» будет своим.
попробую доходчиво объяснить, в чем ее суть:
после определения касания, шарик необходимо «выдвинуть» за пределы ландшафта.
Сейчас я это делаю так:
while(imgData[3] != 0) {
toX = (toX — stepX);
toY = (toY — stepY);
imgData = where.ctx.getImageData(toX,toY, 1,1).data;
}
то есть выгоняю только центр объекта за пределы ландшафта. Это неправильно. Как избавиться? есть 2 варианта:
1) более точно считать касание (а не по 1 пикселю как сейчас).
2) сильнее «выдвигать» объект из препятствия.
при первом способе мы теряем быстродействие. При втором шарик будет «дергаться» при каждом отскоке.
Оперируя этими двумя способами можно добиться желаемого эффекта. У каждого этот «желаемый эффект» будет своим.
Есть еще третий (почти правильный), но более простой для реализации способ.

Найти точки пересечения контуров препятствия и объекта (A и B).
Найти серединку этого отрезка (С).
Провести перпендикуляр из этой точки и найти точку пересечения этого перпендикуляра с контуром препятствия (D).
Луч DN и будет той самой нормалью.

Найти точки пересечения контуров препятствия и объекта (A и B).
Найти серединку этого отрезка (С).
Провести перпендикуляр из этой точки и найти точку пересечения этого перпендикуляра с контуром препятствия (D).
Луч DN и будет той самой нормалью.
спасибо, первый раз слышу о подобном способе.
На картинке это все круто, а в коде как будет выглядеть?
довольно красиво:
1) находим две точки (элементарно?)
2) по двум точкам прямую (девятый, если не ошибаюсь, класс)
3) эта прямая — и есть перпендикуляр к нормали. А дальше как у меня.
1) находим две точки (элементарно?)
2) по двум точкам прямую (девятый, если не ошибаюсь, класс)
3) эта прямая — и есть перпендикуляр к нормали. А дальше как у меня.
Совершенно верно. Самое сложное — это как раз найти те точки A, B и D
Точка D — это точка «касания». ее тоже нужно найти, и уже к этой точке строить «углы» падения и отражения
A&B ищутся довольно просто. С точкой «касания» дела обстоят сложнее. Да и нужна ли она нам? нормаль можно (не совсем точно) найти, используя только A&B, или я не прав?
Дело в том что сами A и B уже вносят искажение.
Если еще и D проигнорировать, то точность еще больше пострадает.
Кстати, D найти проще чем А и B.
Если еще и D проигнорировать, то точность еще больше пострадает.
Кстати, D найти проще чем А и B.
«Кстати, D найти проще чем А и B.»
не сильно затруднит описать нахождение? :)
не сильно затруднит описать нахождение? :)
Вообще, контуры как самих объектов, так и препятствий лучше сделать векторными, описав линии контуров отрезками и дугами окружностей. Другими словами нарисовать все (обвести все контуры) «циркулем-и-линейкой». Это позволит полностью отказаться от «попиксельной физики» и любую траекторию движения рассчитать чисто аналитически (без прорисовки на холсте). Точки пересечения двух линий, двух окружностей и одной линии с окружностью можно найти очень просто и главное — быстро, а расчет будет более точным!
И, кстати, сами контуры можно не очень точно задавать — лишь бы получилась непрерывная линия (по-возможности). Начать «обводку» лучше с «округлостей», потом ответить на окружностях (и на остальных кусочках контура) точки, которые потом соединить.
И, кстати, сами контуры можно не очень точно задавать — лишь бы получилась непрерывная линия (по-возможности). Начать «обводку» лучше с «округлостей», потом ответить на окружностях (и на остальных кусочках контура) точки, которые потом соединить.
просто мне интересен способ определения (и обработки) взаимодействий предметов любой формы (в том числе меняющейся) с препятствиями любой формы (в т.ч. меняющейся). Я считаю, что постоянно пересчитывать уравнения для изменившихся форм довольно долгое занятие… или я не прав?
Зачем мне это нужно? хочу сделать игрушку, похожую на worms, но немного доработанную (например поиграть на самостоятельно нарисованной карте).
Зачем мне это нужно? хочу сделать игрушку, похожую на worms, но немного доработанную (например поиграть на самостоятельно нарисованной карте).
В игре Worms контур ландшафта меняется либо прямыми линиями, либо окружностями (воронки от взрывов).
Сами объекты меняются совсем даже не произвольным образом: заранее готовятся несколько изображений одного объекта, которые чередуются в заданной последовательности.
Никто не мешает одновременно с рисованием самих объектов одновременно векторизовать их контуры.
Сами объекты меняются совсем даже не произвольным образом: заранее готовятся несколько изображений одного объекта, которые чередуются в заданной последовательности.
Никто не мешает одновременно с рисованием самих объектов одновременно векторизовать их контуры.
«векторизовать их контуры» не знаю как это сделать… что посоветуете почитать на эту тему?
Можно и «вручную» мышкой «потыкаться» в картинку в том же самом «пейнте», и записать в «блокноте» пары координат «х и у» для каждой точки в контуре.
То есть в итоге должен получиться один (или несколько) полигонов (многоугольники).
что-то вроде того:
Причем из этого контура можно выделить прямолинейные и скругленные участки.
Прямолинейные участки задаются двумя точками, а дуги окружностей — тремя.
То есть в итоге должен получиться один (или несколько) полигонов (многоугольники).
что-то вроде того:
10,15
20,12
25,35
25,48
8,50
10,15
Причем из этого контура можно выделить прямолинейные и скругленные участки.
Прямолинейные участки задаются двумя точками, а дуги окружностей — тремя.
Почему после каждого перемещения нужно определять касания или пересечения с объектами? Почему нельзя, зная параметры движения, вычислить точку соприкосновения заранее?
Фон может поменяться в течении движения?
во первых да, фон не обязательно может быть статическим.
а во вторых для проверки я беру всего 1 пиксель. По-моему это не сильно затратно.
А проссчитывать я пытался, только есть проблема — округления. То ли у меня руки кривые, то ли на самом деле они так сильно влияют, но при рассчете «заранее» возникали своеобразные проблемы…
а во вторых для проверки я беру всего 1 пиксель. По-моему это не сильно затратно.
А проссчитывать я пытался, только есть проблема — округления. То ли у меня руки кривые, то ли на самом деле они так сильно влияют, но при рассчете «заранее» возникали своеобразные проблемы…
Бинго это и есть правильный способ. Если делать что-то другое то рано или поздно увеличение скорости приведет к проскакиванию объектов друг через друга. Почему автор статьи его не выбрал — не знаю.
отличная программа.
было бы здорово, если бы добавили туда
1. гравитацию, то есть затухания полёта в направлении «вверх»
2. коэффициент упругости, то есть замедление скорости при каждом соударении.
хочется поймать случаи, когда круг «скатывается» по наклонной.
в этом случае должен работать уже не коэффициент упругости, а коэффициент силы трения, когда шарик не «отрывается» от поверхности и исчерпал энергию для отскока. силы для качения должна добавлять гравитация.
было бы здорово, если бы добавили туда
1. гравитацию, то есть затухания полёта в направлении «вверх»
2. коэффициент упругости, то есть замедление скорости при каждом соударении.
хочется поймать случаи, когда круг «скатывается» по наклонной.
в этом случае должен работать уже не коэффициент упругости, а коэффициент силы трения, когда шарик не «отрывается» от поверхности и исчерпал энергию для отскока. силы для качения должна добавлять гравитация.
если я не ошибаюсь, то для этой задачи проще использовать готовые движки, например, Box2D
Рабочий пример.
Рабочий пример.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Обработка 2D столкновений с использованием LibCanvas