This is ActorMgr.m in view mode; [Download] [Up]
#import "ActorMgr.h" #import "Thinker.h" #import "Ship.h" #import "Asteroid.h" #import "CacheManager.h" #import "Scenario.h" #import "GameInfo.h" #import "ActorMatrix.h" #import "KeyTimer.h" int level; id keyTimerList; extern BOOL pauseState; @implementation Object (actorMgrAdditions) - (BOOL) addToEmployedList:dude { return YES; } @end @implementation ActorMgr - init { [super init]; employedList = [[List allocFromZone:[self zone]] init]; retireList = [[List allocFromZone:[self zone]] init]; goodList = [[List allocFromZone:[self zone]] init]; badList = [[List allocFromZone:[self zone]] init]; destroyAllList = [[List allocFromZone:[self zone]] init]; keyTimerList = [[List allocFromZone:[self zone]] init]; requestedLevel = -1; return self; } - createCollisionLists { Actor *act; int i, count = [employedList count]; for (i=0; i<count; i++) { act = (Actor *)[employedList objectAt:i]; if ((act->x > gx + collisionDistance*xOffset) || (act->x < gx - collisionDistance*xOffset) || (act->y > gy + collisionDistance*yOffset) || (act->y < gy - collisionDistance*yOffset) || !act->employed) continue; switch((int)(act->alliance)) { case GOOD: [goodList addObject:act]; break; case EVIL: [badList addObject:act]; break; case DESTROYALL: [destroyAllList addObject:act]; break; // these will be collided twice against destroyall actors case GOODNBAD: [goodList addObject:act]; [badList addObject:act]; break; } } return self; } - doCollisions { int i, j, count, count2; Actor *actor1, *actor2; id list1=nil, list2=nil; COLLISION_PARADIGM how2collide; how2collide = [scenario collisionParadigm]; if (how2collide == GOOD_V_EVIL) { int k; [self createCollisionLists]; for (k=0; k<3; k++) { switch (k) { case 0: list1 = destroyAllList; list2 = goodList; break; case 1: list1 = destroyAllList; list2 = badList; break; case 2: list1 = goodList; list2 = badList; break; } count = [list1 count]; count2 = [list2 count]; for (i=0; i<count; i++) for (j=0; j<count2; j++) { actor1 = (Actor *)[list1 objectAt:i]; actor2 = (Actor *)[list2 objectAt:j]; if (actorsCollide(actor1,actor2)) // if ([actor1 collideWith:actor2]) { BOOL h1, h2; h1 = [actor2 doYouHurt:actor1]; h2 = [actor1 doYouHurt:actor2]; if (h1) [actor1 performCollisionWith:actor2]; if (h2) [actor2 performCollisionWith:actor1]; } } } } else if (how2collide == ALL_V_ALL) { // unoptimized, collide all objects against each other count = [employedList count]; for (i=0; i<count-1; i++) for (j=i+1; j<count; j++) { actor1 = (Actor *)[employedList objectAt:i]; actor2 = (Actor *)[employedList objectAt:j]; if (actorsCollide(actor1,actor2)) // if ([actor1 collideWith:actor2]) { BOOL h1, h2; h1 = [actor2 doYouHurt:actor1]; h2 = [actor1 doYouHurt:actor2]; if (h1) [actor1 performCollisionWith:actor2]; if (h2) [actor2 performCollisionWith:actor1]; } } } else { // no collision paradigm recognized } return self; } - makeActorsPerform:(SEL)action { [employedList performInOrder:action]; return self; } - oneStep { int i, count; Actor *actor1; if (requestedLevel >= 0) { [self _createLevel:requestedLevel]; [[gameList objectAt: gameIndex] setLevel:requestedLevel]; requestedLevel = -1; } [keyTimerList performInOrder:@selector(preOneStep)]; [employedList performInOrder:@selector(oneStep)]; if (gameStatus == GAME_RUNNING) [collider doCollisions]; // retire actors as necessary count = [retireList count]; for (i=0; i<count; i++) { actor1 = (Actor *)[retireList objectAt:i]; if (!actor1->employed) [employedList removeObject:actor1]; } [retireList empty]; [goodList empty]; [badList empty]; [destroyAllList empty]; [employedList performInOrder:@selector(scheduleDrawing)]; [keyTimerList performInOrder:@selector(postOneStep)]; return self; } - requestLevel:(int)lev { requestedLevel = lev; return self; } // This method begins with an underbar because it's not safe for // actors to call it in the midst of the animation cycle. - _createLevel:(int)lev { [employedList performInOrder:@selector(retire)]; [employedList empty]; [retireList empty]; if (lev == 0) { lev = 1; if ([scenario respondsTo:@selector(newGame)]) [scenario newGame]; } [scenario _createLevel:lev]; level = lev; if ([scenario respondsTo:@selector(collisionDelegate)]) collider = [scenario collisionDelegate]; else collider = self; [mainView display]; [cacheMgr eraseCache]; return self; } - (Actor *) newActor:(int)actorType for:sender tag:(int)tag { List *theList; Actor *theActor = nil; int i, count; BOOL found = NO; theList = [(id)actorType instanceList]; count = [theList count]; for (i=0; i<count; i++) { theActor = (Actor *)[theList objectAt:i]; if (!(theActor->employed)) { found = YES; break; } } if (!found) { id myClass = (id)actorType; theActor = [[myClass allocFromZone:[self zone]] init]; } [theActor activate:sender :tag]; [scenario didActivate:theActor]; if ([sender addToEmployedList:theActor]) [employedList addObjectIfAbsent:theActor]; return theActor; } - destroyActor:(Actor *)theActor { if (theActor && (theActor->employed)) { [theActor retire]; [scenario didRetire:theActor]; [retireList addObject: theActor]; } return self; } - draw { [employedList performInOrder:@selector(calcDrawRect)]; [employedList performInOrder:@selector(draw)]; return self; } - setGameStatus:(GAME_STATUS)gs { id thinker = [NXApp delegate]; gameStatus = gs; switch (gameStatus) { case GAME_RUNNING: [thinker setPauseState:(pauseState & ~(16 | 32))]; break; case GAME_PAUSED: [thinker setPauseState:(pauseState | 16)]; break; case GAME_DYING: break; case GAME_DEAD: [thinker setPauseState:(pauseState | 32)]; break; } [[gameList objectAt: gameIndex] setStatus:gameStatus]; return self; } - (GAME_STATUS)gameStatus { return gameStatus; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.