【问题标题】:Efficient irregular bitmap hit area高效的不规则位图命中区域
【发布时间】:2011-09-07 21:18:50
【问题描述】:

我有一个 Flash 项目,它必须显示大量不规则形状的位图(大约 10000 个),我想知道鼠标当前位于哪个位图上。如果鼠标悬停在位图的透明部分上,则不应计为鼠标悬停。

一种方法是计算命中区域,然后用包含位图的Sprite 替换每个位图,用计算的命中区域替换另一个Sprite,然后设置hitArea 属性。但是这样效率非常低,结果完全无法使用。

最有效的方法是什么?

【问题讨论】:

    标签: flash actionscript-3 actionscript


    【解决方案1】:

    在容器上试试这个:

    var hits:Array = getObjectsUnderPoint(new Point(mouseX, mouseY));
    if(hits.length > 0)
    {
        var bitmap:Bitmap = hits[0] as Bitmap;
        var color:uint = bitmap.bitmapData.getPixel32(bitmap.mouseX, bitmap.mouseY);
        if(color >>> 24 > 0)
        {
            trace('hit: '+bitmap);
        }
    }
    

    如果位图重叠,则迭代hits。您还可以设置透明度的阈值。

    【讨论】:

    • 为了澄清这个答案中的方法,他正在检查鼠标下的像素是否透明,如果不是则只报告命中。请注意,他首先会进行正常的 hitTest 以确定哪个位图需要进行更详细的检查。
    • 我认为我的答案更有效(不确定),但这种方法更简单,所以我会先尝试一下。
    • 我不认为这个答案效率低下,getObjectsUnderPoint 仍然可以引用空间网格
    【解决方案2】:

    检查this transparent PNG example out,我想它可能正是您要找的。​​p>

    Here is a link to the demo.

    祝你好运。

    【讨论】:

    • 这通过在位图本身上处理 mouse_over 事件来工作。我需要一种仅通过知道鼠标的 X 和 Y 位置即可工作的方法。
    【解决方案3】:

    我建议使用spatial hashing 之类的东西。假设每个位图的大小相似,那么我们可以将您的舞台划分为一个巨大的网格,其中每个单元格都将大于任何给定的位图。

    网格中的每个存储桶都包含对位图的引用(请注意,位图一次可能位于多个单元格中)。单击舞台时,您可以检索鼠标坐标以用作对该网格的查找。然后,您可以遍历单元格以查找其中包含的位图,并检查 x,y 坐标是否在位图的边界框中。如果是,那么您可以检查位图的像素以检查它是否是透明像素。

    假设找到一个位图,那么您可以在单击位图时将其返回。

    【讨论】:

      【解决方案4】:

      我脑子里没有这方面的代码,但你可以做的是为每个位图设置一个图层,在其中你用纯色填充图像,为每个图像使用不同的颜色.然后点击鼠标,对平面颜色层进行截图并检查鼠标下像素的颜色。

      补充:刚刚看到您关于位图不动的评论。这意味着您无需在单击鼠标时截取屏幕截图;只需在第一次加载位图时截取一次屏幕截图。

      【讨论】:

      • 很好的答案。我的 2 美分:为了有效地做到这一点,使用 copyChannel() 将每个图像的 alpha 通道复制到新的位图中,然后使用 colorTransform() 为位图赋予特定的颜色(这是它在 10000 中的数量)。使用 copyPixels() 将它们粘贴到与显示大小相同的屏幕外位图。当您想知道鼠标在哪个精灵上时,请在当前鼠标坐标处使用 getPixel() 读取像素 - 像素的颜色将是精灵的编号。我会发布代码,但这不是我的答案 =)
      • 我认为如果我需要在鼠标移动而不是单击时进行检查,这将是非常低效的。
      【解决方案5】:

      如果位图是显示对象,请使用 DisplayObjectContainer 方法:getObjectsUnderPoint()。这可以正确处理不规则的矢量对象,但我没有尝试使用位图对象。

      【讨论】:

      • 试过了,不行。它处理透明像素的方式与处理不透明像素的方式不同。
      • 那么您继续检查由 getOpjectsUnderPoint() 返回的大大减少的位图对象集合中鼠标下方位图中的像素。 (这与 Sean Fujiwara 的回答相同。)
      【解决方案6】:

      最大的问题是要循环通过大量图像并检查透明度。 如果位图及其位置没有太大变化(相对于彼此),那么有一个非常干净的解决方案:

      Make an array of bitmaps(references to bitmaps actually so not consuming a 
      gigamount of memory) the size of your screen (or even bigger when you want
      to be able to pan around in a bigger area like in a platform game for example).
      
      Loop over all images in z order (beginning with the image furthest away)
        [Calculate a mask for each image (making a black and white bitmap, white is transparent, black is everything else)]
        Loop over the pixels in the image [mask] and update the array (mind the offset) to the current bitmap if not transparent
      

      现在每次想要获取鼠标经过的图像,都可以使用这个数组来查找。

      每次布局更改时,您都必须重新计算。

      这为您提供了一些广泛的指导方针,有许多可能的优化。

      【讨论】:

        猜你喜欢
        • 2011-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多