00001
00002
00003
00004
00005
00006
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
00027 backGroundStartPoint.x = 0;
00028 backGroundStartPoint.y = 0;
00029 debugLabels = NO;
00030 simple = NO;
00031
00032
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
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;
00064 }
00065
00066 - (int) minScale {
00067 return 2;
00068 }
00069
00070
00071 - (void) cacheImages {
00072
00073 sleep(2);
00074 }
00075
00076 - (void) cacheImagesInSeperateThread:(id)sender {
00077
00078
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
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
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
00117
00118 int deltaX = point.x - (bounds.size.width / 2);
00119 int deltaY = point.y - (bounds.size.height / 2);
00120
00121
00122
00123 NSPoint gamePoint;
00124 gamePoint.x = centrePos.x + deltaX*scale;
00125 gamePoint.y = centrePos.y + deltaY*scale;
00126
00127 return gamePoint;
00128 }
00129
00130
00131
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
00143 - (NSRect) gameRectAroundMeForViewRect:(NSRect)bounds withScale:(int)scale {
00144
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
00153 static NSRect result;
00154 static NSRect previousBounds;
00155 static int previousScale;
00156
00157
00158
00159
00160
00161 previousScale = scale;
00162 previousBounds = bounds;
00163
00164
00165 result.size = [self gameSizeFromViewSize:bounds.size withScale:scale];
00166
00167
00168
00169 result.origin = [self gamePointFromViewPoint:bounds.origin
00170 viewRect:bounds
00171 gamePosInCentreOfView:gamePoint
00172 withScale:scale];
00173 return result;
00174 }
00175
00176
00177
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
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
00197 int deltaX = point.x - centrePos.x;
00198 int deltaY = point.y - centrePos.y;
00199
00200
00201
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
00225 if (alert != ([me flags] & ALERT_FILTER)) {
00226 alert = ([me flags] & ALERT_FILTER);
00227
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
00243 bounds.size.height -= 1;
00244
00245 [line removeAllPoints];
00246 [line appendBezierPathWithRect:bounds];
00247 float oldWidth = [line lineWidth];
00248 [line setLineWidth: PF_ALERT_BORDER_WIDTH];
00249 [line stroke];
00250 [line setLineWidth:oldWidth];
00251 }
00252
00253 }
00254
00255 - (void) drawBackgroundInRect:(NSRect) drawingBounds ofViewBounds:(NSRect)viewBounds forMe:(Player*) me {
00256
00257
00258 NSSize backGroundImageSize = [self backGroundImageSize];
00259
00260 NSPoint startPoint = backGroundStartPoint;
00261
00262
00263
00264
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
00271
00272
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
00287 NSRect targetArea;
00288
00289 targetArea.size = backGroundImageSize;
00290
00291
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
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
00314 [[NSColor brownColor] set];
00315
00316
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
00327
00328
00329
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
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
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
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
00374 if (!NSPointInRect([planet predictedPosition], gameBounds)) {
00375 continue;
00376 }
00377
00378
00379 planetGameBounds.origin = [planet predictedPosition];
00380 planetGameBounds.size = [planet size];
00381
00382 planetGameBounds.origin.x -= planetGameBounds.size.width / 2;
00383 planetGameBounds.origin.y -= planetGameBounds.size.height / 2;
00384
00385
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
00393 if (!NSPointInRect(planetViewBounds.origin, drawingBounds)) {
00394 continue;
00395 }
00396
00397
00398 [self drawPlanet: planet inRect:planetViewBounds];
00399
00400
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
00418 if (!NSPointInRect([player predictedPosition], gameBounds)) {
00419 continue;
00420 }
00421
00422
00423 if (([player status] != PLAYER_ALIVE && [player status] != PLAYER_EXPLODE) || ([player flags] & PLAYER_OBSERV) != 0) {
00424 continue;
00425 }
00426
00427
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
00439 if ([player isMe]) {
00440 [notificationCenter postNotificationName:@"PL_UNCLOAKING" userInfo:[NSNumber numberWithBool:NO]];
00441 }
00442 }
00443 else {
00444
00445
00446 }
00447 [player decreaseCloakPhase];
00448 }
00449
00450
00451 playerGameBounds.origin = [player predictedPosition];
00452 playerGameBounds.size = [[player ship] size];
00453
00454 playerGameBounds.origin.x -= playerGameBounds.size.width / 2;
00455 playerGameBounds.origin.y -= playerGameBounds.size.height / 2;
00456
00457
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
00465 if (!NSPointInRect(playerViewBounds.origin, drawingBounds)) {
00466 continue;
00467 }
00468
00469
00470 [self rotateAndDrawPlayer: player inRect:playerViewBounds];
00471
00472
00473 [self drawLabelForPlayer:player belowRect:playerViewBounds];
00474
00475 if (simple) {
00476 continue;
00477 }
00478
00479
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
00489 NSPoint playerPositionInView = [self viewPointFromGamePoint: [player predictedPosition]
00490 viewRect:viewBounds
00491 gamePosInCentreOfView:centreOfGameBounds
00492 withScale:scale];
00493
00494
00495
00496 if (([player status] == PLAYER_EXPLODE) &&
00497 ([player previousStatus] != PLAYER_EXPLODE)) {
00498
00499 [notificationCenter postNotificationName:@"PL_EXPLODE_PLAYER" userInfo:player];
00500 }
00501 [player setPreviousStatus:[player status]];
00502
00503
00504 if (([player flags] & PLAYER_SHIELD) &&
00505 !([player previousFlags] & PLAYER_SHIELD)) {
00506
00507 [notificationCenter postNotificationName:@"PL_SHIELD_UP_PLAYER" userInfo:player];
00508 }
00509 if (!([player flags] & PLAYER_SHIELD) &&
00510 ([player previousFlags] & PLAYER_SHIELD)) {
00511
00512 [notificationCenter postNotificationName:@"PL_SHIELD_DOWN_PLAYER" userInfo:player];
00513 }
00514
00515 [player setPreviousFlags:[player flags]];
00516
00517
00518 Phaser *phaser = [universe phaserWithId:[player phaserId]];
00519 NSPoint phaserEndPoint;
00520
00521 if ([phaser status] != PHASER_FREE) {
00522 if([phaser previousStatus] == PHASER_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
00534 compute = PHASER_MAX_DISTANCE * ([[player ship] phaserDamage ] / 100.0f);
00535
00536
00537
00538
00539
00540
00541 phaserEndPoint.x = (int)([player predictedPosition].x + (int)(compute * sinf([phaser dirInRad])));
00542 phaserEndPoint.y = (int)([player predictedPosition].y - (int)(compute * cosf([phaser dirInRad])));
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
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
00558 [[self colorForTeam:[player team]] set];
00559 }
00560 else {
00561 [[NSColor whiteColor] set];
00562 }
00563
00564
00565 phaserStartPoint = playerPositionInView;
00566
00567 phaserEndPoint = [self viewPointFromGamePoint: phaserEndPoint
00568 viewRect:viewBounds
00569 gamePosInCentreOfView:centreOfGameBounds
00570 withScale:scale];
00571
00572
00573
00574 [line removeAllPoints];
00575 [line moveToPoint:phaserStartPoint];
00576 [line lineToPoint:phaserEndPoint];
00577 [line stroke];
00578
00579
00580 [phaser increaseFuse];
00581 if([phaser fuse] > [phaser maxfuse]) {
00582 [phaser setStatus: PHASER_FREE];
00583 }
00584 }
00585 }
00586
00587
00588 [phaser setPreviousStatus:[phaser status]];
00589
00590
00591
00592 if(([player flags] & (PLAYER_TRACT | PLAYER_PRESS)) == 0 || [player status] != PLAYER_ALIVE) {
00593 continue;
00594 }
00595
00596
00597 Player *tractee = [player tractorTarget];
00598 if(tractee == nil) {
00599 continue;
00600 }
00601
00602
00603 if ([tractee status] != PLAYER_ALIVE) {
00604
00605
00606 continue;
00607 }
00608
00609 NSPoint tractorStartPoint = playerPositionInView;
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
00619
00620
00621
00622 double theta = atan2((double)(tractorEndPoint.x - tractorStartPoint.x),
00623 (double)(tractorStartPoint.y - tractorEndPoint.y)) + pi / 2.0;
00624
00625
00626
00627
00628
00629
00630
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
00645
00646
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
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
00677
00678
00679 if (!NSPointInRect([torp predictedPosition], gameBounds)) {
00680
00681
00682 if (![player isMe]) {
00683 [player decreaseTorpCount];
00684 }
00685
00686 [torp setStatus: TORP_FREE];
00687 [torp setPreviousStatus:TORP_FREE];
00688
00689 continue;
00690 }
00691
00692
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
00700 torpGameBounds.origin.x -= torpGameBounds.size.width / 2;
00701 torpGameBounds.origin.y -= torpGameBounds.size.height / 2;
00702
00703
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
00711 if (!NSPointInRect(torpViewBounds.origin, drawingBounds)) {
00712 continue;
00713 }
00714
00715
00716 [self drawTorp: torp inRect:torpViewBounds];
00717
00718
00719
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
00734 [notificationCenter postNotificationName:@"PL_TORP_EXPLODED" userInfo:torp];
00735 }
00736
00737
00738 [torp decreaseFuse];
00739 if ([torp fuse] <= 0) {
00740
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
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
00768 if (!NSPointInRect([plasma predictedPosition], gameBounds)) {
00769
00770 if ([plasma status] == PLASMA_EXPLODE && ![player isMe]) {
00771 [plasma setStatus: PLASMA_FREE];
00772 [player decreasePlasmaCount];
00773 }
00774 continue;
00775 }
00776
00777
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
00785 plasmaGameBounds.origin.x -= plasmaGameBounds.size.width / 2;
00786 plasmaGameBounds.origin.y -= plasmaGameBounds.size.height / 2;
00787
00788
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
00796 if (!NSPointInRect(plasmaViewBounds.origin, drawingBounds)) {
00797 continue;
00798 }
00799
00800
00801 [self drawPlasma: plasma inRect:plasmaViewBounds];
00802
00803
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
00817 [notificationCenter postNotificationName:@"PL_PLASMA_EXPLODED" userInfo:plasma];
00818 }
00819
00820
00821 [plasma decreaseFuse];
00822 if ([plasma fuse] <= 0) {
00823
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
00837 NSPoint left = rect.origin;
00838 left.y += rect.size.height;
00839
00840 NSPoint right = left;
00841 right.x += rect.size.width;
00842
00843 NSPoint mid = rect.origin;
00844 mid.x += rect.size.width/2;
00845
00846
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
00859 NSPoint left = rect.origin;
00860
00861 NSPoint right = rect.origin;
00862 right.x += rect.size.width;
00863
00864 NSPoint mid = rect.origin;
00865 mid.x += rect.size.width/2;
00866 mid.y += rect.size.height;
00867
00868
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
00885 [[NSColor whiteColor] set];
00886
00887
00888 if ((([me flags] & PLAYER_PLOCK) != 0) ||
00889 (([me flags] & PLAYER_PLLOCK) != 0)) {
00890
00891 if (([me flags] & PLAYER_PLOCK) != 0) {
00892
00893 Player *player = [me playerLock];
00894
00895 if (([player flags] & PLAYER_CLOAK) == 0) {
00896
00897 if (NSPointInRect([player predictedPosition], gameBounds)) {
00898
00899 triangleGamePoint = [player predictedPosition];
00900
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;
00908 }
00909 } else {
00910 return;
00911 }
00912 } else {
00913
00914 Planet *planet = [me planetLock];
00915
00916 if (NSPointInRect([planet predictedPosition], gameBounds)) {
00917
00918 triangleGamePoint = [planet predictedPosition];
00919
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;
00927 }
00928 }
00929
00930
00931 NSRect rect;
00932 rect.size.width = (PF_TRIANGLE_WIDTH) / scale;
00933 rect.size.height = (PF_TRIANGLE_HEIGHT) / scale;
00934
00935 rect.origin.x = triangleViewPoint.x - rect.size.width / 2;
00936 rect.origin.y = triangleViewPoint.y - rect.size.height;
00937
00938
00939 if (!NSPointInRect(rect.origin, drawingBounds)) {
00940 return;
00941 }
00942
00943 [self drawTriangleNotchDownInRect:rect];
00944 }
00945 }
00946
00947
00948
00949 - (void) drawView:(NSView*)view withMeInCenterForViewRect:(NSRect)drawingBounds withScale:(int)scale {
00950
00951 NSRect viewBounds = [view bounds];
00952
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
00962 Player *me = [universe playerThatIsMe];
00963
00964
00965
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
00976
00977 [self drawAlertBorder:viewBounds forMe:me];
00978
00979
00980
00981 viewBounds = NSInsetRect(viewBounds, PF_ALERT_BORDER_WIDTH, PF_ALERT_BORDER_WIDTH);
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 if (!simple) {
00997 [self drawBackgroundInRect:drawingBounds ofViewBounds:viewBounds forMe:me];
00998 }
00999
01000
01001
01002
01003
01004 [self drawGalaxyEdgesInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01005
01006
01007
01008
01009 [self drawPlanetsInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01010
01011
01012
01013
01014
01015 [self drawPlayersInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01016
01017
01018
01019
01020 if (!simple) {
01021 [self drawTorpsInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01022 }
01023
01024
01025
01026
01027 if (!simple) {
01028 [self drawPlasmasInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01029 }
01030
01031
01032
01033
01034 [self drawLockInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01035
01036
01037
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
01048 [line removeAllPoints];
01049 [line appendBezierPathWithOvalInRect:rect];
01050 [line stroke];
01051 }
01052
01053 - (void) drawDoubleCircleInRect:(NSRect) rect {
01054
01055 [line removeAllPoints];
01056 [line setWindingRule:NSEvenOddWindingRule];
01057 [line appendBezierPathWithOvalInRect:rect];
01058 [line appendBezierPathWithOvalInRect:NSInsetRect(rect, 5, 5)];
01059 [line stroke];
01060
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
01075
01076
01077 [[NSGraphicsContext currentContext] saveGraphicsState];
01078
01079
01080 NSAffineTransform *transform = [NSAffineTransform transform];
01081
01082
01083 NSPoint center = [self centreOfRect:Rect];
01084
01085 [transform translateXBy:center.x yBy:center.y];
01086 [transform rotateByDegrees:course];
01087
01088 [transform concat];
01089
01090
01091 Rect.origin = NSZeroPoint;
01092 [self drawPlayer:player inRect:[self createRectAroundOrigin:Rect]];
01093
01094
01095 [transform invert];
01096 [transform concat];
01097 [[NSGraphicsContext currentContext] restoreGraphicsState];
01098 }
01099
01100
01101 - (void) drawPlayer:(Player*) player inRect:(NSRect) Rect {
01102
01103
01104
01105
01106 [[self colorForTeam:[player team]] set];
01107
01108
01109
01110 [shapes drawSpaceShipInRect:NSInsetRect(Rect, Rect.size.width*0.1515, Rect.size.height*0.1515)];
01111
01112
01113
01114
01115
01116
01117 }
01118
01119 - (void) drawShieldWithStrenght: (float)shieldPercentage inRect:(NSRect) Rect {
01120
01121
01122 NSPoint centre = [self centreOfRect:Rect];
01123
01124 float radius = (Rect.size.width / 2) + 1;
01125
01126
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
01136 float angle = (360.0 * shieldPercentage / 100);
01137
01138
01139
01140
01141 [shieldColor set];
01142
01143
01144 [line removeAllPoints];
01145 [line appendBezierPathWithArcWithCenter:centre radius:radius startAngle:0.0 endAngle:angle];
01146 [line stroke];
01147
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
01158
01159
01160 [[self colorForTeam:[planet owner]] set];
01161
01162 [self drawDoubleCircleInRect:Rect];
01163 }
01164
01165 - (void) drawTorp:(Torp*) torp inRect:(NSRect) Rect {
01166
01167
01168
01169 [[self colorForTeam:[[torp owner] team]] set];
01170
01171 [self drawCircleInRect:Rect];
01172 }
01173
01174 - (void) drawPlasma:(Plasma*) plasma inRect:(NSRect) Rect {
01175
01176
01177
01178 [[self colorForTeam:[plasma team]] set];
01179
01180 [self drawCircleInRect:Rect];
01181 }
01182
01183 - (void) drawBackgroundImageInRect:(NSRect) Rect {
01184
01185
01186
01187 }
01188
01189 - (void) drawLabelForPlanet:(Planet*)planet belowRect:(NSRect)planetViewBounds {
01190
01191
01192 NSString *label = [NSString stringWithString:[planet name]];
01193
01194
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
01214 NSString *label = [NSString stringWithString:[player mapChars]];
01215
01216
01217 if ([player showInfo] || debugLabels) {
01218 label = [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
01242 NSArray *torps = [player torps];
01243 label = [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
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