获取点和影片剪辑之间的距离

Posted

技术标签:

【中文标题】获取点和影片剪辑之间的距离【英文标题】:Get distance between a point and a movieclip 【发布时间】:2019-03-30 10:23:32 【问题描述】:

我正在实现一个游戏,但我一直在寻找一种方法来计算从一个点到动画剪辑最近边缘的 x 和 y 距离。 例如:

我需要计算从每个黑点到动画剪辑最近边缘之间的距离(动画剪辑并不总是圆形,它是随机形状)。

我很乐意找到解决方案。谢谢!

【问题讨论】:

MovieClip 真的总是一个圆形吗?或者它是一个不限于任何东西的随机形状? 形状随意。 哦,这很棘手。我认为最直接(以及性能低效)的方法是在该 MovieClip 上使用 getBounds(...) 方法,然后遍历其边界框像素hitTestPoint(...) 以像素为单位(shapeFlag 设置为 true,还要记住它需要 global 坐标作为参数,而不是本地)方法来确定 a) 属于 MovieClip 的点,并且 b) 最接近您想要的任何其他点 (Point.distance(. ..) 方法)。 P.S. 线条没有实质内容,即使您将它们设置为 100px 宽度也不会 hitTestPoint。只有填充、文本字段、位图图片(这些实际上是在发布时翻译为位图填充),不知道按钮的点击区域,也许他们不会。像发光、模糊和阴影这样的过滤器可能也不会。 你有关于形状本身的任何信息吗? (边缘/点坐标)它是如何生成的?我可能已经找到了解决方案,但它真的很丑,而且可能效率不高。 【参考方案1】:

我怀疑(尽管被证明是错误的)如果没有关于形状的几何数据,基于像素的操作可能是唯一的方法。

如果有几何数据,那么可以只对形状中的点与其他点之间的距离进行线性检查(想到的第一个简单的解决方案——更好的解决方案)。

即使形状是用户生成的(如绘图),也可以在绘图期间对点进行采样以获取点数据,依此类推。我把它放在一边,因为我认为其中任何一个都会比我下面的解决方案更快/更有效(仅假设像素)。

话虽如此,这个解决方案的工作原理是使用 BitmapData 的 hitTest() 检查两个形状是否发生碰撞。它几乎没有效率,不可否认,我不久前刚醒来,并决定这是一个很好的晨练。我没有测试任何错误情况(也就是,如果点在形状内)。

它的工作原理是从点末端开始并在其周围绘制越来越大的圆圈,在每一步将其转换为位图并使用 BitmapData 的 hitTest()。当它认为位图相交/接触时,围绕该点的圆的半径将是与形状最近的距离。

但是,可以通过调整“探针/步长”来提高效率(类似于二分搜索比线性搜索更有效)。但是,我将把它留给读者(代码 cmets 中的示例)。

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:决定添加一张图片来展示它在做什么。

【讨论】:

以上是关于获取点和影片剪辑之间的距离的主要内容,如果未能解决你的问题,请参考以下文章

影片剪辑和图形符号之间的性能有区别吗?

检测数组中影片剪辑内的对象与另一个对象数组之间的碰撞

如何从随机影片剪辑中获取 .x 和 .y?

如何在 CreateJs 中获取影片剪辑的宽度/高度?

ActionScript 2,嵌套影片剪辑列表

在舞台 AS3 上放置多个影片剪辑实例