开发者

Efficient irregular bitmap hit area

I have a Flash project that must display a large amount of irregularly shaped bitmaps (around 10000) and I want to know what bitmap the mouse is currently over. If the mouse is over a transparent part of the bitmap, it shouldn't count as mouse over.

One way to do this is to calculate the hit area, then replace each bitmap with a Sprite containing the bitmap and another Sprite with the calculated hit area, then set the hitArea property. But this is highly ine开发者_Python百科fficient and the result is completely unusable.

What's the most efficient way to do this?


Try this on the container:

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);
    }
}

If the Bitmaps overlap, iterate over hits. You can also set a threshold for the transparency.


Check this transparent PNG example out, I think it may be just what you're looking for.

Here is a link to the demo.

Best of luck.


What I would propose is to make use of something like a spatial hashing. Assuming each bitmap is of a similar size then we can divide your stage into a giant grid, where each cell will be bigger than any given bitmap.

Each bucket in the grid would hold a reference to a bitmap (note that a bitmap might be in more than one cell at a time). When the stage is clicked on, you can retrieve the mouse coordinates to use as a look up into this grid. Then you can iterate through the cell for bitmaps that it contains and check if the x,y coordinates are in the bounding box of the bitmap. If it is, then you can examine the pixel of the bitmap to check if it is a transparent pixel or not.

Assuming a bitmap is found, then you can return it as the bitmap clicked on.


I don't have code for this off the top of my head, but what you could do is have a layer for each bitmap where you've filled in the image with a flat color, with a different color for each image. Then on mouse click do a screenshot of the flat color layers and check the color of the pixel under the mouse.

ADDITION: Just saw your comment that the bitmaps don't move. That means you don't need to take a screenshot on mouse click; just take the screenshot once when the bitmaps are first loaded.


If the bitmaps are display objects, use the DisplayObjectContainer method: getObjectsUnderPoint(). This handles irregular vector objects correctly, but I haven't tried with bitmap objects.


The big issue is the massive amount of image to loop trough and check for transparency. If the bitmaps and their location doesn't change much (relative to each other) then there is a quite clean solution:

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

Now each time you want to get the image the mouse is over, you can use this array to look it up.

You'll have to recalculate this every time the layout changes.

This gives you some broad guidelines, there are many possible optimizations possible.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜