2

I have a problem and I have potential solution. But I wanted to confirm if there is an easy and simple way to solve my problem.

App type:

Isometric Game

Problem statement:

I am loading images in my flash app and have mouse events attached to them.

The images I load are prop images like vehicles, trees, buildings etc., and all of them are transparent.

Example: Red ball asset (please ignore the yellow background which I applied to describe the problem)

Red Ball Asset

If I click on the actual image area (colored in red), then every thing works perfect

I don't want to trigger mouseevent when I click on empty image part (or transparent area, which I have shown in yellow color)

There is one way I know by creating masks in flash. I don't want to do it unless that is the final option left because I load image assets instead of flash assets and I don't want to create a new mask asset for all the assets

There is another method I was going to adopt by using getPixel method of Bitmap. Which is discussed here.

But there is another problem with this method.

I might be able to ignore the click event when I click on the empty part of the asset but if there is some other asset is behind the image in the same location, then I need to process the click event for the occluded image.

Well, thinking of solution to this problem takes me to the getObjectsUnderPoint where I can scan the occluded assets

Community
  • 1
  • 1
dejjub-AIS
  • 1,501
  • 2
  • 24
  • 50
  • Maybe you could also have a look at the hitArea property. I'm not sure it would be better than a mask in your case, so I make this a comment rather than an answer, but at least it is related to the problem: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Sprite.html#hitArea – Lars Blåsjö Mar 03 '12 at 13:17
  • Why not use flash assets instead of image assets? Customize (e.g. by cuting unnecessary transparent pixels) every image and export as swf. Or create swf libraries of assets. – Engineer Mar 03 '12 at 13:29
  • I am pretty sure that all virtual games in facebook are coded to download in the run time. I observed it with http sniffers. When I think, its a better option instead of having bundle all assets in the swf which the game is not going to use. – dejjub-AIS Mar 03 '12 at 15:08

2 Answers2

2

Well, what you proposed as a solution is 100% valid. Just move the logic of determining what game object is clicked outside of that object.

  1. Listen for MOUSE_DOWN/MOUSE_UP events at container which contains your game objects.
  2. Catch an event
  3. Check if the game object which is the target of this event is transparent at this point using BitmapData.getPixel32
  4. If it is use getObjectsUnderPoint to find out all other game objects at this point
  5. Find in a loop the first object which is not transparent at this point

Now you got the actual object which is hit.

Valentin Simonov
  • 1,768
  • 10
  • 14
  • Every time the user clicks on an object, you want to do BitmapData.draw() for multiple objects, then presumably localToGlobal() and globalToLocal() to find the right object? Every single time? And you call my solution stupid? Hats off. How about you show us some code. – Manish Mar 03 '12 at 16:38
  • He uses bitmaps. Bitmaps got `bitmapData` property. – Valentin Simonov Mar 03 '12 at 17:07
  • he can't possibly be working with `Bitmap` objects, because they're not clickable to begin with. I assume he's working `Loader` objects, since he says "download in the run time." – Manish Mar 03 '12 at 17:23
  • Alright and while loading images with `Loader` its `content` contains what? – Valentin Simonov Mar 03 '12 at 17:30
  • I am loading with loader and cloning bmp. I will try that – dejjub-AIS Mar 04 '12 at 05:22
1

One interesting solution is to use Sprite objects with the individual non-transparent pixels burnt onto them.

Suppose this is your Loader "complete" handler:

private function loaderCompleteHandler(event:Event):void
{
    // Loader is not our child, we use a Sprite instead (below).
    var loader:Loader = Loader(event.target);

    var sprite:Sprite = new Sprite();
    addChild(sprite);

    var w:Number = loader.content.width;
    var h:Number = loader.content.height;

    // Use transparent bitmap.
    var bitmapData:BitmapData = new BitmapData(w, h, true, 0);
    bitmapData.draw(loader.content);

    // Now burn the image onto the Sprite object, ignoring
    // the transparent pixels.
    for (var xPos:int = 0; xPos < w; xPos++) {
        for (var yPos:int = 0; yPos < h; yPos++) {
            var pixel32:uint = bitmapData.getPixel32(xPos, yPos);
            var alpha:int = pixel32 >>> 24;
            if (alpha != 0) {
                sprite.graphics.beginFill(pixel32 & 0xFFFFFF, alpha / 0xFF);
                sprite.graphics.drawRect(xPos, yPos, 1, 1);
                sprite.graphics.endFill();
            }
        }
    }

}

Essentially you want "empty" pixels that aren't clickable, and fully transparent pixels aren't quite the same thing. With this solution you get empty pixels.

Only problem is that this might be slow. Give it a shot.

Manish
  • 3,472
  • 1
  • 17
  • 16
  • 4
    @ValentinSimonov "This is stupid" is not a helpful comment. Please explain why it's stupid. – Manish Mar 03 '12 at 16:49
  • Because much better solution exists. – Valentin Simonov Mar 03 '12 at 17:11
  • It will kill memory and cpu when You load lot of assets . – turbosqel Mar 03 '12 at 17:36
  • @turbosqel I am simply substituting one Sprite object for one Loader object. Memory, no problem. CPU, maybe. I highly doubt it though; this is done when the image is first loaded (not on every click). – Manish Mar 03 '12 at 19:21
  • You can try this when You have few images , but not ingame when You will have 20, 50 , 100 and more . You drawing a vector rectangle for each pixel in image . To display another You will have to copy whole object graphics and redrawing such thing takes lot of cpu. 'Noob AS Three Developer' is trying to do game , not a slideshow . – turbosqel Mar 03 '12 at 20:46
  • I am convinced with this solution and working fine for my game. Though my game has dozens of images they are not unique images so I already have cloning process implemented and I am creating a sprite only once and it is happening within millsecs (unnoticeable), How ever I have problem with the getObjectsUnderPoint solution as I need to do it every time I move the mouse and it is much much more performance intensive than this one. Thanks guys for your ideas and thoughts – dejjub-AIS Apr 28 '12 at 12:49