#include "GameManager.h" #include "SoundManager.h" #define INTERVAL (1.0f / 50.0f) static pascal void Timer(EventLoopTimerRef r, void * d) { #pragma unused(r) VGame * g; double currentTime; double interval; Vector front, push; g = (VGame *)d; currentTime = GetCurrentEventTime(); interval = (currentTime - g->lastTime) + g->slop; while (interval > INTERVAL) { if (g->Status == MENU) { RunInterface(&g->Interface, INTERVAL); } else { if (!g->Paused) { RunWorld(&g->world, INTERVAL); if (g->world.Finished && !(g->Status & (FINISHEDLEVEL | DYING))) { SwitchMode(g, (PLAYING | FINISHEDLEVEL)); } } 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); if (g->world.Player.Shields <= 0 && !(g->Status & (DYING | FINISHEDLEVEL))) { SwitchMode(g, (PLAYING | DYING)); } if (g->Status & (STARTINGLEVEL | FINISHEDLEVEL | DYING)) { g->ModeFade += (1.0 / INTERVAL); if ((g->Status & STARTINGLEVEL) && g->ModeFade > STARTLEVELFADETIME) { SwitchMode(g, PLAYING); } else if ((g->Status & FINISHEDLEVEL) && g->ModeFade > FINISHLEVELFADETIME) { StopLevel(&g->world); if ((g->world.CurrentLevel + 1) >= g->world.NumberOfLevels) { SwitchMode(g, MENU); g->Interface.GameWasWon = 1; } else { /* if(g->world.CurrentLevel >= 0) StartLevel(&g->world, -(g->world.CurrentLevel + 1)); else StartLevel(&g->world, -g->world.CurrentLevel); */ StartLevel(&g->world, (g->world.CurrentLevel + 1)); SwitchMode(g, (PLAYING | STARTINGLEVEL)); } } else if ((g->Status & DYING) && g->ModeFade > DEATHFADETIME) { StopLevel(&g->world); InitPlayer(&g->world.Player); StartLevel(&g->world, g->world.CurrentLevel); SwitchMode(g, (PLAYING | STARTINGLEVEL)); } } } interval -= INTERVAL; } g->slop = interval; g->lastTime = currentTime; if(g->Status == MENU) { glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); DrawInterface(&g->Interface); if(g->w.IsFullScreen) aglSwapBuffers(g->w.FullScreen); else aglSwapBuffers(g->w.Windowed); return; } g->Frames++; if(TickCount() - g->FrameTimer > 60) { g->FrameTimer = TickCount(); g->FramesPerSecond = g->Frames; g->Frames = 0; } glClear(GL_DEPTH_BUFFER_BIT); glLoadIdentity(); DrawWorld(&g->world, interval); if (g->Status & (STARTINGLEVEL | FINISHEDLEVEL | DYING)) { if (g->Status & STARTINGLEVEL) glColor4f(0.0, 0.0, 0.0, 1.0 - (g->ModeFade / STARTLEVELFADETIME)); else if (g->Status & FINISHEDLEVEL) glColor4f(0.0, 0.0, 0.0, (g->ModeFade / FINISHLEVELFADETIME)); else if (g->Status & DYING) glColor4f(0.0, 0.0, 0.0, (g->ModeFade / DEATHFADETIME)); glLoadIdentity(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDisable(GL_DEPTH_TEST); glBegin(GL_QUADS); glVertex3f(-10.0, 10.0, -2.0); glVertex3f(10.0, 10.0, -2.0); glVertex3f(10.0, -10.0, -2.0); glVertex3f(-10.0, -10.0, -2.0); glEnd(); glEnable(GL_DEPTH_TEST); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } if(g->w.IsFullScreen) aglSwapBuffers(g->w.FullScreen); else aglSwapBuffers(g->w.Windowed); } static void ResumeGame(VGame * g) { g->lastTime = GetCurrentEventTime(); g->FrameTimer = TickCount(); if (g->Status != MENU && g->w.IsFullScreen) HideCursor(); else ShowCursor(); } 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); ShowCursor(); if (g->Status & PLAYING && g->Paused) { glClear(GL_DEPTH_BUFFER_BIT); DrawWorld(&g->world, 1.0); aglSwapBuffers(g->w.Windowed); } } else { CreateFullScreenContext(&g->w); if (g->Status != MENU) HideCursor(); if (g->Paused) { glClear(GL_DEPTH_BUFFER_BIT); DrawWorld(&g->world, 1.0); aglSwapBuffers(g->w.FullScreen); } } return noErr; break; case 'EndG': if (g->Status & PLAYING) { SwitchMode(g, MENU); } break; case kHICommandAbout: OpenAboutWindow(&g->m); return noErr; break; case kHICommandPreferences: if (!g->w.IsFullScreen) OpenSettingsWindow(&g->Settings); return noErr; break; } return eventNotHandledErr; } static pascal OSStatus KeyDown(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused (nextEvent) VGame * g; VSettings * s; unsigned char charCode; UInt32 modifiers; SInt16 key; g = (VGame *) userData; s = GetSettings(); GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode); GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); key = KeyWithModifiers(charCode, modifiers); if (charCode == 27) { /* Escape */ if (g->w.IsFullScreen) { CreateWindowedContext(&g->w); ShowCursor(); if (g->Status & PLAYING && g->Paused) { glClear(GL_DEPTH_BUFFER_BIT); DrawWorld(&g->world, 1.0); aglSwapBuffers(g->w.Windowed); } } } if (!(g->Status & PLAYING) || (g->Status & DYING)) return eventNotHandledErr; if (SettingsIsEquivalentKey(s, key, s->Left)) { g->Rotation &= ~RIGHT; g->Rotation |= LEFT; } if (SettingsIsEquivalentKey(s, key, s->Right)) { g->Rotation &= ~LEFT; g->Rotation |= RIGHT; } if (SettingsIsEquivalentKey(s, key, s->Up)) { g->Rotation &= ~DOWN; g->Rotation |= UP; } if (SettingsIsEquivalentKey(s, key, s->Down)) { g->Rotation &= ~UP; g->Rotation |= DOWN; } if (SettingsIsEquivalentKey(s, key, s->Forward)) { g->Direction = FORWARDS; } if (SettingsIsEquivalentKey(s, key, s->Backward)) { g->Direction = BACKWARDS; } if (SettingsIsEquivalentKey(s, key, s->Brake)) { g->Direction |= STOP; } if (SettingsIsEquivalentKey(s, key, s->Bullet)) { g->world.Player.Firing = 1; g->world.Player.NextFireTime = 0.0; } if (SettingsIsEquivalentKey(s, key, s->Rocket)) { if (g->world.Player.NumRockets > 0) PlaySound(GetSoundManager(), LAUNCHROCKETSOUND); AddWeapon(&g->world, WEAPONTYPEROCKET); } if (SettingsIsEquivalentKey(s, key, s->RocketTarget)) { PlaySound(GetSoundManager(), ROCKETTARGETSOUND); FindTarget(&g->world); } if (SettingsIsEquivalentKey(s, key, s->Pause)) { if (g->Paused) { //SetEventLoopTimerNextFireTime(g->timerRef, (kEventDurationSecond / 120.0)); ResumeGame(g); } else { //SetEventLoopTimerNextFireTime(g->timerRef, kEventDurationForever); InitCursor(); } g->Paused = !g->Paused; g->world.Console.Paused = g->Paused; } return eventNotHandledErr; } static pascal OSStatus KeyUp(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent) VGame * g; VSettings * s; unsigned char charCode; g = (VGame *) userData; s = GetSettings(); GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode); if (!(g->Status & PLAYING)) return eventNotHandledErr; if (charCode == (s->Left & 0xFF)) { g->Rotation &= ~LEFT; } if (SettingsIsEquivalentKey(s, charCode, (s->Right & 0xFF))) { g->Rotation &= ~RIGHT; } if (SettingsIsEquivalentKey(s, charCode, (s->Up & 0xFF))) { g->Rotation &= ~UP; } if (SettingsIsEquivalentKey(s, charCode, (s->Down & 0xFF))) { g->Rotation &= ~DOWN; } if (SettingsIsEquivalentKey(s, charCode, (s->Forward & 0xFF)) || SettingsIsEquivalentKey(s, charCode, (s->Backward & 0xFF))) { g->Direction &= ~(FORWARDS | BACKWARDS); } if (SettingsIsEquivalentKey(s, charCode, (s->Brake & 0xFF))) { g->Direction &= ~STOP; } if (SettingsIsEquivalentKey(s, charCode, (s->Bullet & 0xFF))) { g->world.Player.Firing = 0; } return eventNotHandledErr; } static pascal OSStatus AppActivated(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent, theEvent) VGame * g; g = (VGame *) userData; SetEventLoopTimerNextFireTime(g->timerRef, (kEventDurationSecond / 120.0)); ResumeGame(g); 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); ShowCursor(); 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); SetQDGlobalsRandomSeed(TickCount()); InitSettings(&g->Settings); InitMenu(&g->m); InitWindow(&g->w); InitInterface(&g->Interface, &g->w, g); GetSoundManager(); /* Make sure SM is inited */ eventType.eventClass = kEventClassWindow; eventType.eventKind = kEventWindowActivated; InstallWindowEventHandler(g->w.TheWindow, NewEventHandlerUPP(AppActivated), 1, &eventType, g, NULL); eventType.eventClass = kEventClassWindow; eventType.eventKind = kEventWindowDeactivated; InstallWindowEventHandler(g->w.TheWindow, NewEventHandlerUPP(AppDeactivated), 1, &eventType, g, NULL); g->Status = MENU; SetOrtho(&g->w); g->w.quitOnClose = true; g->lastTime = GetCurrentEventTime(); g->slop = 0.0; g->Paused = false; g->ModeFade = 0.0; 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); CleanUpSettings(&g->Settings); } void SwitchMode(VGame * g, int Mode) { int previousMode; previousMode = g->Status; g->Status = Mode; if (Mode == MENU && previousMode != MENU) { SetOrtho(&g->w); ShowCursor(); CleanUpWorld(&g->world); CleanUpConsole(&g->world.Console); } else if ((Mode & PLAYING) && !(previousMode & PLAYING)) { SetPerspective(&g->w); if (g->w.IsFullScreen) HideCursor(); InitConsole(&g->world.Console, &g->world.Player, &g->FramesPerSecond); InitWorld(&g->world); g->Direction = STATIONARY; g->Rotation = STATIONARY; g->lastTime = GetCurrentEventTime(); g->Paused = false; g->Frames = 0; g->FramesPerSecond = -1; g->FrameTimer = TickCount(); } g->ModeFade = 0.0; }