Just about every game will need collision detection of some form. If you are using Cocoa and Objective-C for your game programming, then you’re in luck. There are a bunch of easy to use methods that can save you some serious time.
For Bullfrog, I’ve started with an all developer graphics based approach. All game objects are created procedurally. For the time being, I’m using no sprites and very little animation. Later, I’ll add these things, but for now, I’m concentrating on the game play.
The biggest challenge I’ve faced to this point was how to handle collision detection. The bullfrog attacks by flicking out its frog tongue to catch the bugs buzzing around his frog pond. The tongue is drawn using the Cocoa class
NSBezierPath and its instance methods:
NSBezierPath* tonguePath = [[NSBezierPath alloc] init];
[tonguePath setLineWidth: TONGUE_WIDTH];
[tonguePath moveToPoint: [self getMouthPoint]];
[tonguePath lineToPoint: [self getTonguePoint]];
This code is called when the game loop requests the frog class to draw itself. If the player is currently attacking, the frog tongue gets drawn.
One of the nice things about the
NSBezierPath class is that it provides the extremely convenient method
bounds. This gives you a bounding rectangle for the graphic we drew above.
bounds, we can use the fantastically useful Core Foundation function
NSIsEmptyRect() combined with
NSIntersectionRect to determine if two objects intersect or collide.
Since I’m using
NSBezierPath to draw all my bugs, I can get all their bounding rectangles too. If I call
NSIntersetionRect with the bounding rectangle for the frog’s tongue and each bug’s bounding rectangle, I can tell if there is a collision by checking the resulting
NSIsEmptyRect. This is illustrated in the following code.
-(void) playerAttackWithTongueRect: (NSRect)tongueRect
NSMutableArray* bugsToRemove = [[NSMutableArray alloc] init];
NSEnumerator* bugEnumerator = [_bugs objectEnumerator];
while (bug = [bugEnumerator nextObject])
NSRect collisionRect = NSIntersectionRect(tongueRect, [bug getBoundingRect]);
if ( !NSIsEmptyRect(collisionRect) )
[bugsToRemove addObject: bug];
[_player setBugsEaten: [_player bugsEaten] + 1];
There is one big catch to all this however. This may be because of the way I have implemented my frog’s tongue, but it seems that the NSBezierPath object returns a
NIL instead of the correct
NSRectangle when the frog is facing in one of the cardinal compass directions: 0, 90, 180, 270, or 360 degrees.
To get around this issue I needed to construct my own
NSRectangle whenever my frog was facing one of these directions.
... [snip] ...
NSRect tongueRect = [tonguePath bounds];
if ( NSIsEmptyRect(tongueRect) )
if ( [self direction] == 0 || [self direction] == 360 )
tongueRect = NSMakeRect( mouthPoint.x, mouthPoint.y, [self attackRange], 3.0);
else if ( [self direction] == 180 )
tongueRect = NSMakeRect( mouthPoint.x - [self attackRange], mouthPoint.y, [self attackRange], 3.0); }
else if ( [self direction] == 90 )
tongueRect = NSMakeRect( mouthPoint.x, mouthPoint.y, 3.0, [self attackRange]); }
else if ( [self direction] == 270 )
tongueRect = NSMakeRect( mouthPoint.x, mouthPoint.y - [self attackRange], 3.0, [self attackRange]); }
... [snip] ...
Now the tongue will collide with the bug bounding rectangles in the cardinal compass directions.