Как получить самое верхнее значение x и y формы в спрайте? - PullRequest
0 голосов
/ 30 июля 2010

Я здесь полностью в лесу - у меня есть спрайт с нарисованной формой (в этом примере два разных спрайта). В любой точке мне нужно получить значения x и y самой верхней точкиформы.Спрайт действительно вращается, поэтому он также изменится в любой момент.Я даже не знаю, с чего начать - помогите?

http://paulmignard.com/stackoverflow/pieces.PNG

Ответы [ 2 ]

2 голосов
/ 31 июля 2010

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

function getTopMost(dpo:DisplayObject,global:Boolean = false):Point {
    var bounds:Rectangle = dpo.getBounds(dpo);
    var bmd:BitmapData = new BitmapData(bounds.width,1,true,0);
    var mat:Matrix = new Matrix();
    mat.translate(-bounds.x,-bounds.y);
    bmd.draw(dpo,mat);
    var colRect:Rectangle = bmd.getColorBoundsRect(0xff000000,0,false);
    bmd.dispose();
    var point:Point = new Point(bounds.x + colRect.x,bounds.y + colRect.y);
    var transfMatrix:Matrix = global ? dpo.transform.concatenatedMatrix : dpo.transform.matrix;
    return transfMatrix.transformPoint(point);
}

Сначала мы получаем ограничивающий прямоугольник экранного объекта. Таким образом, мы сразу отбрасываем любой прозрачный пиксель. Теперь этот прямоугольник уже дает вам «самый низкий» у спрайта (верхняя граница), так что теперь нам нужно только найти значение для соответствующего смещения x, чтобы получить искомую точку. На данный момент мы должны проверить пиксели, поэтому нам нужен объект BitampData. Нам нужно только нарисовать видимую часть экранного объекта (область, заключенная в bounds). Но так как мы уже знаем значение для y, высоты 1 px будет достаточно. Эти BitmapData должны обеспечивать прозрачность, и мы будем заполнять их прозрачными черными пикселями перед рисованием (поэтому мы можем обнаружить непрозрачные пиксели после; здесь мы рассматриваем прозрачный пиксель, значение альфа которого равно 0, и непрозрачный все остальное; используйте порог вместо этого, если хотите, это потребует небольших изменений в коде). При рисовании мы применяем перевод, чтобы нарисовать только ту часть, которую мы хотим, воображаемую «линию» высотой 1 пиксель вдоль верхней границы, равную ширине объекта.

Как только мы нарисовали BitmapData, мы получили прямоугольник, который охватывает все непрозрачные пиксели, используя getColorBoundsRect. Значение x этого прямоугольника - это то, что мы искали. И теперь у нас есть и х и у. Эти координаты относятся к видимой области объекта (bounds), поэтому мы должны сместить их по x и y, равным bounds. И это самая верхняя левая точка фигуры внутри спрайта.

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

Редактировать

Функция, которая делает то же самое, что и выше, но позволяет вам указать альфа-порог в диапазоне 0 - 255. Она использует ту же идею, которую я объяснил ранее, хотя ее реализация немного сложнее.

function getTopMostThreshold(dpo:DisplayObject,alphaVal:int,global:Boolean = false):Point {
    if(alphaVal < 0) {
        alphaVal = 0;
    }
    if(alphaVal > 0xff) {
        alphaVal = 0xff;
    }
    var alphaThreshold:uint = alphaVal << 24;
    var dpoBounds:Rectangle = dpo.getBounds(dpo);
    //  draw all pixel with alpha > 0
    var boundsBmd:BitmapData = new BitmapData(dpoBounds.width,dpoBounds.height,true,0);
    var mat:Matrix = new Matrix();
    mat.translate(-dpoBounds.x,-dpoBounds.y);
    boundsBmd.draw(dpo,mat);
    //  any pixel with alpha >= threshold will be set to alpha = 0xff
    boundsBmd.threshold(boundsBmd,
            new Rectangle(0,0,boundsBmd.width,boundsBmd.height),
            new Point(0,0),
            ">=",
            alphaThreshold,
            0xff000000,
            0xff000000);
    //  this rect encloses all pixels that passed the threshold (and hence were set to alpha = 0xff)
    //  With this, we have the value for y
    var alphaBounds:Rectangle = boundsBmd.getColorBoundsRect(0xff000000,0xff000000,true);   
    //  now, let's find the value for x; we know y, so 1 px height will be enough
    var aux:BitmapData = new BitmapData(alphaBounds.width,1,true,0);
    //  again, any pixel with alpha >= threshold will be set to alpha = 0xff
    aux.threshold(boundsBmd,
            alphaBounds,
            new Point(0,0),
            ">=",
            alphaThreshold,
            0xff000000,
            0xff000000);
    //  this rect will gives us the x value
    var colRect:Rectangle = aux.getColorBoundsRect(0xff000000,0xff000000,true);
    boundsBmd.dispose();
    aux.dispose();
    //  now, just add up the offsets: 
    //      the bounds of the dpo (that is, every px with alpha > 0)
    //      the area that encloses every px with alpha >= threshold
    //      the color bounds rect of the aux bmd we used to find x 
    var point:Point = new Point(dpoBounds.x + alphaBounds.x + colRect.x,
                                dpoBounds.y + alphaBounds.y + colRect.y);
    var transfMatrix:Matrix = global ? dpo.transform.concatenatedMatrix : dpo.transform.matrix;
    return transfMatrix.transformPoint(point);
}
1 голос
/ 31 июля 2010

Эй, я чувствую, что вы пытаетесь использовать этот спрайт как есть.Если это так, я бы посоветовал вам установить точку регистрации в этом месте, т.е. указать источник изображения в этой конкретной точке.Затем спрайт может быть легко использован, а проверки выполняются с использованием координат x & y.

  • Если вы делаете это динамически, т.е. вы рисуете изображение через as3, то начинайте с этой точки для рисования.Ваша точка регистрации останется такой же, как и точка начала координат.
  • Если вы используете вспышку для рисования изображения, установите изображение так, чтобы точка находилась в 0,0.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...