This is Thinker.m in view mode; [Download] [Up]
#import "Thinker.h" #import "BackView.h" #import "DisplayManager.h" #import "CacheManager.h" #import "ActorMgr.h" #import "SoundMgr.h" #import "Xoxeroids.h" #import "psfuncts.h" #import "EKProgressView.h" #import <drivers/event_status_driver.h> @implementation Thinker unsigned timeInMS, lastTimeInMS, obscureTime; float timeScale; float maxTimeScale; float collisionDistance; id actorMgr, displayMgr, cacheMgr, soundMgr; id scenario; id mainView; id abackView; id gcontentView; id gameList; int gameIndex; id sceneOneStepper; BOOL pauseState; BOOL fullScreen; BOOL keepLooping; BOOL obscureMouse; NXEventHandle eventhandle; double oldKeyThreshold; int BULLET1SND, BULLET2SND, EXP1SND, EXP2SND, EXP3SND, SHIPSND, WARPSND, FUTILITYSND; static unsigned currentTimeInMs() { struct timeval curTime; gettimeofday (&curTime, NULL); return (curTime.tv_sec) * 1000 + curTime.tv_usec / 1000; } NXZone *scenarioZone, *bundleZone; - init { [super init]; imageNames = [[List alloc] init]; imageRequestor = [[List alloc] init]; soundsToCache = [[Storage allocFromZone:[self zone]] initCount:8 elementSize: sizeof(int) description: @encode(int)]; return self; } - appDidInit:sender { NXZone *actorZone, *displayZone; id commonBundle; char path[1024]; srandom(time(0)); timeInMS = lastTimeInMS = currentTimeInMs(); eventhandle = NXOpenEventStatus(); oldKeyThreshold = NXKeyRepeatThreshold(eventhandle); NXSetKeyRepeatThreshold(eventhandle, 300.0); [self createTimer]; mainView = abackView = backView; gameWindow = littleWindow; gcontentView = [littleWindow contentView]; [nullInfoBox getFrame: &inspectorFrame]; actorZone = NXCreateZone(vm_page_size, vm_page_size, YES); displayZone = NXCreateZone(vm_page_size, vm_page_size, YES); scenarioZone = NXCreateZone(vm_page_size, vm_page_size, YES); bundleZone = NXCreateZone(vm_page_size, vm_page_size, YES); actorMgr = [[ActorMgr allocFromZone:actorZone] init]; displayMgr = [[DisplayManager allocFromZone:displayZone] init]; cacheMgr = [[CacheManager allocFromZone:displayZone] init]; [self getSoundSetting]; [self setupGameBrowser]; [[NXBundle mainBundle] getPath:path forResource:"CommonEffects" ofType:"XoXo"]; commonBundle = [[NXBundle allocFromZone:bundleZone] initForDirectory:path]; [[[commonBundle classNamed:"CommonStuff"] allocFromZone:scenarioZone] init]; [self selectGame:nil]; [[invisibleInfoBox window] makeKeyAndOrderFront:self]; [littleWindow makeFirstResponder:mainView]; [littleWindow setBackgroundGray:NX_BLACK]; [littleWindow makeKeyAndOrderFront:self]; [self newGame:self]; return self; } void timedEntryFunction (DPSTimedEntry timedEntry, double timeNow, void *theObject) { [(id)theObject doOneStepLoop]; } - createTimer { if (!timerValid) { timerValid = YES; timer = DPSAddTimedEntry(0.02, &timedEntryFunction, self, NX_BASETHRESHOLD); } return self; } - removeTimer { if (timerValid) DPSRemoveTimedEntry (timer); timerValid = NO; return self; } - doOneStepLoop { NXEvent dummyEvent, *pEvent; [mainView lockFocus]; keepLooping = YES; do { [self oneStep]; while ([NXApp peekNextEvent:NX_ALLEVENTS into:&dummyEvent waitFor:0 threshold:NX_BASETHRESHOLD]) { if ((dummyEvent.type & (NX_KEYDOWNMASK|NX_KEYUPMASK)) && (!(dummyEvent.flags & NX_COMMANDMASK))) { // if it's a key event other than a command key, we save // ourselves the overhead of a focus change pEvent = [NXApp getNextEvent: NX_ALLEVENTS waitFor:0 threshold:NX_BASETHRESHOLD]; [NXApp sendEvent: pEvent]; } else { keepLooping = NO; break; } } } while (timerValid && keepLooping); [mainView unlockFocus]; return self; } - justOneStep { [mainView lockFocus]; // [self oneStep]; { // new behavior to replace onestep above [actorMgr makeActorsPerform:@selector(erase)]; [cacheMgr oneStep]; [displayMgr oneStep]; } [mainView unlockFocus]; return self; } - oneStep { float tinterval; lastTimeInMS = timeInMS; timeInMS = currentTimeInMs(); tinterval = timeInMS - lastTimeInMS; if (obscureMouse && (timeInMS > obscureTime)) { PSobscurecursor(); obscureTime = timeInMS + 5000; } if (tinterval < 1) tinterval = 1; timeScale = tinterval/100; if (timeScale > maxTimeScale) timeScale = maxTimeScale; [soundMgr oneStep]; [sceneOneStepper oneStep]; // notify the scenario, if it cares [actorMgr oneStep]; [cacheMgr oneStep]; [displayMgr oneStep]; NXPing (); // Synchronize postscript for smoother animation return self; } // This should return a float between 0 and 1 float frandom() { float val = (random() & 0x7fffffff); val /= 0x7fffffff; return val; } float randBetween(float a, float b) { float val, scale, t; if (a > b) { t = a; a = b; b = t; } scale = (b-a); val = scale * frandom(); return (a + val); } - toggleFullScreen:sender; { [self setFullScreen: !fullScreen]; return self; } - setFullScreen:(BOOL)flag { if (flag) { NXRect r={{0, 0}}; if ([self bigWindowOK]) { [NXApp getScreenSize:&(r.size)]; [self createBigWindowIfNecessary]; tweakWindow([bigWindow windowNum], 40); [self installGameViewsIntoWindow:bigWindow]; [bigWindow placeWindow:&r]; [bigWindow makeKeyAndOrderFront:self]; [bigWindow display]; } else flag = NO; } else { [bigWindow orderOut:self]; [self installGameViewsIntoWindow:littleWindow]; [littleWindow makeKeyAndOrderFront:self]; [littleWindow display]; } fullScreen = flag; return self; } - toggleUserPause:sender { [self setPauseState: (pauseState ^ 1)]; return self; } - setPauseState:(BOOL)flag { if (flag) [self removeTimer]; else [self createTimer]; pauseState = flag; return self; } - appDidHide:sender { [self setPauseState:(pauseState | 2)]; return self; } - appDidUnhide:sender { [self setPauseState:(pauseState & ~2)]; return self; } - appDidBecomeActive:sender { [self setPauseState:(pauseState & ~4)]; NXSetKeyRepeatThreshold(eventhandle, 300.0); return self; } - appDidResignActive:sender { [self setPauseState:(pauseState | 4)]; NXSetKeyRepeatThreshold(eventhandle, oldKeyThreshold); return self; } - windowDidBecomeKey:sender { if (sender == littleWindow || sender == bigWindow) [self setPauseState:(pauseState & ~8)]; return self; } - windowDidResignKey:sender { if (sender == littleWindow || sender == bigWindow) [self setPauseState:(pauseState | 8)]; return self; } - windowDidMove:sender { if ((sender == littleWindow) && ([scenario respondsTo:@selector(windowDidMove:)])) [scenario windowDidMove:sender]; return self; } - appWillTerminate:sender { NXSetKeyRepeatThreshold(eventhandle, oldKeyThreshold); return self; } - newGame:sender { [self setPauseState:(pauseState & ~1)]; [actorMgr setGameStatus:GAME_RUNNING]; [actorMgr requestLevel:0]; return self; } // Image Loading status stuff was borrowed from Erik Kay, // slightly munged for xox by sam // add an image filename to the image resource list - addImageResource:(const char *)r for:whom { //! we cheat here a bit and take advantage of the fact that a list just //! takes id's which are pointers, and therefore, character pointers work //! just fine too. Probably not the best thing to do... [imageNames addObject:(id)NXCopyStringBuffer(r)]; [imageRequestor addObject:whom]; return self; } - addSoundResource:(int)sound { [soundsToCache addElement:&sound]; return self; } // preload resources for the app - loadResources { int i, count, progress = 0; char *str; id whom; int soundndx; // actually load the images count = [imageNames count]; for (i = 0; i < count; i++) { str = (char *)[imageNames objectAt:i]; whom = [imageRequestor objectAt:i]; [[statusText setStringValue:str] display]; [whom cacheImage:str]; free(str); // update the progress bar progress++; [progressView setProgress:progress]; NXPing(); } // convert/cache the sounds count = [soundsToCache count]; for (i = 0; i < count; i++) { soundndx = *(int *)[soundsToCache elementAt:i]; str = (char *)[soundMgr soundName:soundndx]; if (str) { [[statusText setStringValue:str] display]; [soundMgr cacheSound:soundndx]; } // update the progress bar progress++; [progressView setProgress:progress]; NXPing(); } [imageNames empty]; [imageRequestor empty]; [soundsToCache empty]; return self; } @end @implementation List (XoxAdditions) - performInOrder:(SEL)aSelector { int i, count = numElements; for (i=0; i<count; i++) [dataPtr[i] perform: aSelector]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.