3

I´m making a game that simulates an industry of pan, and one of the process is Painting.

What I want to do is to let the player paint the pan, but i don´t want it to be easy using FILL, i want that the player paint the pan with an brush and then the game detects if all the area was painted and let the player advance.

For the painting i intend to use that library: http://www.nocircleno.com/graffiti/

But i have no idea how to detect if all the area was painted. Can someone show me some way of doing that?

Pyva
  • 33
  • 3

3 Answers3

6

One of the ways would be - you make a shielding BitmapData that has transparency and is opaque in place which you need your player to paint. (Color it as needed, but make sure the color is fully opaque). Then gather histogram() then query alpha vector for 255th value, this will be the initial value for zero percent filled. These range from 0-255, so you can't use 100 or any other fixed value. Then, while the player is painting, you draw the brush over that BitmapData with blendMode parameter set to BlendMode.ERASE, this will net your BitmapData to gain transparency where the brush was drawn. After your player finishes drawing by any means (say, the paint is used up), you run another histogram() over the BitmapData, and query the 255th value of alpha channel vector. 0 means the bitmap is fully transparent (or at least, only a small amount of pixels is left opaque), thus you can count a zero as 100% fill, for anything greater use the proportion.

var bd:BitmapData=new BitmapData(w,h,true,0x0); // fully transparent initial bitmap
bd.draw(yourPaintBase); // a shape that designates area to be painted. Must be fully opaque
var bm:Bitmap=new Bitmap(bd);
// position it as needed, so the area which should be painted is aligned to wherever you need
addChild(bm);
addEventListener(Event.ENTER_FRAME,doPaint);
var baseValue:int=bd.histogram()[3][255]; // Vector #3 contains alpha, #255 contains 
// percentage of those pixels that have alpha of 255 = fully opaque
function doPaint(e:Event):void {
    if (!areWePainting) return;
    var sh:Shape=getBrush(); // shuold return an existing Shape object reference for performance
    sh.x=e.localX;
    sh.y=e.localY; // we are drawing where the mouse is
    bd.draw(sh,null,null,BlendMode.ERASE);
    decreasePaint(); // we have used some paint
    if (noMorePaint()) {
        e.target.removeEventListener(Event.ENTER_FRAME,doPaint);
        var endValue:int=Math.floor(100*(1-bd.histogram()[3][255]/baseValue));
        // aligning to percentage. This is the value you seek
        reportFilledPercentage(endValue);
    }
}
Vesper
  • 18,599
  • 6
  • 39
  • 61
  • 1
    Your answer is a little harder than the other for me. . But if I master your way of doing that I can place the image that I want behind the Shield. I will try your answer first, if it gets too complicated for me I will try the other. I can´t up vote your answer. I will try to help some people and when i have 15 reputation i will definatelly upvote you. – Pyva Mar 13 '13 at 03:47
2

You can iterate over the pixels on your BitmapData and use getPixel() to check if the color of all those pixels is not white. If a white one is found, the image is not fully painted.

Something like this:

function containsWhite(bitmapData:BitmapData):Boolean
{
    for(var c:int = 0; c < bitmapData.width; c++)
    {
        for(var r:int = 0; r < bitmapData.height; r++)
        {
            // Check if pixel is white.
            if(bitmapData.getPixel(c, r) >= 0xFFFFFF)
            {
                return true;
            }
        }
    }

    return false;
}
Marty
  • 39,033
  • 19
  • 93
  • 162
  • 1
    It's worth noting that while this is the correct process, it is also a very heavy process on the processor and can be very slow, depending on the size of the bitmap. – Josh Mar 12 '13 at 16:16
  • That's true - you can break down larger images into chunks and then perform the check on each chunk separately. You can implement a callback to accept the true / false response once all the chunks have been assessed. This is a good candidate for an asynchronous approach :) – Marty Mar 12 '13 at 21:22
  • This is a good candidate to offload onto a worker or onto PixelBender, honestly. Obviously you will only be able to use a worker with non-mobile projects, though. – Josh Mar 12 '13 at 21:48
  • I will try that. .. REALLY thanks for your answer. I can´t up vote your answer. I will try to help some people and when i have 15 reputation i will definatelly upvote you. – Pyva Mar 13 '13 at 03:44
  • 1
    @user2159322 You're able to accept answers, which will raise your reputation as well. – Marty Mar 13 '13 at 03:49
  • 2
    @Apocalyptic0n3 I don't see if this can be offloaded to Pixel Bender, because PB shader returns a value per pixel, based on the supplied image's data, and here only one consolidated value is needed. PB can simplify the image for you, though, say by returning a black pixel for every non-white one, so you can use a `histogram()` more safely. – Vesper Mar 13 '13 at 03:59
  • @Vesper Good call. I've only used Pixel Bender for very basic things, so I wasn't sure if you could or not. I assumed you could, but I think you're right. Using it to make histogram work better is a great idea, though – Josh Mar 13 '13 at 04:52
0

Your essentially dealing with a collision detection problem. From looking at their API you could try something like a for loop with getColorAtPoint and try to determine they have drawn at each pixel.

If all else fails look into collision between the objects the library generates using the .hitTestObject method of an object.

See this: http://sierakowski.eu/list-of-tips/39-collision-detection-methods-hittest-and-hittestobject-alternatives.html

And this to see how someone handles collision with pixels: http://www.emanueleferonato.com/2010/08/05/worms-like-destructible-terrain-in-flash-part-2/