#include "GameManager.h" #include static pascal void Timer(EventLoopTimerRef r, void * d) { #pragma unused(r) VGame * g; UnsignedWide microseconds; float interval; Vector front, push; g = (VGame *)d; if(g->Status == MENU) { glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); RunInterface(&g->Interface); DrawInterface(&g->Interface); if(g->w.IsFullScreen) aglSwapBuffers(g->w.FullScreen); else aglSwapBuffers(g->w.Windowed); return; } g->Frames++; microseconds = UpTime(); interval = (10000.0 / (microseconds.lo - g->lastTime.lo)); g->lastTime = microseconds; if(TickCount() - g->FrameTimer > 60) { g->FrameTimer = TickCount(); g->FramesPerSecond = g->Frames; g->Frames = 0; } if (!g->Paused) { RunWorld(&g->world, interval); } glClear(GL_DEPTH_BUFFER_BIT); glLoadIdentity(); ForwardsVector(&g->world.Camera, 1.0, &front); push = front; if (g->Direction & STOP) { StopShip(&g->world.Physics, (SHIPACCELERATION / interval)); } else if (g->Direction & FORWARDS) { push.x *= (SHIPACCELERATION / interval); push.y *= (SHIPACCELERATION / interval); push.z *= (SHIPACCELERATION / interval); PushShip(&g->world.Physics, &push); } else if (g->Direction & BACKWARDS) { push.x *= -(SHIPACCELERATION / interval); push.y *= -(SHIPACCELERATION / interval); push.z *= -(SHIPACCELERATION / interval); PushShip(&g->world.Physics, &push); } TurnShip(&g->world.Physics, g->Rotation, interval); DrawWorld(&g->world, interval); if(g->w.IsFullScreen) aglSwapBuffers(g->w.FullScreen); else aglSwapBuffers(g->w.Windowed); } static void ResumeGame(VGame * g) { g->lastTime = UpTime(); g->FrameTimer = TickCount(); } static void SwitchMode(VGame * g, int Mode) { g->Status = Mode; if(Mode == MENU) { SetOrtho(&g->w); } else if(Mode == PLAYING) { SetPerspective(&g->w); ResumeGame(g); } } static pascal OSStatus MenuSelected(EventHandlerCallRef r, EventRef e, void * d) { #pragma unused(r) VGame * g; HICommand TheCommand; g = (VGame *)d; GetEventParameter(e, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &TheCommand); switch(TheCommand.commandID) { case 'FScn': if (g->w.IsFullScreen) { CreateWindowedContext(&g->w); if (g->Paused) { glClear(GL_DEPTH_BUFFER_BIT); DrawWorld(&g->world, 1.0); aglSwapBuffers(g->w.Windowed); } } else { CreateFullScreenContext(&g->w); if (g->Paused) { glClear(GL_DEPTH_BUFFER_BIT); DrawWorld(&g->world, 1.0); aglSwapBuffers(g->w.FullScreen); } } return noErr; break; case 'abou': OpenAboutWindow(&g->m); return noErr; break; default: return eventNotHandledErr; } } static pascal OSStatus MouseDown(EventHandlerCallRef r, EventRef e, void * d) { #pragma unused (r) VGame * g; Point MouseLoc; Rect HitRect; g = (VGame *) d; if(g->Status == PLAYING || !g->Interface.TitleDone) return eventNotHandledErr; GetEventParameter(e, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(MouseLoc), NULL, &MouseLoc); SetPortWindowPort(g->w.TheWindow); GlobalToLocal(&MouseLoc); /*sprintf(&String[1], "Horiz: %d Vert: %d", MouseLoc.h, MouseLoc.v); String[0] = (char)strlen(&String[1]); StandardAlert(kAlertNoteAlert, (unsigned char *)String, NULL, NULL, &Hit);*/ SetRect(&HitRect, 320, 485, 395, 515); if(PtInRect(MouseLoc, &HitRect)) SwitchMode(g, PLAYING); SetRect(&HitRect, 320, 515, 395, 555); if(PtInRect(MouseLoc, &HitRect)) /* We don't have options *yet* */; SetRect(&HitRect, 320, 555, 395, 595); if(PtInRect(MouseLoc, &HitRect)) QuitApplicationEventLoop(); return eventNotHandledErr; } static pascal OSStatus MouseMoved(EventHandlerCallRef r, EventRef e, void * d) { #pragma unused (r) VGame * g; Point MouseLoc; Rect HitRect; g = (VGame *) d; if(g->Status == PLAYING || !g->Interface.TitleDone) return eventNotHandledErr; GetEventParameter(e, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(MouseLoc), NULL, &MouseLoc); SetPortWindowPort(g->w.TheWindow); GlobalToLocal(&MouseLoc); SetRect(&HitRect, 320, 485, 395, 515); if(PtInRect(MouseLoc, &HitRect)) g->Interface.TitleOver.Play = true; else g->Interface.TitleOver.Play = false; SetRect(&HitRect, 320, 515, 395, 555); if(PtInRect(MouseLoc, &HitRect)) g->Interface.TitleOver.Prefs = true; else g->Interface.TitleOver.Prefs = false; SetRect(&HitRect, 320, 555, 395, 595); if(PtInRect(MouseLoc, &HitRect)) g->Interface.TitleOver.Quit = true; else g->Interface.TitleOver.Quit = false; return eventNotHandledErr; } static pascal OSStatus KeyDown(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused (nextEvent) VGame * g; char charCode; UInt32 modifiers; g = (VGame *) userData; GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode); GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); switch (charCode) { case 13: /* Return */ if(g->Status == MENU) SwitchMode(g, PLAYING); else SwitchMode(g, MENU); break; case 28: /* Left arrow */ g->Rotation &= ~RIGHT; g->Rotation |= LEFT; break; case 29: /* Right arrow */ g->Rotation &= ~LEFT; g->Rotation |= RIGHT; break; case 30: /* Up arrow */ g->Rotation &= ~DOWN; g->Rotation |= UP; break; case 31: /* Down arrow */ g->Rotation &= ~UP; g->Rotation |= DOWN; break; case ' ': if(modifiers & shiftKey) g->Direction = BACKWARDS; else g->Direction = FORWARDS; break; case 'b': case 'B': g->Direction |= STOP; break; case 'f': case 'F': AddWeapon(&g->world, WEAPONTYPEBULLET); break; case 'r': case 'R': AddWeapon(&g->world, WEAPONTYPEROCKET); break; case 'p': case 'P': if (g->Paused) { SetEventLoopTimerNextFireTime(g->timerRef, (kEventDurationSecond / 120.0)); ResumeGame(g); } else { SetEventLoopTimerNextFireTime(g->timerRef, kEventDurationForever); } g->Paused = !g->Paused; break; case ']': if (g->Paused) { g->Paused = 0; g->lastTime = UpTime(); g->lastTime.lo -= 100000; Timer(NULL, g); g->Paused = 1; } break; } return eventNotHandledErr; } static pascal OSStatus KeyUp(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent) VGame * g; char charCode; g = (VGame *) userData; GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode); switch (charCode) { case 28: /* Left arrow */ g->Rotation &= ~LEFT; break; case 29: /* Right arrow */ g->Rotation &= ~RIGHT; break; case 30: /* Up arrow */ g->Rotation &= ~UP; break; case 31: /* Down arrow */ g->Rotation &= ~DOWN; break; case ' ': g->Direction &= ~(FORWARDS | BACKWARDS); break; case 'b': case 'B': g->Direction &= ~STOP; break; } return eventNotHandledErr; } static pascal OSStatus AppActivated(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent, theEvent) VGame * g; g = (VGame *) userData; if (!g->Paused) SetEventLoopTimerNextFireTime(g->timerRef, (kEventDurationSecond / 120.0)); g->lastTime = UpTime(); return eventNotHandledErr; } static pascal OSStatus AppDeactivated(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent, theEvent) VGame * g; g = (VGame *) userData; SetEventLoopTimerNextFireTime(g->timerRef, kEventDurationForever); return eventNotHandledErr; } void InitGame(VGame * g) { EventTypeSpec eventType; InitCursor(); InstallEventLoopTimer(GetMainEventLoop(), 0, (kEventDurationSecond / 120.0), NewEventLoopTimerUPP(Timer), g, &g->timerRef); eventType.eventClass = kEventClassCommand; eventType.eventKind = kEventProcessCommand; InstallEventHandler(GetApplicationEventTarget(), NewEventHandlerUPP(MenuSelected), 1, &eventType, g, NULL); eventType.eventClass = kEventClassKeyboard; eventType.eventKind = kEventRawKeyDown; InstallApplicationEventHandler(NewEventHandlerUPP(KeyDown), 1, &eventType, g, NULL); eventType.eventClass = kEventClassKeyboard; eventType.eventKind = kEventRawKeyUp; InstallApplicationEventHandler(NewEventHandlerUPP(KeyUp), 1, &eventType, g, NULL); eventType.eventClass = kEventClassApplication; eventType.eventKind = kEventAppActivated; InstallApplicationEventHandler(NewEventHandlerUPP(AppActivated), 1, &eventType, g, NULL); eventType.eventClass = kEventClassApplication; eventType.eventKind = kEventAppDeactivated; InstallApplicationEventHandler(NewEventHandlerUPP(AppDeactivated), 1, &eventType, g, NULL); SetQDGlobalsRandomSeed(TickCount()); InitMenu(&g->m); InitWindow(&g->w); InitWorld(&g->world); InitConsole(&g->world.Console, &g->world.Player, &g->FramesPerSecond); InitInterface(&g->Interface, &g->w); eventType.eventClass = kEventClassMouse; eventType.eventKind = kEventMouseDown; InstallApplicationEventHandler(NewEventHandlerUPP(MouseDown), 1, &eventType, g, NULL); eventType.eventKind = kEventMouseMoved; InstallApplicationEventHandler(NewEventHandlerUPP(MouseMoved), 1, &eventType, g, NULL); SwitchMode(g, MENU); g->Direction = STATIONARY; g->Rotation = STATIONARY; g->lastTime = UpTime(); g->w.quitOnClose = true; g->Paused = false; g->Frames = 0; g->FramesPerSecond = -1; g->FrameTimer = TickCount(); } void RunGame(VGame * g) { InitGame(g); RunApplicationEventLoop(); CleanUpGame(g); } void CleanUpGame(VGame * g) { RemoveEventLoopTimer(g->timerRef); CleanUpWindow(&g->w); CleanUpMenu(&g->m); CleanUpWorld(&g->world); }