/Volumes/Plantain/MyDocuments/Projects/MacTrek/MacTrek/Painter/PainterFactory.m

00001 //
00002 //  PainterFactory.m
00003 //  MacTrek
00004 //
00005 //  Created by Aqua on 19/06/2006.
00006 //  Copyright 2006 __MyCompanyName__. All rights reserved.
00007 //
00008 
00009 #import "PainterFactory.h"
00010 
00011 @implementation PainterFactory
00012 
00013 NSPoint backGroundStartPoint;
00014 LLTrigonometry *trigonometry;
00015 LLShapes *shapes;
00016 int alert = PLAYER_GREEN;
00017 static NSBezierPath *line = nil;
00018 static NSBezierPath *dashedLine = nil; 
00019 NSDictionary *normalStateAttribute;
00020 
00021 #define ALERT_FILTER (PLAYER_GREEN | PLAYER_YELLOW | PLAYER_RED)
00022 
00023 - (id) init {
00024     self = [super init];
00025     if (self != nil) {
00026         // init vars
00027         backGroundStartPoint.x = 0;
00028         backGroundStartPoint.y = 0;
00029         debugLabels = NO;
00030         simple = NO;
00031         
00032         //create helpers
00033         trigonometry = [LLTrigonometry defaultInstance];
00034         shapes = [[LLShapes alloc] init];
00035         universe = [Universe defaultInstance];
00036         line = [[NSBezierPath alloc] init];        
00037         dashedLine = [[NSBezierPath alloc] init];
00038         float dash = { 1.0, 3.0 };
00039         [dashedLine setLineDash: dash count: 2 phase: 0.0]; 
00040         
00041         normalStateAttribute =[[NSDictionary dictionaryWithObjectsAndKeys:
00042         [NSColor whiteColor],NSForegroundColorAttributeName,nil] retain];
00043         // initial cache is in seperate thread
00044         [NSThread detachNewThreadSelector:@selector(cacheImagesInSeperateThread:) toTarget:self withObject:nil];
00045 
00046     }
00047     return self;
00048 }
00049 
00050 - (void) setSimplifyDrawing:(bool)simpleDraw {
00051     simple = simpleDraw;
00052 }
00053 
00054 - (void) setDebugLabels:(bool)debug {
00055     debugLabels = debug;
00056 }
00057 
00058 - (bool) debugLabels {
00059     return debugLabels;
00060 }
00061 
00062 - (int) maxScale {
00063     return 400; // 10* netrek zoom out
00064 }
00065 
00066 - (int) minScale {
00067     return 2;   // netrek game grid
00068 }
00069 
00070 // overrule in subclass to cache the images
00071 - (void) cacheImages {
00072     // takes about 5 seconds..
00073     sleep(2);
00074 }
00075 
00076 - (void) cacheImagesInSeperateThread:(id)sender {
00077     
00078     // create a private pool for this thread
00079     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
00080     
00081     NSLog(@"PainterFactory.cacheImagesInSeperateThread: start running");
00082     [self cacheImages];
00083     NSLog(@"PainterFactory.cacheImagesInSeperateThread: complete");
00084     
00085     [notificationCenter postNotificationName:@"PF_IMAGES_CACHED"];
00086     
00087     // release the pool
00088     [pool release];
00089 }
00090 
00091 - (NSSize) backGroundImageSize {
00092     return PF_DEFAULT_BACKGROUND_IMAGE_SIZE;
00093 }
00094 
00095 - (NSColor*) colorForTeam:(Team*)team {
00096     return [team colorForTeam];
00097 }
00098 
00099 - (NSPoint) centreOfRect:(NSRect)aRect {
00100     NSPoint result = aRect.origin;
00101     result.x += aRect.size.width / 2;
00102     result.y += aRect.size.height / 2;
00103     return result;
00104 }
00105 
00106 - (NSPoint) gamePointFromViewPoint:(NSPoint)point withMeInViewRect:(NSRect)bounds withScale:(int)scale {
00107      
00108     // our game pos
00109     NSPoint centrePos = [[universe playerThatIsMe] predictedPosition];
00110     return [self gamePointFromViewPoint:point viewRect:bounds gamePosInCentreOfView:centrePos withScale:scale];
00111 }
00112 
00113 - (NSPoint) gamePointFromViewPoint:(NSPoint)point viewRect:(NSRect)bounds 
00114              gamePosInCentreOfView:(NSPoint)centrePos withScale:(int)scale {
00115     
00116     // we are in the center of our view, thus bounds / 2
00117     // get the relative position in the view
00118     int deltaX = point.x - (bounds.size.width / 2);
00119     int deltaY = point.y - (bounds.size.height / 2);
00120 
00121     
00122     // the point is relative to me with scaling
00123     NSPoint gamePoint;
00124     gamePoint.x = centrePos.x + deltaX*scale;
00125     gamePoint.y = centrePos.y + deltaY*scale;
00126     
00127     return gamePoint;    
00128 }
00129 
00130 // warning: this does not effect the origin
00131 // for that i need to know the view bounds
00132 - (NSSize)  gameSizeFromViewSize:(NSSize)rect withScale:(int)scale {
00133     
00134     NSSize size;
00135     
00136     size.height = rect.height*scale;
00137     size.width  = rect.width*scale;
00138     
00139     return size;
00140 }
00141 
00142 // special function around me as a player
00143 - (NSRect) gameRectAroundMeForViewRect:(NSRect)bounds withScale:(int)scale {
00144     // our game pos
00145     NSPoint centrePos = [[universe playerThatIsMe] predictedPosition];
00146     
00147     return [self gameRectAround:centrePos forView:bounds withScale:scale];
00148 }
00149     
00150 - (NSRect) gameRectAround:(NSPoint)gamePoint forView:(NSRect)bounds withScale:(int)scale {
00151             
00152     // optimise a little
00153     static NSRect result;
00154     static NSRect previousBounds;
00155     static int previousScale;
00156     /* // $$ only if i did not move !!!!
00157     if (([trigonometry rect:bounds isEqualToRect:previousBounds]) &&
00158         (scale == previousScale)) {
00159         return result;
00160     }*/
00161     previousScale = scale;
00162     previousBounds = bounds;
00163     
00164     // resize the bounds to the right scale
00165     result.size = [self gameSizeFromViewSize:bounds.size withScale:scale];
00166     
00167     // the view frame starts at 0,0 but that is not the origin of
00168     // the game view
00169     result.origin = [self gamePointFromViewPoint:bounds.origin
00170                                         viewRect:bounds 
00171                            gamePosInCentreOfView:gamePoint 
00172                                        withScale:scale];  
00173     return result;
00174 }
00175 
00176 // warning: this does not effect the origin
00177 // for that i would need to know the view bounds
00178 - (NSSize)  viewSizeFromGameSize:(NSSize)rect withScale:(int)scale{
00179     
00180     NSSize size;
00181     
00182     size.height = rect.height / scale;
00183     size.width  = rect.width / scale;
00184     
00185     return size;
00186 }
00187 
00188 - (NSPoint) viewPointFromGamePoint:(NSPoint)point withMeInViewRect:(NSRect)bounds withScale:(int)scale {    
00189     // our game pos
00190     NSPoint centrePos = [[universe playerThatIsMe] predictedPosition];
00191     return [self viewPointFromGamePoint:point viewRect:bounds gamePosInCentreOfView:centrePos withScale:scale];
00192 }
00193 
00194 - (NSPoint) viewPointFromGamePoint:(NSPoint)point viewRect:(NSRect)bounds 
00195              gamePosInCentreOfView:(NSPoint)centrePos withScale:(int)scale {
00196     // offset to the other point
00197     int deltaX = point.x - centrePos.x;
00198     int deltaY = point.y - centrePos.y;
00199     
00200     // we are in the center of our view, thus bounds / 2
00201     // the point is relative to me with scaling
00202     NSPoint viewPoint;
00203     viewPoint.x = (bounds.size.width / 2) + deltaX / scale;
00204     viewPoint.y = (bounds.size.height / 2) + deltaY / scale;
00205     
00206     return viewPoint;    
00207 }
00208 
00209 - (NSRect) rectWithHeight:(int)height width:(int)width centerPoint:(NSPoint)centerGravity {
00210     
00211     NSRect result;
00212     
00213     result.size.width = width;
00214     result.size.height = height;
00215     result.origin.x = centerGravity.x - width / 2;
00216     result.origin.y = centerGravity.y - height / 2;
00217     
00218     return result;
00219 }
00220 
00221 
00222 - (void) drawAlertBorder:(NSRect) bounds forMe:(Player *)me {
00223     
00224     // Change border color to signify alert status
00225     if (alert != ([me flags] & ALERT_FILTER)) {
00226         alert = ([me flags] & ALERT_FILTER);
00227         // probably START on change to RED, abort on all other
00228         [notificationCenter postNotificationName:@"PL_ALERT_STATUS_CHANGED" userInfo:[NSNumber numberWithInt:alert]]; 
00229     }
00230     if ([me flags] & ALERT_FILTER) {
00231         switch (alert) {
00232                         case PLAYER_GREEN :
00233                 [[NSColor greenColor] set];
00234                                 break;
00235                         case PLAYER_YELLOW :
00236                 [[NSColor yellowColor] set];
00237                                 break;
00238                         case PLAYER_RED :
00239                 [[NSColor redColor] set];
00240                                 break;
00241         }               
00242         // bug in Aqua?
00243         bounds.size.height -= 1;
00244         // draw the border
00245         [line removeAllPoints];
00246         [line appendBezierPathWithRect:bounds];
00247         float oldWidth = [line lineWidth]; // remember
00248         [line setLineWidth: PF_ALERT_BORDER_WIDTH];
00249         [line stroke];
00250         [line setLineWidth:oldWidth]; // restore
00251     }
00252     
00253 }
00254 
00255 - (void) drawBackgroundInRect:(NSRect) drawingBounds ofViewBounds:(NSRect)viewBounds forMe:(Player*) me {
00256     
00257     // get the size of the stamp
00258     NSSize backGroundImageSize = [self backGroundImageSize];
00259     // use a local var so we can debug...
00260     NSPoint startPoint = backGroundStartPoint;
00261     
00262     // $$ scale the stars (nah don't do that)
00263     
00264     // move the start point away  in the oposite dir, based on my speed
00265     float course = [me course];
00266     
00267     startPoint.x -= cos(course) * (float)[me speed] / 4.0f;
00268     startPoint.y -= sin(course) * (float)[me speed] / 4.0f;
00269     
00270     //NSLog(@"### c %f sp (%f, %f)", course, startPoint.x, startPoint.y);
00271     
00272     // repeat the bitmap if it shifted completely out of view
00273     if(startPoint.x < -backGroundImageSize.width) {
00274         startPoint.x += backGroundImageSize.width;
00275     }
00276     else if(startPoint.x > 0.0f) {
00277         startPoint.x -= backGroundImageSize.width;
00278     } 
00279     if(startPoint.y < -backGroundImageSize.height) {
00280         startPoint.y += backGroundImageSize.height;
00281     }
00282     else if(startPoint.y > 0.0f) {
00283         startPoint.y -= backGroundImageSize.height;     
00284     }
00285     
00286     // paint the image all over the the bounds that have been given for view
00287     NSRect targetArea;
00288     // $$ do not scale the stars here?
00289     targetArea.size = backGroundImageSize;
00290     // go and paint 
00291     // $$ i think bounds should have been viewBounds and then check if the origin is in the drawing bounds
00292     for(int y = (int)startPoint.y; y < viewBounds.size.height; y += backGroundImageSize.height) {
00293         for(int x = (int)startPoint.x; x < viewBounds.size.width; x += backGroundImageSize.width) {
00294             targetArea.origin.x = x;
00295             targetArea.origin.y = y;
00296             NSPoint otherEnd = NSMakePoint(x+backGroundImageSize.width,y+backGroundImageSize.height);
00297             
00298             // is the image in the drawing rectangle?
00299             if ((!NSPointInRect(targetArea.origin, drawingBounds)) &&
00300                 (!NSPointInRect(otherEnd,drawingBounds))) {
00301                 continue;
00302             }
00303             
00304             [self drawBackgroundImageInRect: targetArea];
00305         }
00306     } 
00307     
00308     backGroundStartPoint = startPoint;
00309 }
00310 
00311 - (void) drawGalaxyEdgesInRect:(NSRect) drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00312     
00313     // the line color
00314     [[NSColor brownColor] set];
00315     
00316     // orgin in view coordinates
00317     NSPoint upperLeft = [self viewPointFromGamePoint:NSMakePoint(0, 0) 
00318                                             viewRect:viewBounds
00319                                gamePosInCentreOfView:[self centreOfRect:gameBounds]
00320                                            withScale:scale];
00321     NSPoint lowerRight = [self viewPointFromGamePoint:NSMakePoint(UNIVERSE_PIXEL_SIZE, UNIVERSE_PIXEL_SIZE)
00322                                              viewRect:viewBounds 
00323                                 gamePosInCentreOfView:[self centreOfRect:gameBounds] 
00324                                             withScale:scale];
00325     
00326     // $$ but do we need to draw it ? check with drawingBounds to make sure...
00327     // $$ todo, but it is only a few lines    
00328     
00329     // are we near the north line?
00330     if (gameBounds.origin.y <= 0) {
00331         [line removeAllPoints];
00332         [line moveToPoint:upperLeft];
00333         [line lineToPoint:NSMakePoint(lowerRight.x, upperLeft.y)];
00334         [line stroke];        
00335     }
00336     
00337     // are we near the south line?
00338     if (gameBounds.origin.y + gameBounds.size.height < UNIVERSE_PIXEL_SIZE) {
00339         [line removeAllPoints];
00340         [line moveToPoint:lowerRight];
00341         [line lineToPoint:NSMakePoint(upperLeft.x, lowerRight.y)];
00342         [line stroke];        
00343     }
00344     
00345     // are we near the west line?
00346     if (gameBounds.origin.x <= 0) {       
00347         [line removeAllPoints];
00348         [line moveToPoint:upperLeft];
00349         [line lineToPoint:NSMakePoint(upperLeft.x, lowerRight.y)];
00350         [line stroke];        
00351     }
00352     
00353     // are we near the east line?
00354     if (gameBounds.origin.x + gameBounds.size.width > UNIVERSE_PIXEL_SIZE) {
00355         [line removeAllPoints];
00356         [line moveToPoint:lowerRight];
00357         [line lineToPoint:NSMakePoint(lowerRight.x, upperLeft.y)];
00358         [line stroke];        
00359     }
00360     
00361 }
00362 
00363 - (void)drawPlanetsInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00364     
00365     NSRect planetGameBounds;
00366     NSRect planetViewBounds;
00367     Planet *planet;
00368     NSPoint centreOfGameBounds = [self centreOfRect:gameBounds];
00369     
00370     for (int i = 0; i < UNIVERSE_MAX_PLANETS; i++) {
00371         planet = [universe planetWithId:i];
00372         
00373         // is the planet in the view?
00374         if (!NSPointInRect([planet predictedPosition], gameBounds)) {
00375             continue;
00376         }
00377         
00378         // get the rect around the planet in game coordinates
00379         planetGameBounds.origin = [planet predictedPosition];
00380         planetGameBounds.size = [planet size];
00381         // offset the origin to the upper left
00382         planetGameBounds.origin.x -= planetGameBounds.size.width / 2;
00383         planetGameBounds.origin.y -= planetGameBounds.size.height / 2;
00384         
00385         // convert to the view 
00386         planetViewBounds.size = [self viewSizeFromGameSize: planetGameBounds.size withScale: scale];
00387         planetViewBounds.origin = [self viewPointFromGamePoint: planetGameBounds.origin 
00388                                                       viewRect:viewBounds
00389                                          gamePosInCentreOfView:centreOfGameBounds
00390                                                      withScale:scale];
00391         
00392         // is the planet in the drawing rectangle?
00393         if (!NSPointInRect(planetViewBounds.origin, drawingBounds)) {
00394             continue;
00395         }
00396         
00397         // draw it
00398         [self drawPlanet: planet inRect:planetViewBounds];
00399         
00400         // draw the name
00401         [self drawLabelForPlanet:planet belowRect:planetViewBounds];
00402     }
00403     
00404 }
00405 
00406 - (void)drawPlayersInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds  withScale:(int)scale {
00407     
00408     NSRect playerGameBounds;
00409     NSRect playerViewBounds;
00410     Player *player;
00411     Player *me = [universe playerThatIsMe];
00412     NSPoint centreOfGameBounds = [self centreOfRect:gameBounds];
00413     
00414     for (int i = 0; i < UNIVERSE_MAX_PLAYERS; i++) {
00415         player = [universe playerWithId:i];
00416         
00417         // is the player in the view?
00418         if (!NSPointInRect([player predictedPosition], gameBounds)) {
00419             continue;
00420         }
00421         
00422         // see if this player is active
00423         if (([player status] != PLAYER_ALIVE && [player status] != PLAYER_EXPLODE) || ([player flags] & PLAYER_OBSERV) != 0) {
00424             continue;
00425         }
00426         
00427         // handle the drawing of cloak phase frames
00428         if (([player flags] & PLAYER_CLOAK) != 0) {
00429             if ([player cloakPhase] < (PLAYER_CLOAK_PHASES - 1)) {
00430                 if([player isMe] && [player cloakPhase] == 0) {
00431                     [notificationCenter postNotificationName:@"PL_CLOAKING" userInfo:[NSNumber numberWithBool:YES]];                   
00432                 }
00433                 [player increaseCloakPhase];
00434             }
00435         }
00436         else if ([player cloakPhase] > 0) {
00437             if ([player cloakPhase] == PLAYER_CLOAK_PHASES - 1) {
00438                 // $$ do not report others YET
00439                 if ([player isMe]) {
00440                     [notificationCenter postNotificationName:@"PL_UNCLOAKING" userInfo:[NSNumber numberWithBool:NO]];
00441                 }
00442             }
00443             else {
00444                 // $$ do not report others YET
00445                 //[notificationCenter postNotificationName:@"PL_CLOAKING" userInfo:[NSNumber numberWithBool:YES]];
00446             }
00447             [player decreaseCloakPhase];
00448         }
00449 
00450         // get the rect around the player in game coordinates
00451         playerGameBounds.origin = [player predictedPosition];
00452         playerGameBounds.size = [[player ship] size];
00453         // offset the origin to the upper left
00454         playerGameBounds.origin.x -= playerGameBounds.size.width / 2;
00455         playerGameBounds.origin.y -= playerGameBounds.size.height / 2;
00456         
00457         // convert to the view         
00458         playerViewBounds.size = [self viewSizeFromGameSize: playerGameBounds.size withScale: scale];
00459         playerViewBounds.origin = [self viewPointFromGamePoint: playerGameBounds.origin 
00460                                                       viewRect:viewBounds
00461                                          gamePosInCentreOfView:centreOfGameBounds
00462                                                      withScale:scale];
00463         
00464         // is the player in the drawing rectangle?
00465         if (!NSPointInRect(playerViewBounds.origin, drawingBounds)) {
00466             continue;
00467         }
00468         
00469         // draw it
00470         [self rotateAndDrawPlayer: player inRect:playerViewBounds];
00471     
00472         // draw name
00473         [self drawLabelForPlayer:player belowRect:playerViewBounds];
00474         
00475         if (simple) {   // in simple mode we do not draw any weapons
00476             continue;
00477         }
00478         
00479         // calculate in percent and draw shields
00480         if ([player flags] & PLAYER_SHIELD) {
00481             float shieldStrenght = 100.0;
00482             if ([player isMe]) {
00483                 shieldStrenght = [player shield] * 100 / [[player ship] maxShield];
00484             }
00485             [self drawShieldWithStrenght: shieldStrenght inRect:playerViewBounds];            
00486         }
00487         
00488         // safe this value, we may need it again
00489         NSPoint playerPositionInView = [self viewPointFromGamePoint: [player predictedPosition] 
00490                                                            viewRect:viewBounds
00491                                               gamePosInCentreOfView:centreOfGameBounds
00492                                                           withScale:scale];
00493         
00494         
00495         // $$ should i not do something similar for the explosion phases?
00496         if (([player status] == PLAYER_EXPLODE) &&
00497             ([player previousStatus] != PLAYER_EXPLODE)) {
00498             // the player started exploding
00499             [notificationCenter postNotificationName:@"PL_EXPLODE_PLAYER" userInfo:player];
00500         }
00501         [player setPreviousStatus:[player status]];
00502         
00503         // check shield raised, lowered
00504         if (([player flags] & PLAYER_SHIELD) &&
00505             !([player previousFlags] & PLAYER_SHIELD)) {
00506             // the player raised shields
00507             [notificationCenter postNotificationName:@"PL_SHIELD_UP_PLAYER" userInfo:player];
00508         }         
00509         if (!([player flags] & PLAYER_SHIELD) &&
00510             ([player previousFlags] & PLAYER_SHIELD)) {
00511             // the player lowered shields
00512             [notificationCenter postNotificationName:@"PL_SHIELD_DOWN_PLAYER" userInfo:player];
00513         } 
00514         
00515         [player setPreviousFlags:[player flags]];        
00516         
00517         // draw the players phaser
00518         Phaser *phaser = [universe phaserWithId:[player phaserId]];
00519         NSPoint phaserEndPoint;
00520         
00521         if ([phaser status] != PHASER_FREE) {
00522             if([phaser previousStatus] == PHASER_FREE) { // from free to not free
00523                 if ([player isMe]) {
00524                     [notificationCenter postNotificationName:@"PL_MY_PHASER_FIRING" userInfo:phaser];
00525                 } else {
00526                     [notificationCenter postNotificationName:@"PL_OTHER_PHASER_FIRING" userInfo:phaser];
00527                 }                
00528             }
00529             
00530             float compute;
00531             switch ([phaser status]) { 
00532                                 case PHASER_MISS:
00533                                         // Here I will have to compute the end coordinate
00534                                         compute = PHASER_MAX_DISTANCE * ([[player ship] phaserDamage ] / 100.0f);
00535                     // use radian conversion or tri
00536                     //NSLog(@"deg %d rad %f, cos %f, sin %f disx %d disy %d, px %f, py %f", 
00537                     //[phaser course], [phaser dirInRad],
00538                     //      sinf([phaser dirInRad]), cosf([phaser dirInRad]),
00539                     //      (int) (compute * cosf([phaser dirInRad])), (int)(compute * sinf([phaser dirInRad])),
00540                     //      [player predictedPosition].x, [player predictedPosition].y);
00541                                         phaserEndPoint.x = (int)([player predictedPosition].x + (int)(compute * sinf([phaser dirInRad]))); 
00542                     phaserEndPoint.y = (int)([player predictedPosition].y - (int)(compute * cosf([phaser dirInRad]))); // flipped coordinates
00543                                         break;
00544                     
00545                                 case PHASER_HIT2:
00546                                         phaserEndPoint = [phaser predictedPosition];
00547                                         break;
00548                                 default:
00549                     phaserEndPoint = [[phaser target] predictedPosition];
00550                                         break;
00551             }
00552             
00553             NSPoint phaserStartPoint =[player predictedPosition];
00554             // phaser shooting exactly at me?
00555             if (phaserStartPoint.x != phaserEndPoint.x || phaserStartPoint.y != phaserEndPoint.y) {
00556                 if ([phaser status] == PHASER_MISS || (([phaser fuse] % 2) == 0) || [player team] != [me team]) {
00557                     // get the team color so that my phaser will not always be white
00558                     [[self colorForTeam:[player team]] set];
00559                 }
00560                 else {
00561                     [[NSColor whiteColor] set];
00562                 }
00563 
00564                 // project the phaser
00565                 phaserStartPoint = playerPositionInView; // we calculated this before...
00566                 
00567                 phaserEndPoint = [self viewPointFromGamePoint: phaserEndPoint 
00568                                                      viewRect:viewBounds
00569                                         gamePosInCentreOfView:centreOfGameBounds
00570                                                     withScale:scale];
00571                 
00572                 //NSLog(@"PainterFactory.playerPhaser firing at x=%f, y=%f", phaserEndPoint.x, phaserEndPoint.y);
00573                 
00574                 [line removeAllPoints];
00575                 [line moveToPoint:phaserStartPoint];
00576                 [line lineToPoint:phaserEndPoint];
00577                 [line stroke];
00578                 
00579                 // increase the faser duration
00580                 [phaser increaseFuse];
00581                 if([phaser fuse] > [phaser maxfuse]) {
00582                     [phaser setStatus: PHASER_FREE];
00583                 }
00584             }
00585         }
00586         
00587         // update
00588         [phaser setPreviousStatus:[phaser status]];
00589         
00590         // draw tractors/pressors         
00591         // needed?
00592         if(([player flags] & (PLAYER_TRACT | PLAYER_PRESS)) == 0 || [player status] != PLAYER_ALIVE) {
00593             continue;
00594         }
00595         
00596         // hmm no target?
00597         Player *tractee = [player tractorTarget];
00598         if(tractee == nil) {
00599             continue;
00600         }
00601         
00602         // dead target ?
00603         if ([tractee status] != PLAYER_ALIVE) {            
00604             // $$ we can tractor cloaked targets....
00605             //|| ((tractee.flags & PLAYER_CLOAK) != 0 && tractee.cloakphase == (PLAYER_CLOAK_PHASES - 1)) {
00606             continue;
00607             }
00608         
00609         NSPoint tractorStartPoint = playerPositionInView;    // we calculated this before    
00610         NSPoint tractorEndPoint = [self viewPointFromGamePoint: [tractee predictedPosition] 
00611                                                       viewRect:viewBounds
00612                                          gamePosInCentreOfView:centreOfGameBounds
00613                                                      withScale:scale];
00614         if (tractorStartPoint.x == tractorEndPoint.x && tractorStartPoint.y == tractorEndPoint.y) {
00615             continue;
00616         }
00617         
00618         //NSLog(@"PainterFactory.drawPlayers tractor from (%f, %f) to (%f, %f)",
00619         //      tractorStartPoint.x, tractorStartPoint.y,
00620         //      tractorEndPoint.x, tractorEndPoint.y);
00621         
00622         double theta = atan2((double)(tractorEndPoint.x - tractorStartPoint.x), 
00623                              (double)(tractorStartPoint.y - tractorEndPoint.y)) + pi / 2.0;
00624         //double dir = theta / pi * 128; // no need we can work in rad
00625                 
00626         //NSLog(@"PainterFactory.drawPlayers tractor from (%f / %f) to (%f)",
00627         //      ((double)(tractorEndPoint.x - tractorStartPoint.x)), 
00628         //      ((double)(tractorStartPoint.y - tractorEndPoint.y)) + pi / 2.0);
00629 
00630         // $$ fixed the colors here...
00631         if ([player flags] & PLAYER_PRESS) {
00632             [[NSColor purpleColor] set];
00633         } else {
00634             [[NSColor greenColor] set];
00635         }
00636         
00637         NSSize tracteeSize = [self viewSizeFromGameSize: [[tractee ship] size] withScale: scale];
00638         int width  = tracteeSize.width;
00639         int height = tracteeSize.height;
00640         double maxDim = ( width > height ? width : height) / 2.0;
00641         int yOffset = (int)(cos(theta) * maxDim);
00642         int xOffset = (int)(sin(theta) * maxDim);
00643         
00644         //NSLog(@"PainterFactory.drawPlayers tractor tetha %f xOff %d, yOff %d", theta, xOffset, yOffset);
00645         
00646         // draw it
00647         NSPoint p1 = NSMakePoint(tractorEndPoint.x + xOffset, tractorEndPoint.y + yOffset);
00648         NSPoint p2 = NSMakePoint(tractorEndPoint.x - xOffset, tractorEndPoint.y - yOffset);
00649         [dashedLine removeAllPoints];        
00650         [dashedLine moveToPoint:p1];
00651         [dashedLine lineToPoint:tractorStartPoint];
00652         [dashedLine lineToPoint:p2];
00653         [dashedLine stroke];
00654     }    
00655 }
00656 
00657 - (void)drawTorpsInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds  withScale:(int)scale {
00658     
00659     NSRect torpGameBounds;
00660     NSRect torpViewBounds;
00661     Player *player;
00662     NSPoint centreOfGameBounds = [self centreOfRect:gameBounds];
00663     
00664     // check all torps of all players
00665     for (int i = 0; i < UNIVERSE_MAX_PLAYERS; i++) {
00666         player = [universe playerWithId:i];
00667         
00668         NSArray *torps = [player torps];
00669         for (int t = 0; t < [torps count]; t++) {
00670             Torp *torp = [torps objectAtIndex:t];            
00671             
00672             if ([torp status] == TORP_FREE) {
00673                 continue;
00674             }
00675             
00676             // is the torp in the view?
00677             // $$ this does not work because of the zoom,
00678             // should calc torps exceded maxTorpRange instead
00679             if (!NSPointInRect([torp predictedPosition], gameBounds)) {                
00680                 // Call any torps off screen "free" (if owned by other)
00681                 //if ([torp status] == TORP_EXPLODE && ![player isMe]) {
00682                 if (![player isMe]) {
00683                     [player decreaseTorpCount];
00684                 }
00685                 // !! reset the torp status always, to play our sounds
00686                 [torp setStatus: TORP_FREE];
00687                 [torp setPreviousStatus:TORP_FREE];
00688 
00689                 continue;
00690             }            
00691             
00692             // get the rect around the torp in game coordinates
00693             torpGameBounds.origin = [torp predictedPosition];
00694             if ([torp status] == TORP_EXPLODE) {
00695                 torpGameBounds.size = [torp explosionSize];
00696             } else {
00697                 torpGameBounds.size = [torp size];
00698             }
00699             // offset the origin to the upper left
00700             torpGameBounds.origin.x -= torpGameBounds.size.width / 2;
00701             torpGameBounds.origin.y -= torpGameBounds.size.height / 2;
00702             
00703             // convert to the view 
00704             torpViewBounds.size = [self viewSizeFromGameSize: torpGameBounds.size withScale: scale];
00705             torpViewBounds.origin = [self viewPointFromGamePoint: torpGameBounds.origin 
00706                                                         viewRect:viewBounds
00707                                            gamePosInCentreOfView:centreOfGameBounds
00708                                                        withScale:scale];
00709             
00710             // is the player in the drawing rectangle?
00711             if (!NSPointInRect(torpViewBounds.origin, drawingBounds)) {
00712                 continue;
00713             }
00714             
00715             // draw it
00716             [self drawTorp: torp inRect:torpViewBounds];
00717 
00718             // see if we need to fire events
00719             //NSLog(@"PainterFactory.drawTorpsInRect status %d, previous %d", [torp status], [torp previousStatus]);
00720             if (([torp status] == TORP_MOVE) && 
00721                 ([torp previousStatus] != TORP_MOVE)) {                
00722                 if ([player isMe]) {
00723                     [notificationCenter postNotificationName:@"PL_TORP_FIRED_BY_ME" userInfo:torp];
00724                 } else {
00725                     [notificationCenter postNotificationName:@"PL_TORP_FIRED_BY_OTHER" userInfo:torp];
00726                 }
00727             }  
00728             
00729             
00730             if ([torp status] == TORP_EXPLODE) {
00731                 
00732                 if ([torp previousStatus] != TORP_EXPLODE) {
00733                     // it just went boom
00734                     [notificationCenter postNotificationName:@"PL_TORP_EXPLODED" userInfo:torp];
00735                 }
00736                 
00737                 // decrease fuse
00738                 [torp decreaseFuse];
00739                 if ([torp fuse] <= 0) {
00740                     // done
00741                     [torp setStatus:TORP_FREE];
00742                     [player decreaseTorpCount];
00743                 }
00744             }
00745             
00746             [torp setPreviousStatus:[torp status]];
00747          }
00748     }
00749 }
00750 
00751 - (void)drawPlasmasInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds  withScale:(int)scale  {
00752     
00753     NSRect plasmaGameBounds;
00754     NSRect plasmaViewBounds;
00755     Player *player;
00756     NSPoint centreOfGameBounds = [self centreOfRect:gameBounds];
00757     
00758     // check all plasmas of all players
00759     for (int i = 0; i < UNIVERSE_MAX_PLAYERS; i++) {
00760         player = [universe playerWithId:i];        
00761         Plasma *plasma = [universe plasmaWithId:[player plasmaId]];            
00762         
00763         if ([plasma status] == PLASMA_FREE) {
00764             continue;
00765         }
00766         
00767         // is the plasma in the view?
00768         if (!NSPointInRect([plasma predictedPosition], gameBounds)) {                
00769             // Call any plasmas off screen "free" (if owned by other)
00770             if ([plasma status] == PLASMA_EXPLODE && ![player isMe]) {
00771                 [plasma setStatus: PLASMA_FREE];
00772                 [player decreasePlasmaCount];
00773             }
00774             continue;
00775         }
00776         
00777         // get the rect around the plasma in game coordinates
00778         plasmaGameBounds.origin = [plasma predictedPosition];
00779         if ([plasma status] == PLASMA_EXPLODE) {
00780             plasmaGameBounds.size = [plasma explosionSize];
00781         } else {
00782             plasmaGameBounds.size = [plasma size];
00783         }
00784         // offset the origin to the upper left
00785         plasmaGameBounds.origin.x -= plasmaGameBounds.size.width / 2;
00786         plasmaGameBounds.origin.y -= plasmaGameBounds.size.height / 2;
00787         
00788         // convert to the view 
00789         plasmaViewBounds.size = [self viewSizeFromGameSize: plasmaGameBounds.size withScale: scale];
00790         plasmaViewBounds.origin = [self viewPointFromGamePoint: plasmaGameBounds.origin 
00791                                                       viewRect:viewBounds
00792                                          gamePosInCentreOfView:centreOfGameBounds
00793                                                      withScale:scale];
00794         
00795         // is the player in the drawing rectangle?
00796         if (!NSPointInRect(plasmaViewBounds.origin, drawingBounds)) {
00797             continue;
00798         }
00799         
00800         // draw it
00801         [self drawPlasma: plasma inRect:plasmaViewBounds];
00802         
00803         // see if we need to fire events
00804         if (([plasma status] == PLASMA_MOVE) && 
00805             ([plasma previousStatus] != PLASMA_MOVE)) {
00806             if ([player isMe]) {
00807                 [notificationCenter postNotificationName:@"PL_PLASMA_FIRED_BY_ME" userInfo:plasma];
00808             } else {
00809                 [notificationCenter postNotificationName:@"PL_PLASMA_FIRED_BY_OTHER" userInfo:plasma];
00810             }
00811         }
00812         
00813         if ([plasma status] == PLASMA_EXPLODE) {
00814                         
00815             if ([plasma previousStatus] != PLASMA_EXPLODE) {
00816                 // it just went boom
00817                 [notificationCenter postNotificationName:@"PL_PLASMA_EXPLODED" userInfo:plasma];
00818             }
00819             
00820             // decrease fuse
00821             [plasma decreaseFuse];
00822             if ([plasma fuse] <= 0) {
00823                 // done
00824                 [plasma setStatus:PLASMA_FREE];
00825                 [player decreasePlasmaCount];
00826             }
00827         } 
00828         
00829         [plasma setPreviousStatus:[plasma status]];
00830        
00831     }
00832 }
00833 
00834 - (void)drawTriangleNotchUpInRect:(NSRect)rect {
00835     
00836     // left is bottom left
00837     NSPoint left = rect.origin;
00838     left.y += rect.size.height;
00839     // right is left + width
00840     NSPoint right = left;
00841     right.x += rect.size.width;
00842     // mid is mid top
00843     NSPoint mid = rect.origin;
00844     mid.x += rect.size.width/2; 
00845     
00846     // color must be set outside!
00847     [line removeAllPoints];
00848     [line moveToPoint:left];
00849     [line lineToPoint:right];
00850     [line lineToPoint:mid];
00851     [line lineToPoint:left];
00852     [line closePath];
00853     [line stroke];
00854 }
00855 
00856 - (void)drawTriangleNotchDownInRect:(NSRect)rect {
00857     
00858     // left is top left
00859     NSPoint left = rect.origin;
00860     // right is left + width
00861     NSPoint right = rect.origin;
00862     right.x += rect.size.width;
00863     // mid is mid bottom
00864     NSPoint mid = rect.origin;
00865     mid.x += rect.size.width/2; 
00866     mid.y += rect.size.height;
00867               
00868     // color must be set outside!
00869     [line removeAllPoints];
00870     [line moveToPoint:left];
00871     [line lineToPoint:right];
00872     [line lineToPoint:mid];
00873     [line lineToPoint:left];
00874     [line closePath];
00875     [line stroke];
00876 }
00877 
00878 - (void)drawLockInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00879     
00880     Player *me = [universe playerThatIsMe];
00881     NSPoint triangleViewPoint;
00882     NSPoint triangleGamePoint;
00883 
00884     // default colour
00885     [[NSColor whiteColor] set];
00886         
00887     // are we locked?
00888     if ((([me flags] & PLAYER_PLOCK) != 0) || 
00889         (([me flags] & PLAYER_PLLOCK) != 0)) {        
00890         // yes
00891         if (([me flags] & PLAYER_PLOCK) != 0) {
00892             // locked onto a ship
00893             Player *player = [me playerLock];
00894             // player cloaked?
00895             if (([player flags] & PLAYER_CLOAK) == 0) {
00896                 // or outside screen?
00897                 if (NSPointInRect([player predictedPosition], gameBounds)) {
00898                     // find point
00899                     triangleGamePoint = [player predictedPosition];
00900                     // on top of ship
00901                     triangleGamePoint.y -= [[player ship] size].height / 2;
00902                     triangleViewPoint = [self viewPointFromGamePoint:triangleGamePoint 
00903                                                             viewRect:viewBounds
00904                                                gamePosInCentreOfView:[self centreOfRect:gameBounds]
00905                                                            withScale:scale];
00906                 } else {
00907                     return; // outside view
00908                 }
00909             } else {
00910                 return; // cloacked
00911             }
00912         } else { 
00913             // locked onto a planet
00914             Planet *planet = [me planetLock];
00915             // or outside screen?
00916             if (NSPointInRect([planet predictedPosition], gameBounds)) {
00917                 // find point
00918                 triangleGamePoint = [planet predictedPosition];
00919                 // on top of planet
00920                 triangleGamePoint.y -= [planet size].height / 2;
00921                 triangleViewPoint = [self viewPointFromGamePoint:triangleGamePoint 
00922                                                         viewRect:viewBounds
00923                                            gamePosInCentreOfView:[self centreOfRect:gameBounds]
00924                                                        withScale:scale];
00925             } else {
00926                 return; // outside view
00927             }
00928         }
00929         
00930         // set up the drawing erea
00931         NSRect rect;
00932         rect.size.width = (PF_TRIANGLE_WIDTH) / scale;
00933         rect.size.height = (PF_TRIANGLE_HEIGHT) / scale;
00934         // triangleViewPoint points at the notch
00935         rect.origin.x = triangleViewPoint.x - rect.size.width / 2;
00936         rect.origin.y = triangleViewPoint.y - rect.size.height;
00937         
00938         // is the player in the drawing rectangle?
00939         if (!NSPointInRect(rect.origin, drawingBounds)) {
00940             return;
00941         }
00942         
00943         [self drawTriangleNotchDownInRect:rect];
00944     }
00945 }
00946 
00947 // it all revolves around drawingBounds (where to draw, viewBounds what belongs in this view, 
00948 // and gameBounds (origin of the vieuwBounds
00949 - (void) drawView:(NSView*)view withMeInCenterForViewRect:(NSRect)drawingBounds withScale:(int)scale {
00950 
00951     NSRect viewBounds = [view bounds];
00952     // area of interest of the game grid
00953     NSRect gameBounds = [self gameRectAroundMeForViewRect:viewBounds withScale:scale]; 
00954     
00955     [self drawRect:drawingBounds ofViewBounds:viewBounds whichRepresentsGameBounds:gameBounds withScale:scale];
00956 }
00957 
00958 - (void) drawRect:(NSRect)drawingBounds ofViewBounds:(NSRect)viewBounds whichRepresentsGameBounds:(NSRect)gameBounds 
00959         withScale:(int)scale {
00960     
00961     // get some helpers
00962     Player *me = [universe playerThatIsMe];   
00963     
00964     // -------------------------------------------------------------------------
00965     // 0. gather some metrics
00966     // -------------------------------------------------------------------------
00967     
00968     static NSTimeInterval start, stop;
00969     start = [NSDate timeIntervalSinceReferenceDate];  
00970     if ((start-stop) > 0.1) {
00971         NSLog(@"PainterFactory.drawView: slept %f sec", (start-stop));
00972     }
00973     
00974     // -------------------------------------------------------------------------
00975     // 1. draw alert border (yellow/red/green)
00976     // -------------------------------------------------------------------------
00977     [self drawAlertBorder:viewBounds forMe:me];
00978     
00979     // make sure our border is respected
00980     // by schrinking the view
00981     viewBounds = NSInsetRect(viewBounds, PF_ALERT_BORDER_WIDTH, PF_ALERT_BORDER_WIDTH);
00982     
00983     // -------------------------------------------------------------------------
00984     // 2. draw background stars
00985     //      these are small stars floating in the oposite direction
00986     //      the original calculations are based on the game view:
00987     //      - every update, we will have shifted aprox the same amount as the
00988     //        calculation below, but planets will move
00989     //      - by applying it to the local view the stars will move with respect
00990     //        to me thus should stay roughly on top of the planets.
00991     //      - because we draw in the view, we must respect the alert border too.
00992     // -------------------------------------------------------------------------
00993     
00994     // $$ i bet this goes wrong, i may need to know the dimensions of the whole
00995     // $$ view to find out where to start painting this patch
00996     if (!simple) {
00997             [self drawBackgroundInRect:drawingBounds ofViewBounds:viewBounds forMe:me];
00998     }
00999     
01000     // -------------------------------------------------------------------------
01001     // 3. draw galaxy edges 
01002     //      is a Rect measuring UNIVERSE_PIXEL_SIZE in the gameView
01003     // -------------------------------------------------------------------------
01004     [self drawGalaxyEdgesInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01005         
01006     // -------------------------------------------------------------------------
01007     // 4. draw the planets which are in the view
01008     // -------------------------------------------------------------------------
01009     [self drawPlanetsInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01010     
01011     // -------------------------------------------------------------------------
01012     // 5. draw the players which are in the view
01013     //      this includes phasers and tractors/pressors
01014     // -------------------------------------------------------------------------
01015     [self drawPlayersInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01016     
01017     // -------------------------------------------------------------------------
01018     // 6. draw torps
01019     // -------------------------------------------------------------------------
01020     if (!simple) {
01021         [self drawTorpsInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01022     }
01023     
01024     // -------------------------------------------------------------------------
01025     // 7. draw plasmas
01026     // -------------------------------------------------------------------------
01027     if (!simple) {
01028         [self drawPlasmasInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];    
01029     }
01030     
01031     // -------------------------------------------------------------------------
01032     // 8. draw locking triangle
01033     // -------------------------------------------------------------------------
01034     [self drawLockInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01035     
01036     // -------------------------------------------------------------------------
01037     // 0. gather some metrics
01038     // -------------------------------------------------------------------------
01039     stop = [NSDate timeIntervalSinceReferenceDate];  
01040     if ((stop - start) > 0.1) {
01041         NSLog(@"PainterFactory.drawView: %f sec", (stop-start));
01042     }
01043     
01044 }
01045 
01046 - (void) drawCircleInRect:(NSRect) rect {
01047     // color must be set outside!
01048     [line removeAllPoints];
01049     [line appendBezierPathWithOvalInRect:rect];
01050     [line stroke];  
01051 }
01052 
01053 - (void) drawDoubleCircleInRect:(NSRect) rect {
01054     // color must be set outside!
01055     [line removeAllPoints];
01056     [line setWindingRule:NSEvenOddWindingRule];
01057     [line appendBezierPathWithOvalInRect:rect];
01058     [line appendBezierPathWithOvalInRect:NSInsetRect(rect, 5, 5)];
01059     [line stroke];  
01060     // reset
01061     [line setWindingRule:[NSBezierPath defaultWindingRule]];
01062 }
01063 
01064 - (NSRect) createRectAroundOrigin:(NSRect)Rect {
01065     NSRect result = Rect;
01066     result.origin.x = -(result.size.width/2);
01067     result.origin.y = -(result.size.height/2);
01068     return result;
01069 }
01070 
01071 - (void) rotateAndDrawPlayer:(Player*) player inRect:(NSRect) Rect {
01072     
01073     float course = [player course];
01074     //float course = 0;
01075     
01076     // first save the GC
01077     [[NSGraphicsContext currentContext] saveGraphicsState];
01078     
01079     // set up the rotate
01080     NSAffineTransform *transform = [NSAffineTransform transform];
01081     
01082     // assume ship drawn at 0,0 and move to ship position
01083     NSPoint center = [self centreOfRect:Rect];
01084     // transforms are read in reverse so this reads: first rotate then translate!
01085     [transform translateXBy:center.x yBy:center.y];
01086     [transform rotateByDegrees:course];  
01087     // concat the transform
01088     [transform concat];
01089     
01090     // draw the ship around 0,0
01091     Rect.origin = NSZeroPoint;
01092     [self drawPlayer:player inRect:[self createRectAroundOrigin:Rect]];
01093     
01094     // and restore the GC
01095     [transform invert];
01096     [transform concat];
01097     [[NSGraphicsContext currentContext] restoreGraphicsState];
01098 }
01099 
01100 // should be overwritten by subclasses
01101 - (void)   drawPlayer:(Player*) player inRect:(NSRect) Rect {
01102     //NSLog(@"PainterFactory.drawPlayer course %f %@",course, 
01103     //      [NSString stringWithFormat:@"x=%f, y=%f, w=%f, h=%f", 
01104     //          Rect.origin.x, Rect.origin.y, Rect.size.width, Rect.size.height]);
01105     
01106     [[self colorForTeam:[player team]] set];
01107         
01108     // draw the ship in a sqrt(2)/2 size rect (inner circle)
01109     // sides should be 0.707 * rect.width thus reduced by 0,292893218813 / 2
01110     [shapes drawSpaceShipInRect:NSInsetRect(Rect, Rect.size.width*0.1515, Rect.size.height*0.1515)];
01111     
01112     /* draw as triangle 
01113     [self drawTriangleNotchUpInRect:NSInsetRect(Rect, Rect.size.width*0.1515, Rect.size.height*0.1515)];
01114     // $$ abuse line (very bad)
01115     [line fill];
01116     */
01117 }
01118 
01119 - (void)   drawShieldWithStrenght: (float)shieldPercentage inRect:(NSRect) Rect {
01120     
01121     // recalculate
01122     NSPoint centre = [self centreOfRect:Rect];
01123     // shield extends our ship by 1 point
01124     float radius = (Rect.size.width / 2) + 1; // assume Rect is square!!
01125     
01126     // get the colour
01127     NSColor *shieldColor = [NSColor greenColor];
01128     if (shieldPercentage < 50.0) {
01129         shieldColor = [NSColor yellowColor];
01130     }
01131     if (shieldPercentage < 25.0) {
01132         shieldColor = [NSColor redColor];
01133     }
01134     
01135     // get angle
01136     float angle = (360.0 * shieldPercentage / 100);
01137     
01138     //NSLog(@"PainterFactory.drawShield strenght %f, angle %f", shieldPercentage, angle);
01139     
01140     // draw
01141     [shieldColor set];
01142     
01143     // first the remaining strenght
01144     [line removeAllPoints];  
01145     [line appendBezierPathWithArcWithCenter:centre radius:radius startAngle:0.0 endAngle:angle];
01146     [line stroke]; 
01147     // then the lost shield
01148     if (angle < 360.0) {
01149         [dashedLine removeAllPoints];
01150         [dashedLine appendBezierPathWithArcWithCenter:centre radius:radius startAngle:angle endAngle:360.0];
01151         [dashedLine stroke];
01152     }
01153 
01154 }
01155 
01156 - (void)   drawPlanet:(Planet*) planet inRect:(NSRect) Rect {
01157     //NSLog(@"PainterFactory.drawPlanet %@", 
01158     //      [NSString stringWithFormat:@"x=%f, y=%f, w=%f, h=%f", 
01159     //          Rect.origin.x, Rect.origin.y, Rect.size.width, Rect.size.height]);
01160     [[self colorForTeam:[planet owner]] set];
01161     
01162     [self drawDoubleCircleInRect:Rect];
01163 }
01164 
01165 - (void)   drawTorp:(Torp*) torp       inRect:(NSRect) Rect {
01166     //NSLog(@"PainterFactory.drawTorp %@",  
01167     //      [NSString stringWithFormat:@"x=%f, y=%f, w=%f, h=%f", 
01168     //          Rect.origin.x, Rect.origin.y, Rect.size.width, Rect.size.height]);
01169     [[self colorForTeam:[[torp owner] team]] set];
01170     
01171     [self drawCircleInRect:Rect];
01172 }
01173 
01174 - (void)   drawPlasma:(Plasma*) plasma inRect:(NSRect) Rect {
01175     //NSLog(@"PainterFactory.drawPlasma %@", 
01176     //      [NSString stringWithFormat:@"x=%f, y=%f, w=%f, h=%f", 
01177     //          Rect.origin.x, Rect.origin.y, Rect.size.width, Rect.size.height]);
01178     [[self colorForTeam:[plasma team]] set];
01179     
01180     [self drawCircleInRect:Rect];
01181 }
01182 
01183 - (void)   drawBackgroundImageInRect:(NSRect) Rect {
01184     //NSLog(@"PainterFactory.drawBackgroundImageInRect %@",  
01185     //[NSString stringWithFormat:@"x=%f, y=%f, w=%f, h=%f", 
01186     //    Rect.origin.x, Rect.origin.y, Rect.size.width, Rect.size.height]);
01187 }
01188 
01189 - (void) drawLabelForPlanet:(Planet*)planet belowRect:(NSRect)planetViewBounds {
01190     
01191     // draw the name, 12pnt below the planet
01192     NSString *label = [NSString stringWithString:[planet name]];
01193     
01194     // extended label?
01195     if ([planet showInfo] || debugLabels) {
01196         label = [NSString stringWithFormat:@"%@ %d [%c%c%c]",
01197             [planet name],
01198             [planet armies],
01199             ([planet flags] & PLANET_REPAIR ? 'R' : '-'),
01200             ([planet flags] & PLANET_FUEL ?   'F' : '-'),
01201             ([planet flags] & PLANET_AGRI ?   'A' : '-')
01202             ];
01203     }   
01204     
01205     [[NSColor whiteColor] set];
01206     NSPoint namePosition = planetViewBounds.origin;
01207     namePosition.y += planetViewBounds.size.height +  [label sizeWithAttributes:normalStateAttribute].height;
01208     [label drawAtPoint: namePosition withAttributes:normalStateAttribute];  
01209 }
01210 
01211 - (void) drawLabelForPlayer:(Player*)player belowRect:(NSRect)playerViewBounds {
01212     
01213     // draw the name, 12pnt below the player
01214     NSString *label = [NSString stringWithString:[player mapChars]];
01215 
01216     // extended label?
01217     if ([player showInfo] || debugLabels) {
01218         label = // in debug we show status[NSString stringWithFormat:@"%@ %d(%d) %d %d [%c%c%c%c%c%c] %@",
01219             [player longName],
01220             [player speed],
01221             [player requestedSpeed],
01222             [player kills],
01223             [player armies],
01224             ([player flags] & PLAYER_REPAIR ? 'R' : '-'),
01225             ([player flags] & PLAYER_BOMB ?   'B' : '-'),
01226             ([player flags] & PLAYER_ORBIT ?  'O' : '-'),
01227             ([player flags] & PLAYER_CLOAK ?  'C' : '-'),
01228             ([player flags] & PLAYER_BEAMUP ?  'U' : '-'),
01229             ([player flags] & PLAYER_BEAMDOWN ?  'D' : '-'),
01230             (debugLabels ? [[player statusString] substringFromIndex:7] : @"") 
01231             ];
01232     }   
01233     
01234     [[NSColor whiteColor] set];
01235     NSPoint namePosition = playerViewBounds.origin;
01236     int labelHeight = [label sizeWithAttributes:normalStateAttribute].height;
01237     namePosition.y += playerViewBounds.size.height +  labelHeight;
01238     [label drawAtPoint: namePosition withAttributes:normalStateAttribute];   
01239     
01240     if (debugLabels) {
01241         // prepare another line
01242         NSArray *torps = [player torps];
01243         label = // we know that there are 8 and this is debug[NSString stringWithFormat:@"T[%c%c%c%c%c%c%c%c] F[%d%d%d%d%d%d%d%d]",
01244             [[torps objectAtIndex:0] statusChar],  
01245             [[torps objectAtIndex:1] statusChar],
01246             [[torps objectAtIndex:2] statusChar],
01247             [[torps objectAtIndex:3] statusChar],
01248             [[torps objectAtIndex:4] statusChar],
01249             [[torps objectAtIndex:5] statusChar],
01250             [[torps objectAtIndex:6] statusChar],
01251             [[torps objectAtIndex:7] statusChar],
01252             [[torps objectAtIndex:0] fuse], 
01253             [[torps objectAtIndex:1] fuse],
01254             [[torps objectAtIndex:2] fuse],
01255             [[torps objectAtIndex:3] fuse],
01256             [[torps objectAtIndex:4] fuse],
01257             [[torps objectAtIndex:5] fuse],
01258             [[torps objectAtIndex:6] fuse],
01259             [[torps objectAtIndex:7] fuse]];
01260             
01261         namePosition.y += labelHeight;
01262         [label drawAtPoint: namePosition withAttributes:normalStateAttribute]; 
01263         
01264         // prepare another line
01265         Plasma *plasma = [universe plasmaWithId:[player plasmaId]];
01266         Phaser *phaser = [universe phaserWithId:[player phaserId]];
01267         label = [NSString stringWithFormat:@"PH[%c][%d] PL[%c][%d]",
01268             [phaser statusChar],
01269             [phaser fuse],
01270             [plasma statusChar],
01271             [plasma fuse]];
01272         
01273         namePosition.y += labelHeight;
01274         [label drawAtPoint: namePosition withAttributes:normalStateAttribute];  
01275     }
01276 }
01277 
01278 @end

Generated on Fri Jul 28 19:15:23 2006 for MacTrek by  doxygen 1.4.7