View Full Version : get a circle-shaped piece of an image

Feb 25, 2005, 01:58 AM
[note: I accidentally posted this in the Web Design and Development forum. I hope it's okay that I'm posting it here now (where it belongs) as well.]

Hi all,

I'm going to try to port my mom's adventure games (text + graphics) to OS X with Cocoa. I'm facing a problem with a bit of graphics animation. I'm not sure how to describe it...it's kind of like, blackness comes in on you from all sides, so that your circle of vision gets smaller and smaller. If this were to be done using rects, I could simply show smaller and smaller pieces of the image (the image that represents the scene, or what the player can see), with blackness all around. But I'm not sure how to do this with circles.

Check out this quick video I made of it, if you aren't sure what I'm talking about:
http://members.cox.net/fredhope2000/pavilion_blackout.mov (about 650 KB)

edit: URL fixed.


Feb 25, 2005, 10:57 AM
404 on the video.

From what I understand you have 1 image (the scene) and you want to overlay another image over it which contains a circle which is transparent (with the rest of the image black) that is getting smaller and smaller?

The animation is easy: use NSTimer. What to do with the timer?

Create a 3 new images of the correct size and composite the scene into the first. Fill the second with black. Draw a black circle of the correct size in the 3rd. The composite the 3rd to the 2nd using NSCompositeSourceOut (http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSImage.html#//apple_ref/doc/uid/20000344/BCIFACIA). This might need to be the other way round (i.e. 2nd to third). This should give you an image that is black with a transparent circle on it. The composite that over the scene.

If it works post the source back!

Feb 25, 2005, 03:00 PM
It worked. Thanks! I haven't put in the timer code yet or anything, but my main difficulty was getting only the center of the image to show. And I fixed the link in my above post, sorry about that.

Feb 25, 2005, 06:38 PM
You asked to see the code, so here it is.

First, make pointers to the scene image and black image, and fill the black image with a black rect:

image = [[NSImage imageNamed:@"sceneimage.jpg"] copy];
sceneWidth = [image size].width;
sceneHeight = [image size].height;

blackImage = [[NSImage alloc] initWithSize:NSMakeSize(sceneWidth, sceneHeight)];
path = [NSBezierPath bezierPathWithRect:NSMakeRect(0, 0, sceneWidth, sceneHeight)];
[blackImage lockFocus];
[[NSColor blackColor] set];
[path stroke];
[path fill];
[blackImage unlockFocus];

Then, draw it all for the first time, including giving the cicle a starting diameter and such. Make the timer:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.02
NSTimer *killTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer:killTimer forMode:NSEventTrackingRunLoopMode];

Here's what's in makeCircleSmaller:

circleDiameter--; //I declared circleDiameter in this class's header file.
float circleRadius = circleDiameter / 2.0;
path = [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(centerPoint.x - circleRadius, centerPoint.y - circleRadius,
circleDiameter, circleDiameter)]; //I defined centerPoint earlier.
[circleImage lockFocus];
[[NSColor blackColor] set];
[path stroke];
[path fill];
[circleImage unlockFocus];

[circleImage lockFocus];
[blackImage compositeToPoint:NSMakePoint(0, 0)
[circleImage unlockFocus];

[image lockFocus];
[circleImage compositeToPoint:NSMakePoint(0, 0)
[image unlockFocus];

[imageView setImage:image];
[imageView setNeedsDisplay:YES];