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.

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.

Announcing LicenseKeeper, a New Blog, and a Company Name

A funny thing has happened to me since I started writing about my pursuit of Mac game development. New needs, ideas, and opportunities have arisen. Some directly related to blogging, some related to running a MicroISV, and yet others related to my normal everyday technology-centric life.

This last item leads me to my first announcement:

Over the past year, my collection of shareware or demo-ware that I’ve downloaded and purchased off the internet has grown significantly. All these products have something in common. They send me a license key to unlock the full version of the software after payment. This license information comes to me via email and I copy and paste or type in this information into the application and it “magically” unlocks its full feature list and I’m ready to go.

So what happens when I reinstall Mac OS X or upgrade my computer? I need to find these emails again and then enter all these license keys and related information. I can use SpotLight or search in Mail.app to help me find all these registration receipts, but that assumes I can remember the applications I registered and their names. Magnify this problem if I ever need to buy multiple licenses for future employees and their computers. What about software running on multiple company servers? It would be nice to have all this information in one place.

This leads me to a new software development project: LicenseKeeperTM.

LicenseKeeperTM is a Cocoa application that keeps track of all the applications a user has purchased, the license keys and serial numbers needed to unlock the software, and all the registration information that was used to purchase each product.

Additionally, LicenseKeeperTM provides me a good way to gain more experience with Cocoa, Objective-C, and CoreData. It also gives me the opportunity to learn about the details of packaging and distributing a Mac software bundle and pushes me to work out the details of my distribution system (i.e. website, payment gateway, etc).

This announcement also brings up a new issue for me. Now that I’m actively working on non-game related software development (yes there are more products to come) and want to share the experiences through a blog, I need a place to do this; MakeMacGames doesn’t feel like the right place to do it. I imagine many that follow this site don’t care about non-game development or about consulting articles.

So this leads us to my second announcement: The Outer Level Blog. This is my new official company blog where I plan to bless the world with all of my non-game programming wisdom.

As I’m sure you’ve derived by these announcements, that my company name is Outer Level. I’ve held off revealing this until now because I wasn’t sure whether to use the same company name I use for my consulting work as my software business. Obviously, I’ve decided to simplify my life and stick with only one company or company name. This reduces paper work and headaches on my side and it may very well turn out that one side of my business benefits the other.

So, if you’re interested in following a MicroISV that is developing applications for the Mac, I hope that you follow me to The Outer Level Blog. But never fear, my gushing about what I’m up to in the realm of Mac game development will continue here on this site.

Game Prototype

I have a prototype started for a simple game using Objective-C and Cocoa. It’s been slow going, but I feel like I’m finally getting somewhere. I worked on it on and off while flying around the country the past couple of weeks on vacation (which helps explain the recent lack of updates to this site).

Okay, so it doesn’t look like much, but it’s a start. Have to start someplace right?

Mostly, what I’m getting out of this is a deeper understanding of Mac game programming in Objective-C and Cocoa.

So far nothing really happens visually except that the player gets drawn to the screen. But the window accepts keyboard input and determines what key(s) were pressed and has the structure ready to send commands to various game objects to tell them what to do: move, shoot, etc.

In order to handle this basic functionality, I put together the following class hierarchy:

The class OLGameView is a subclass of NSView and handles the display of the game state. It in turn calls game objects to draw themselves inside a provided NSRect object via the drawInRect:(NSRect)rect method. Object movement is handled by the keyDown:(NSEvent)theEvent and keyUp:(NSEvent)theEvent methods of the OLGameView class which then calls the moveInDirection:(int)direction method of the Player class.

The next step is to add an NSTimer instance that will handle the refreshing of the window that will create the game animation.

Cocoa Game Programming Workshop

Do you have $10 and the desire to quickly get up to speed on game programming and Apple’s Cocoa framework? I did.

I recently finished a book on Objective-C and Cocoa programming that gave me a pretty good introduction and base for developing applications on the Mac. Though the book was helpful, I still felt lost when it game to taking my recently acquired knowledge and applying it to games.

Enter Cocoa Game Programming Workshop, by David Hill from SpiderWorks.

This $9.95 eBook walks you through developing your own Gauntlet clone.

Well okay, not quite the Gauntlet I remember but certainly a big step forward in putting together a simple tile-based hack-n-slash type game.

The finished game isn’t really the goal though. What I got out of it is a solid base for moving forward with my own Mac game project. Hill, fills in the pieces I was missing and gave me just enough of a start that I feel like I can move forward.

Some of the helpful things I picked up that will definitely help moving forward:

  • Subclassing a Cocoa Custom View to serve as the main game view
  • Displaying images on the screen using NSImage objects
  • Reading and Writing XML documents
  • Accessing resource files (graphics and sounds) included inside the application bundle
  • Setting up a timer with callback functions (selectors)
  • The Cocoa sound API and using NSSound objects
  • Handling Keyboard input
  • Refactoring Objective-C

The book really is geared towards a beginning game programmer. I imagine someone who knows Cocoa and Objective-C to even an intermediate level could probably put this simple game together. But for someone like me, who has no real prior experience with Apple’s development tools, this seemed like the perfect introduction.

There’s enough information to get a game up and running without getting bogged down in too much of Cocoa’s details. Now, I can get started and pick up what I need as I need it.

More on Learning Cocoa

As I stated in yesterday’s article, Learning Cocoa, I’m struggling with the syntax of Objective-C. It’s not that I don’t understand it, it’s just completely different looking than C-derived syntax like Java, C++, C#, and php (the languages I use in “real-life”).

To add to the problem, I’m struggling with style. What I mean here is how to layout the code as I write it. What is the best way to use blank space and comments to full effect? How to name my functions so that they are easy to read and type, etc.

I’ve been following Wil Shipley’s site as he critique’s people’s code for style and best practices. This has been pretty helpful, but not quite the same as having a mentor to look over your shoulder.

So far, the best hope I’ve had is deeming insight from the books I’m reading and any example code I find. Short of that, I’ve been experimenting as I write my code.

For example, I have an initialize method on my Player class. I’ve played with two ways of calling the method. Which format looks easier to read to you?

This may seem like a small thing, but what happens when you have pages upon pages of code? Does your code get messy and hard to read? Right now I’m leaning towards the multi-line style, but Wil Shipley has been recommending everything on one line. Maybe as I get used to looking at Objective-C, I’ll agree with him.

Learning Cocoa

I’ve been spending a considerable amount of time trying to learn Objective-C and especially Cocoa.

After some searching around, I found tons of references to Cocoa Programming for Mac OS X by Aaron Hillegass. It’s a good tool for learning how to build applications with Apple’s development tools and frameworks, though it is missing some of the newer technologies.

I made it through the book and feel a bit better about what is going on, but I never really feel comfortable with a language or framework until I use it in an actual project. I’ve learned a ton of programming languages and frameworks through my years as a professional developer, but I think Objective-C and Cocoa are the hardest so far for me.

The first thing that I struggled with is the strange looking syntax that Objective-C uses to call methods of a class.

For example to call the setHealth method of an instantiated player object and pass in the value of 1, I would do the following:


[player setColumn: 1];

What really gets hairy and hard to read when you are not used to this syntax is when passing in multiple arguments to a method:


[player setPositionAtColumn: 1 andRow: 1];

And just to make it even harder to read, let’s move the player over one column:


[player setPositionAtColumn: [player column] + 1 andRow: 1];

It’s probably just a matter of getting used to the syntax, but boy does it really look and feel foreign to me. Though, I must admit, I really like the way that each method parameter is specified outright with a part of the method name. If you compare the next two method calls, which is more clear on what is happening?


[player initAtColumn: 1 andRow: 1 withHealth: 100 andScore: 0];


player.init(1, 1, 100, 0);

On top of the extremely foreign syntax, the Cocoa framework is huge! Finding out how to do things is an adventure sometimes. It’s one thing to have a book walk you through step-by-step, but when it comes time to actually program something from scratch while looking at the blank screen in the Xcode editor, I feel a bit lost.

Open-Source Shareware Registration Framework

Are you looking for a way to setup a registration system for your shareware software?

There are several commercial products out there, but Aquatic has released a free (donations accepted) open-source framework: AquaticPrime. It supports both Cocoa and Carbon integration and also includes a php-based library for use on your online e-commerce shopping cart system.

AquaticPrime utilizes the strong one-way encryption algorithm, RSA to provide for a powerful way of locking down your product.

Aquatic also has simple Developer Documentation available to help you along your way when integrating the framework into your product.