Bitmaps and Dragonflies

More updates on the game development front. The game is turning out to be pretty fun and challenging. With the new bug types, it makes it very challenging to predict the bugs movement. I have a few more bug type ideas that I’ll be experimenting with that could prove to be quite challenging and interesting.

List of New Features:

  • The game is now fully playable (rounds, score, etc)
  • The frog is now drawn with a bitmap image instead of circles and lines
  • Now has two bug types: gnats (small red circles) and dragonflies (large green circles)
  • Jumping distance has been increased
  • Round time is now set at 30 sec
  • Dragonflies give a time bonus when eaten

Bullfrog Progress

More game development progress updates:

  • Water has been added (though it doesn’t affect game play yet)
  • The frog’s tongue now has a recharge rate, so you can’t simply hold down the attack key
  • Tongue Attack ready indicator via the tongue tip gets drawn
  • Score Board keeps track of bugs, rounds, and time
  • Frame Rate display
  • Game Over and Round Over messages have been added at appropriate times

Latest Screen Shot:

OMG Cup Developer Journals

There’s a nice discussion about the progress people are making on their OMG Contest entries over on iDevGames. Competition looks stiff — pretty intimidating.

Anyway, here’s a list of some of the developer’s journals that I found:

If you know of anyone else that is blogging about their development effort for the OMG Cup 2005, let me know and I’ll add them to the list.

Time-based Animation

Yesterday, I discovered a serious flaw in the design of Bullfrog.

I’ve been developing this game on a PowerMac Dual 2GHz G5 with 1 GB RAM. The game was designed to run at approximately 60 frames per second. The animation was smooth and all the game objects moved at their correct speeds.

Last night, I decided to move my development over to my aging PowerBook 800 MHz G4 with 1 GB RAM so I could work on my code while watching the World Series on my couch.

Boy, what a wake up call!

Everything crawled on the screen. My frame rate dropped to about 30 frames per second and the whole thing became unplayable.

So, in comes the major refactoring task in order to support time-based animation and movement. After a long night, it all seems to be working now.

I keep track of time elapsed between frames and then calculate the percentage difference from the 60 frames per second. Then take that percentage and multiply it against the movement constants for each game object. This seems to take care of all the problems — though I probably need to test it out on some different processors when I get the chance.

Collision Detection With Cocoa

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: moveToPoint:(NSPoint) and lineToPoint:(NSPoint).


NSBezierPath* tonguePath = [[NSBezierPath alloc] init];
[tonguePath setLineWidth: TONGUE_WIDTH];
[tonguePath moveToPoint: [self getMouthPoint]];
[tonguePath lineToPoint: [self getTonguePoint]];
[tonguePath closePath];
[tonguePath stroke];

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.

Armed with 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 NSRectangle with NSIsEmptyRect. This is illustrated in the following code.


-(void) playerAttackWithTongueRect: (NSRect)tongueRect
{
NSMutableArray* bugsToRemove = [[NSMutableArray alloc] init];

NSEnumerator* bugEnumerator = [_bugs objectEnumerator];
Bug* bug;

while (bug = [bugEnumerator nextObject])
{
NSRect collisionRect = NSIntersectionRect(tongueRect, [bug getBoundingRect]);

if ( !NSIsEmptyRect(collisionRect) )
{
[bugsToRemove addObject: bug];
[_player setBugsEaten: [_player bugsEaten] + 1];
[self updateScoreDisplay];
}
}

[_bugs removeObjectsInArray:bugsToRemove];

[bugsToRemove release];
}

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.

A Frog Eats Bugs

I made tremendous progress today.

My bull frog now has full motion control. He can rotate a full 360 degrees and jump forward. He has a nice long frog tongue that can catch all the bugs that are flying around in his frog pond.

Features Remaining:

  • floating lily pads
  • rounds or levels
  • round clock (30 or 60 seconds)
  • score keeping
  • different kinds of bugs (dragon flies, gnats, mosquitos, etc.)
  • sound effects
  • finally, better graphics

Moving a Frog with Trigonometry

Ah, the joys of trigonometry. It’s been a long long time since I needed to know how to find points on a circle and how to determine the length of the the adjacent side of a triangle or remembering what a hypotenuse is.

One of the initial steps of getting my new game, Bullfrog, developed is movement. The player is a bullfrog, if you hadn’t guessed. The frog can rotate 360 degrees and can jump forward. So to move to a given point on the screen, the player would rotate the frog to the desired direction and then jump forward until reaching his destination. Simple enough, right?

Not if you haven’t looked at geometry or trigonometry functions for 15 years. How do you move a frog in a compass direction across the screen? Well, off to Google to search and search and search. One problem with searching on the internet, is you need to know what you are searching for.

Eventually, I figured it all out and found the right formulas. So to save myself time in the future and help my ailing memory, here is the code I wrote to handle these calculations. Maybe, it’ll benefit a reader as well.

Code fragments are in Cocoa / Objective-C:


#define PI 3.14

double DegreeToRadian(double degree)
{
return (degree * PI / 180);
}

double RadianToDegree(double radian)
{
return (radian * 180 / PI);
}

All this trigonometry stuff needs to be done in radians. So these functions convert angles back and forth from radians and degrees.


NSPoint CalculatePointFromCenterOfCircle(NSPoint circleCenter, int direction, int radius)
{
NSPoint point;
point.x = circleCenter.x + cos( DegreeToRadian(direction) ) * radius;
point.y = circleCenter.y + sin( DegreeToRadian(direction) ) * radius;

return point;
}

This code gives us the destination point. We send in the center of our circle or frog, the direction or 360 degree angle we want to move in, and finally the radius or distance we want to travel. We get back an NSPoint or (x,y) coordinates of or landing point.


NSPoint CalculateCenterPointOfCircle(NSRect rect, NSPoint rectOrigin)
{
NSPoint centerPoint = rectOrigin;
centerPoint.x += NSWidth( rect ) / 2;
centerPoint.y += NSHeight( rect ) / 2;

return centerPoint;
}

double CalculateCircleRadius(NSRect rect)
{
return NSWidth( rect ) / 2;
}

These functions do exactly what they are named.


- (void) moveForwardInGameViewRect:(NSRect)gameViewRect;
{
float maxXPosition = NSWidth( gameViewRect ) - [self width];
float maxYPosition = NSHeight( gameViewRect ) - [self height];

NSPoint newPosition = CalculatePointFromCenterOfCircle([self position], [self direction], [self moveSpeed]);

if ( newPosition.x < 0 )
{
newPosition.x = 0;
}

if ( newPosition.y maxXPosition )
{
newPosition.x = maxXPosition;
}

if ( newPosition.y > maxYPosition )
{
newPosition.y = maxYPosition;
}

[self setPosition:newPosition];

}

And finally, here we actually move our frog in the direction it is facing.

With this code and the ability to rotate my frog in 360 degress, I have a turning, leaping bull frog that can now try to catch bugs.

OMG Contest Entry: Bullfrog

After some brainstorming and encouragement from Gianfranco Berardi, I’ve decided to make a go at putting together a game for the Original Mac Games (OMG) Contest.

While dreaming up an idea, I decided that I would start from the prototype I already have. It wasn’t far enough along to really be specific to any one particular game idea, so was easy enough to change.

So with a small stepping stone already written, I just needed a game idea to fit my requirements in order to get started.

But, what to do?

While looking over my prototype, it hit me.

The green circle looks like a big frog to me. It was originally intended to be just a temporary marker for testing movement inside my game view; but no matter, it’s now a bullfrog.

So… the idea.

You are a bullfrog. You live in a small pond. You have 60 seconds to catch and eat all the bugs flying over your pond using only your frog tongue. You must jump from lily pad to lily pad as they float around and eat yourself silly. If you miss a lily pad when jumping, game over. The goal is to clear as many levels as you can without running out of time. Each level gets harder by adding more bugs. Different kinds of bugs move at different speeds. Some bugs give you bonus time.

So, that’s it… what do you think?

OMG Contest Ideas

I’ve been thinking all day about ideas for the OMG Contest. It seems with the very short time requirements for the contest, I’m pretty limited in what I can do. Maybe, this is a good thing.

I started out with a blank piece of notebook paper and simply jotted down requirement ideas that might help limit the scope of a game that could be completed within the time frame on a very small to zero budget.

This is the list I came up with:

  • Game must occur in one location, room, or level
  • The content requirements need to be absolutely minimal: procedural graphics
  • No time for complex A.I.
  • Simple game controls (no joysticks, game pads, etc)
  • No OpenGL
  • Simple game play
  • Fast Paced
  • Randomly generated levels and enemies

If I keep to this list of requirements, it may just be possible to do this. Of course, now I need an idea that fits this list.

OMG Contest

If you haven’t heard by now, you may want to look into the OMG Contest over at iDevGames.com.

Contest Overview
The OMG (Original Mac Games) Cup is a new game programming contest established by iDevGames, in connection with Freeverse Software, to encourage unique Mac game development. iDevGames is proud to partner with the Mac platform’s leading game developer of original Mac games, Freeverse Software. The challenge of the contest is to create innovative Mac OS X games that emphasize engaging gameplay—in only six weeks! The OMG Cup builds on the success of our smaller contest, “21 Days Later,” and the industry leading annual contest, “uDevGames.” With numerous success stories of past entrants of our uDevGames contest releasing commercial games, we look forward to fostering the development of a new generation of Mac game programmers. – Carlos Camacho (Editor-in-Chief, iDevGames)
Official Start
October 18, 2005 12:01am GMT
The Three Fs of Winning
Fame, Free games, and Freeverse cash (Please see complete list below)

I haven’t decided yet if I’m going make a go of this or not. But it looks very interesting and fun. I’m sure they will get a bunch of top notch entries. It’s great that Carlos was able to sign up Freeverse as a sponsor, that gives the contest an air of professionalism and adds some great incentives.