None of the code examples have been checked for accuracy, nor has the text been proofread for general consumption. This book is a collaboration which is why it's available in such a rough form.
So you want to be a Macintosh game programmer? Well, this book is meant to get you up and writing a game as soon as possible. This book is (will be ) filled with tips, tricks and programming secrets that I have collected over the many years of my c.s.mac.programmer newsreading days.
Also included is (will be) great advice from the top Macintosh game programmers of today.
So again, welcome to the Mac Game Programmers book and good luck on your new game.
Matthew Xavier Mora mxmora@mxmdesigns.com
It has been said over and over that the Mac is a lousy game platform because "it is to hard to program" or "the OS gets in the way" (can we have a little cheese with that whine :-)). This book's purpose is to prove both those theories wrong.
In this book we will show you how to get a basic Mac program running. We'll also show you do's and don'ts and other things that effect performance and the Mac user expectations. Once the shell is running its easy to add the other code to your game. Some things we will show are:
Getting Started
The first thing you need to do is to initialize the Toolbox. During toolbox initialization it's a good time to test for the features that you might need for your game. For example, we only support System 7 or greater for this game. If the test for system seven fails then we bring up an alert dialog to let the user know why we can't run. Alert's and other resources are covered in Chapter xx If we fail at initialization then we quit. Below is an example on how to initialize the toolbox.
SysEnvRec gMac;
//--------------------------------------------------------------------
short InitMac()
//--------------------------------------------------------------------
{
short i;
short oe,result = 0;
InitGraf(&qd.thePort;);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs((long)NULL);
SetApplLimit(LMGetCurStackBase() - STACK );
MaxApplZone();
for (i = 0;i<10;i++)
MoreMasters();
oe = SysEnvirons(1,&gMac;);
if (gMac.systemVersion < 0x700) { // if less than system seven then bail
Alert(kNeedSystemSevenAlertID,nil);
result = 1;
}
}
The main function is real small since we don't spend much time in this function. We call InitMac(), if that succeeds then we loop until the gRunning flag is cleared.
//--------------------------------------------------------------------
void main(void)
//--------------------------------------------------------------------
{
EventRecord event;
Boolean gRunning = true;
if (InitMac()) { // Init the toolbox
ExitToShell(); // Ack! Something wrong so bail
}
while (gRunning) {
if (WaitNextEvent(everyEvent,&event,gSleepTime,nil)){
EventLoop(&event);
} else {
DoIdle();
}
}
}
Now is when it starts to get tricky on how to proceed from here. A game like Marathon doesn't have a menu bar so that they only need to detect clicks in their custom drawn screens.
Other games have a menubar and let you do a majority of the game setup from the menu bar. Using this approach you can have a start up window with a menubar and when the user select New game you can then eathier do you game in a window or blank the screens.
In any case you still need to get events and do something with them.
Our event loop function will show how to handle both caees. If you want the menu's handling then set the appropireate defines.
We will show two examples of main eevnt loops. One for Marathon type games that take over the entire screen and th othr for game that play withnin window and have a menu bar.
The proper way to get events on the macintosh is via the Toolbox call WaitNextEvent. Game programmers often try to avoid using the os's method for getting events and usally poll the hardware. On the mac this is frownd upon. The best thing to do is to let the user decide if she wants to have better performance vs giving time to background processes.
//--------------------------------------------------------------------
void EventLoop(EventRecord *evt)
//--------------------------------------------------------------------
{
switch (evt->what) {
case mouseDown:
break;
case keyDown,autoKey:
break;
default:
break;
}
}