Actionscript 3-пиксельное идеальное столкновение. Как? (учебные цели)

Я знаю, что есть люди, создающие для этого классы (например, http://coreyoneil.com/portfolio/index.php?project=5). Но я хочу научиться делать это сам, чтобы я мог создавать все, что мне нужно, так, как мне нужно.

Я читал о BitMap и BitMapData. Я должен иметь возможность .draw MovieClips на BitMap, чтобы затем циклически перебирать пиксели в поисках коллизий. Тем не менее, это странно и запутанно иметь дело со смещениями. И похоже, что MyBitMap.rect всегда имеет x = 0 и y = 0... и я не могу найти исходное положение вещей...

Я думаю сначала сделать hitTestObject, а затем, если это было положительно, я бы исследовал пересечение между прямоугольниками мувиклипов для столкновений пикселей. Но есть и другая проблема (вращение мувиклипов)...

... Мне нужно немного просветления, как это сделать. Пожалуйста, любая помощь будет оценена.


person jmacedo    schedule 07.07.2010    source источник


Ответы (4)


Если вы используете объекты BitmapData с прозрачностью, вы можете использовать BitmapData.hitTest(firstPoint:Point, firstAlphaThreshold:uint, secondObject:Object, secondBitmapDataPoint:Point = null, secondAlphaThreshold:uint = 1):Boolean.

Вам придется перейти от глобальных координат к локальным координатам BitmapData, что потребует немного математики, если он будет повернут. Этого легко добиться (посмотрите аффинное преобразование для получения дополнительной информации в вики):

var coordTransform:Matrix = new Matrix();

coordTransform.rotate(rotationRadians);
coordTransform.translate(x, y);

coordTransform.transformPoint(/* your point */);
person Mahir    schedule 07.07.2010
comment
Я не хочу просто проверять, сталкиваются ли они. Я хочу научиться делать это вручную, потому что мне нужно будет найти такую ​​информацию, как угол столкновения, который, насколько мне известно, не возвращается упомянутой вами функцией. но .. в вашем коде вы говорите об изменении местоположения всех пикселей в растровом изображении с помощью матрицы вращения? это оно? - person jmacedo; 07.07.2010
comment
Угол столкновения? Не могли бы вы уточнить (то есть нормаль к касательной места, где они столкнулись). Способ сделать это вручную — перебрать каждый пиксель одного растрового изображения и посмотреть, не касается ли он пикселя другого растрового изображения. Затем, если какой-либо пиксель касается другого пикселя другого, растровые изображения где-то перекрываются. Теперь вы должны использовать некоторую эвристику, чтобы ограничить тестируемые пиксели, потому что этот метод крайне неэффективен. - person Mahir; 07.07.2010
comment
Преобразование координат было дано в случае, если ваше растровое изображение повернуто. Пример: ваш bmd представляет собой квадрат размером 20x20 пикселей, левый верхний угол которого находится в точке (0,0). Вы поворачиваете его на 45 градусов по часовой стрелке, чтобы он стал ромбом (снова верхний левый угол находится в точке (0,0)). Если вы хотите увидеть, соприкасается ли местоположение сцены (0, 25) с bmd (что так и есть), то вы не можете использовать hitTest с (0, 25), потому что hitTest измеряет местоположения относительно bmd. Вам нужно преобразовать это местоположение в (25/sqrt(2), 25/sqrt(2)), для чего предназначен код в моем примере. - person Mahir; 07.07.2010
comment
Что у меня есть: 2 видеоклипа со скоростью X и скоростью Y. Что я хочу: событие таймера / кадра (‹‹‹это я могу сделать), где я проверяю, сталкиваются ли они, и каков угол столкновения. Как я думаю, что я это сделаю: в actionscript3 есть hitTestObject. Я вижу, сталкиваются ли внешние блоки mc1 и mc2 с этим тестом. Если да, то мне нужно преобразовать их в пиксели и посмотреть, есть ли у них по крайней мере 2 непрозрачных пикселя с одинаковыми координатами (но я проверю это только в прямоугольнике пересечения между двумя внешними блоками мувиклипов). Если это произойдет, они сталкиваются, и я могу узнать угол столкновения - person jmacedo; 07.07.2010
comment
Проблема не в алгоритме или математике. Нужно знать, что делает каждая вещь и каковы ограничения. Что происходит, когда я рисую MovieClip1 в BitMap1, а затем рисую MovieClip2 в BitMap2? Координаты вещей... как работают эти методы. Вот что мне нужно узнать.. - person jmacedo; 07.07.2010

Классическим справочником по обнаружению столкновений пикселей во flash является эта статья Гранта Скиннера< /а>. Это AS2, но логика для AS3 такая же (есть доступные порты, если немного погуглить).

Если я правильно помню, эта конкретная реализация работала до тех пор, пока оба тестируемых объекта имели одного и того же родителя, но это можно исправить.

Что касается значений BitmapData x и y, я понимаю, что это может сбивать с толку; однако то, как это работает, имеет смысл для меня. BitmapData — это именно то, что следует из названия: пиксельные данные. Это не экранный объект, и он не может быть в списке отображения; поэтому наличие x или y, отличного от 0, на самом деле не имеет смысла, если подумать. Самый простой способ справиться с этим, вероятно, сохранить смещение (x,y) исходного объекта (экранный объект, из которого вы нарисовали) и перевести его в глобальное координатное пространство, чтобы вы могли сравнивать любые объекты, независимо от их положения в списке отображения. (используя что-то вроде var globalPoint:Point = source.parent.localToGlobal(new Point(source.x,source.y)).

person Juan Pablo Califano    schedule 08.07.2010
comment
Я помню, что метод Гранта Скиннера работает правильно только в том случае, если оба объекта являются прямыми потомками сцены. - person Cameron; 08.07.2010

Ранее я использовал класс обнаружения идеальных столкновений Троя Гилберта (адаптированный от Андре Мишель, Гранта Скиннера и Бульвара), который работает очень хорошо (обрабатывает вращение, разные родители и т. д.):

http://troygilbert.com/2007/06/pixel-perfect-collision-detection-in-actionscript3/
http://troygilbert.com/2009/08/pixel-perfect-collision-detection-revisited/

и оттуда он также связался с этим проектом (который я не использовал, но выглядит действительно впечатляюще):

http://www.coreyoneil.com/portfolio/index.php?project= 5

person Sly_cardinal    schedule 08.07.2010

В конце концов, мне это удалось, и я уже написал свой класс для обнаружения столкновений, угла столкновений и других дополнений.

Самый запутанный процесс, возможно, заключается в правильном выравнивании растровых изображений для сравнения. Когда мы рисуем() мувиклип в BitmapData, если мы добавимChild() соответствующий Bitmap, мы увидим, что часть его не видна. кажется, что он нарисован от центра только вправо и вниз, оставляя верхнюю и левую части не нарисованными. Решение заключается в предоставлении матрицы преобразования во втором аргументе метода рисования, который выравнивает растровое изображение и заставляет его отрисовываться.

это пример функции в моем классе для создания растрового изображения для сравнения:

    static public function createAlignedBitmap(mc: MovieClip, mc_rect: Rectangle): BitmapData{
                var mc_offset: Matrix;
                var mc_bmd: BitmapData;

                mc_offset = mc.transform.matrix;
                mc_offset.tx = mc.x - mc_rect.x;
                mc_offset.ty = mc.y - mc_rect.y;
                mc_bmd = new BitmapData(mc_rect.width, mc_rect.height, true, 0);
                mc_bmd.draw(mc, mc_offset);

                return mc_bmd;
}

чтобы использовать его, если вы находитесь на временной шкале, вы делаете:

className.createAlignedBitmap(myMovieClip, myMovieClip.getBounds(this))

Обратите внимание на использование getBounds, возвращающего прямоугольник, в который встроен фрагмент ролика. Это позволяет вычислить матрицу смещения.

Этот метод очень похож на показанный здесь http://www.mikechambers.com/blog/2009/06/24/using-bitmapdata-hittest-for-collision-detection/

Кстати, если это интересно для вас, проверьте мой другой вопрос, который я опубликую через несколько минут.

person jmacedo    schedule 15.07.2010