Получить расстояние между точкой и видеоклипом - PullRequest
0 голосов
/ 25 октября 2018

Я реализую игру, и я застрял в поиске способа вычислить расстояние x и y от точки и ближайшего края фрагмента ролика.например: Example

Мне нужно рассчитать расстояние от каждой черной точки до ближайшего края фрагмента ролика (фрагмент ролика не всегда является кругом, это случайная форма).

Я буду более чем счастлив найти решение.Спасибо!

1 Ответ

0 голосов
/ 26 октября 2018

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

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

Даже если форма генерируется пользователем (например, рисование), можно выбрать точкиво время рисования, чтобы получить точечные данные и так далее.Я подхожу к этому как к стороне, поскольку я думаю, что любой из них будет быстрее / эффективнее, чем мое решение ниже (которое предполагает только пиксели).

С учетом сказанного, это решение работает с использованием HitTest BitmapData () проверить, сталкиваются ли две фигуры.Это едва ли эффективно и, правда, я только недавно проснулся и решил, что это хорошее утреннее упражнение.Я не проверял на наличие ошибок (иначе как точка находится внутри фигуры).

Он работает, начиная с конца точки и рисуя вокруг нее все большие и большие круги, на каждом шаге преобразуяв растровое изображение и с помощью hitTest () BitmapData.Когда считается, что растровые изображения пересекаются / соприкасаются, радиус окружности вокруг точки будет наименьшим расстоянием до формы.

Эффективность, однако, можно улучшить, отрегулировав «размер зонда / шага» (ваналогично тому, что бинарный поиск более эффективен, чем линейный поиск).Однако я оставлю это на усмотрение читателя (пример в комментариях к коду).

import flash.display.Shape;
import flash.geom.Point;
import flash.display.BitmapData;
import flash.display.Bitmap;

// assumptions: the movie clip is currenly the only thing on the stage

// first generate the first BitmapData by taking all the pixels on the stage (which should just contain the movieclip)
var stagePixels:BitmapData = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, true, 0xffffff);
stagePixels.draw(this);


function getDistance(inputPoint:Point):int {

    var currentSearchDistance:int = 1;
    var result:Boolean = false;

    var zeroPoint:Point = new Point(0, 0); // just a common reference point for the hitTest() call
    var pointShape:Shape;

    while(result == false){
        // create the shape and draw the circle around the point
        pointShape = new Shape();
        pointShape.graphics.lineStyle(1);
        pointShape.graphics.drawCircle(inputPoint.x, inputPoint.y, currentSearchDistance);

        // convert to BitmapData
        var pointPixels:BitmapData = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, true, 0xffffff);
        pointPixels.draw(pointShape);

        // left this here to show the steps and what it is doing
        // will slow down stage rendering though since there are potentially a lot of bitmaps being added to the stage
        this.addChild(new Bitmap(pointPixels));

        result = stagePixels.hitTest(zeroPoint, 0xff, pointPixels, zeroPoint);

        // for now, increase the search distance by 1 only, so can return true when it hits the shape for the first time.
        // This can be optimized to take larger steps (and smaller) steps as well with multiple probes.
        // ex:
        // take a big step (+50)... didn't hit shape
        // so take another big step (+50)... hit shape so we know the point is between the first 50 to 100
        // take maybe half a step back (-25)... hit shape, so we know the point is between the first 50 and 75
        // take another half step back (-12)... didn't hit shape so we know the point is between 62 abd 75...etc
        // thus can slowly close in on the result instead of taking every small step (would have tkaen 62+ checks to get to this point vs 5)
        // (and can also decide to quite early for a "good enough" result)
        currentSearchDistance++;
    }
    return currentSearchDistance;
}

var dot:Point = new Point(100, 100); // input point here
trace(getDistance(dot));

edit: Решил добавить картинку, чтобы показать, что он делает.Decided to add a picture to show what it's doing.

...