00001
00002
00003
00004
00005
00006
00007
00008
00009 #import "PainterFactory.h"
00010
00011 @implementation PainterFactory
00012
00013
00014 #define ALERT_FILTER (PLAYER_GREEN | PLAYER_YELLOW | PLAYER_RED)
00015
00016 - (id) init {
00017 self = [super init];
00018 if (self != nil) {
00019
00020 backGroundStartPoint.x = 0;
00021 backGroundStartPoint.y = 0;
00022 debugLabels = NO;
00023 simple = NO;
00024 alert = PLAYER_GREEN;
00025
00026
00027 trigonometry = [LLTrigonometry defaultInstance];
00028 shapes = [[LLShapes alloc] init];
00029 universe = [Universe defaultInstance];
00030 line = [[NSBezierPath alloc] init];
00031 dashedLine = [[NSBezierPath alloc] init];
00032 float dash = { 1.0, 3.0 };
00033 [dashedLine setLineDash: dash count: 2 phase: 0.0];
00034
00035 normalStateAttribute =[[NSDictionary dictionaryWithObjectsAndKeys:
00036 [NSColor whiteColor],NSForegroundColorAttributeName,nil] retain];
00037
00038 [NSThread detachNewThreadSelector:@selector(cacheImagesInSeperateThread:) toTarget:self withObject:nil];
00039
00040 }
00041 return self;
00042 }
00043
00044 - (void) setSimplifyDrawing:(bool)simpleDraw {
00045 simple = simpleDraw;
00046 }
00047
00048 - (void) setDebugLabels:(bool)debug {
00049 debugLabels = debug;
00050 }
00051
00052 - (bool) debugLabels {
00053 return debugLabels;
00054 }
00055
00056 - (int) maxScale {
00057 return 400;
00058 }
00059
00060 - (int) minScale {
00061 return 2;
00062 }
00063
00064
00065 - (void) cacheImages {
00066
00067 sleep(2);
00068 }
00069
00070 - (void) cacheImagesInSeperateThread:(id)sender {
00071
00072
00073 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
00074
00075 NSLog(@"PainterFactory.cacheImagesInSeperateThread: start running");
00076 [self cacheImages];
00077 NSLog(@"PainterFactory.cacheImagesInSeperateThread: complete");
00078
00079 [notificationCenter postNotificationName:@"PF_IMAGES_CACHED"];
00080
00081
00082 [pool release];
00083 }
00084
00085 - (NSSize) backGroundImageSize {
00086 return PF_DEFAULT_BACKGROUND_IMAGE_SIZE;
00087 }
00088
00089 - (NSColor*) colorForTeam:(Team*)team {
00090 return [team colorForTeam];
00091 }
00092
00093 - (NSPoint) centreOfRect:(NSRect)aRect {
00094
00095 return [shapes centreOfRect:aRect];
00096 }
00097
00098 - (NSPoint) gamePointFromViewPoint:(NSPoint)point withMeInViewRect:(NSRect)bounds withScale:(int)scale {
00099
00100
00101 NSPoint centrePos = [[universe playerThatIsMe] predictedPosition];
00102 return [self gamePointFromViewPoint:point viewRect:bounds gamePosInCentreOfView:centrePos withScale:scale];
00103 }
00104
00105 - (NSPoint) gamePointFromViewPoint:(NSPoint)point viewRect:(NSRect)bounds
00106 gamePosInCentreOfView:(NSPoint)centrePos withScale:(int)scale {
00107
00108
00109
00110 int deltaX = point.x - (bounds.size.width / 2);
00111 int deltaY = point.y - (bounds.size.height / 2);
00112
00113
00114
00115 NSPoint gamePoint;
00116 gamePoint.x = centrePos.x + deltaX*scale;
00117 gamePoint.y = centrePos.y + deltaY*scale;
00118
00119 return gamePoint;
00120 }
00121
00122
00123
00124 - (NSSize) gameSizeFromViewSize:(NSSize)rect withScale:(int)scale {
00125
00126 NSSize size;
00127
00128 size.height = rect.height*scale;
00129 size.width = rect.width*scale;
00130
00131 return size;
00132 }
00133
00134 - (NSRect) gameRectAround:(NSPoint)gamePoint forView:(NSRect)bounds withScale:(int)scale {
00135
00136
00137 static NSRect result;
00138 static NSRect previousBounds;
00139 static int previousScale;
00140
00141 previousScale = scale;
00142 previousBounds = bounds;
00143
00144
00145 result.size = [self gameSizeFromViewSize:bounds.size withScale:scale];
00146
00147
00148
00149 result.origin = [self gamePointFromViewPoint:bounds.origin
00150 viewRect:bounds
00151 gamePosInCentreOfView:gamePoint
00152 withScale:scale];
00153 return result;
00154 }
00155
00156 - (NSSize) viewSizeFromGameSize:(NSSize)rect withScale:(int)scale{
00157
00158 NSSize size;
00159
00160 size.height = rect.height / scale;
00161 size.width = rect.width / scale;
00162
00163 return size;
00164 }
00165
00166 - (NSPoint) viewPointFromGamePoint:(NSPoint)point withMeInViewRect:(NSRect)bounds withScale:(int)scale {
00167
00168 NSPoint centrePos = [[universe playerThatIsMe] predictedPosition];
00169 return [self viewPointFromGamePoint:point viewRect:bounds gamePosInCentreOfView:centrePos withScale:scale];
00170 }
00171
00172 - (NSPoint) viewPointFromGamePoint:(NSPoint)point viewRect:(NSRect)bounds
00173 gamePosInCentreOfView:(NSPoint)centrePos withScale:(int)scale {
00174
00175 int deltaX = point.x - centrePos.x;
00176 int deltaY = point.y - centrePos.y;
00177
00178
00179
00180 NSPoint viewPoint;
00181 viewPoint.x = (bounds.size.width / 2) + deltaX / scale;
00182 viewPoint.y = (bounds.size.height / 2) + deltaY / scale;
00183
00184 return viewPoint;
00185 }
00186
00187 - (void) drawAlertBorder:(NSRect) bounds forMe:(Player *)me {
00188
00189
00190 if (alert != ([me flags] & ALERT_FILTER)) {
00191 alert = ([me flags] & ALERT_FILTER);
00192
00193 [notificationCenter postNotificationName:@"PL_ALERT_STATUS_CHANGED" userInfo:[NSNumber numberWithInt:alert]];
00194 }
00195 if ([me flags] & ALERT_FILTER) {
00196 switch (alert) {
00197 case PLAYER_GREEN :
00198 [[NSColor greenColor] set];
00199 break;
00200 case PLAYER_YELLOW :
00201 [[NSColor yellowColor] set];
00202 break;
00203 case PLAYER_RED :
00204 [[NSColor redColor] set];
00205 break;
00206 }
00207
00208
00209 [line removeAllPoints];
00210 [line appendBezierPathWithRect:bounds];
00211 float oldWidth = [line lineWidth];
00212 [line setLineWidth: PF_ALERT_BORDER_WIDTH];
00213 [line stroke];
00214 [line setLineWidth:oldWidth];
00215 }
00216
00217 }
00218
00219 - (void) drawBackgroundInRect:(NSRect) drawingBounds ofViewBounds:(NSRect)viewBounds forMe:(Player*) me {
00220
00221
00222 NSSize backGroundImageSize = [self backGroundImageSize];
00223
00224 NSPoint startPoint = backGroundStartPoint;
00225
00226
00227
00228
00229 float course = [me course];
00230
00231 startPoint.x -= cos(course) * (float)[me speed] / 4.0f;
00232 startPoint.y -= sin(course) * (float)[me speed] / 4.0f;
00233
00234
00235
00236
00237 if(startPoint.x < -backGroundImageSize.width) {
00238 startPoint.x += backGroundImageSize.width;
00239 }
00240 else if(startPoint.x > 0.0f) {
00241 startPoint.x -= backGroundImageSize.width;
00242 }
00243 if(startPoint.y < -backGroundImageSize.height) {
00244 startPoint.y += backGroundImageSize.height;
00245 }
00246 else if(startPoint.y > 0.0f) {
00247 startPoint.y -= backGroundImageSize.height;
00248 }
00249
00250
00251 NSRect targetArea;
00252
00253 targetArea.size = backGroundImageSize;
00254
00255 for(int y = (int)startPoint.y; y < viewBounds.size.height; y += backGroundImageSize.height) {
00256 for(int x = (int)startPoint.x; x < viewBounds.size.width; x += backGroundImageSize.width) {
00257 targetArea.origin.x = x;
00258 targetArea.origin.y = y;
00259
00260
00261 if (!NSIntersectsRect(targetArea, drawingBounds)) {
00262 continue;
00263 }
00264
00265 [self drawBackgroundImageInRect: targetArea];
00266 }
00267 }
00268
00269 backGroundStartPoint = startPoint;
00270 }
00271
00272 - (void) drawGalaxyEdgesInRect:(NSRect) drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00273
00274
00275 [[NSColor brownColor] set];
00276
00277
00278 NSPoint upperLeft = [self viewPointFromGamePoint:NSMakePoint(0, 0)
00279 viewRect:viewBounds
00280 gamePosInCentreOfView:[self centreOfRect:gameBounds]
00281 withScale:scale];
00282 NSPoint lowerRight = [self viewPointFromGamePoint:NSMakePoint(UNIVERSE_PIXEL_SIZE, UNIVERSE_PIXEL_SIZE)
00283 viewRect:viewBounds
00284 gamePosInCentreOfView:[self centreOfRect:gameBounds]
00285 withScale:scale];
00286
00287
00288
00289
00290
00291 if (gameBounds.origin.y <= 0) {
00292 [line removeAllPoints];
00293 [line moveToPoint:upperLeft];
00294 [line lineToPoint:NSMakePoint(lowerRight.x, upperLeft.y)];
00295 [line stroke];
00296 }
00297
00298
00299 if (gameBounds.origin.y + gameBounds.size.height > UNIVERSE_PIXEL_SIZE) {
00300 [line removeAllPoints];
00301 [line moveToPoint:lowerRight];
00302 [line lineToPoint:NSMakePoint(upperLeft.x, lowerRight.y)];
00303 [line stroke];
00304 }
00305
00306
00307 if (gameBounds.origin.x <= 0) {
00308 [line removeAllPoints];
00309 [line moveToPoint:upperLeft];
00310 [line lineToPoint:NSMakePoint(upperLeft.x, lowerRight.y)];
00311 [line stroke];
00312 }
00313
00314
00315 if (gameBounds.origin.x + gameBounds.size.width > UNIVERSE_PIXEL_SIZE) {
00316 [line removeAllPoints];
00317 [line moveToPoint:lowerRight];
00318 [line lineToPoint:NSMakePoint(lowerRight.x, upperLeft.y)];
00319 [line stroke];
00320 }
00321
00322 }
00323
00324 - (void)drawPlanetsInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00325
00326 NSRect planetGameBounds;
00327 NSRect planetViewBounds;
00328 Planet *planet;
00329 NSPoint centreOfGameBounds = [self centreOfRect:gameBounds];
00330
00331
00332
00333 int maxFuse = [self maxFuseForPlanet];
00334
00335 for (int i = 0; i < UNIVERSE_MAX_PLANETS; i++) {
00336 planet = [universe planetWithId:i];
00337
00338
00339
00340
00341
00342 if ((!simple) &&([planet fuse] >= maxFuse)) {
00343
00344 [planet setFuse:0];
00345 }
00346
00347
00348
00349
00350
00351
00352 planetGameBounds.origin = [planet predictedPosition];
00353 planetGameBounds.size = [planet size];
00354
00355 planetGameBounds.origin.x -= planetGameBounds.size.width / 2;
00356 planetGameBounds.origin.y -= planetGameBounds.size.height / 2;
00357
00358
00359 planetViewBounds.size = [self viewSizeFromGameSize: planetGameBounds.size withScale: scale];
00360 planetViewBounds.origin = [self viewPointFromGamePoint: planetGameBounds.origin
00361 viewRect:viewBounds
00362 gamePosInCentreOfView:centreOfGameBounds
00363 withScale:scale];
00364
00365
00366 if (!NSIntersectsRect(planetViewBounds, drawingBounds)) {
00367 continue;
00368 }
00369
00370
00371 [self drawPlanet: planet inRect:planetViewBounds];
00372 if (!simple) {
00373 [planet increaseFuse];
00374
00375 }
00376
00377
00378 [self drawLabelForPlanet:planet belowRect:planetViewBounds];
00379 }
00380
00381 }
00382
00383 - (void)drawPlayersInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00384
00385 NSRect playerGameBounds;
00386 NSRect playerViewBounds;
00387 Player *player;
00388 Player *me = [universe playerThatIsMe];
00389 NSPoint centreOfGameBounds = [self centreOfRect:gameBounds];
00390
00391 for (int i = 0; i < UNIVERSE_MAX_PLAYERS; i++) {
00392 player = [universe playerWithId:i];
00393
00394
00395 if (([player status] != PLAYER_ALIVE && [player status] != PLAYER_EXPLODE) || ([player flags] & PLAYER_OBSERV) != 0) {
00396 [player setPreviousStatus:[player status]];
00397 continue;
00398 }
00399
00400
00401 if (([player flags] & PLAYER_CLOAK) != 0) {
00402 if ([player cloakPhase] < (PLAYER_CLOAK_PHASES - 1)) {
00403 if([player isMe] && [player cloakPhase] == 0) {
00404 [notificationCenter postNotificationName:@"PL_CLOAKING" userInfo:[NSNumber numberWithBool:YES]];
00405 }
00406 [player increaseCloakPhase];
00407 }
00408 }
00409 else if ([player cloakPhase] > 0) {
00410 if ([player cloakPhase] == PLAYER_CLOAK_PHASES - 1) {
00411
00412 if ([player isMe]) {
00413 [notificationCenter postNotificationName:@"PL_UNCLOAKING" userInfo:[NSNumber numberWithBool:NO]];
00414 }
00415 }
00416 else {
00417
00418
00419 }
00420 [player decreaseCloakPhase];
00421 }
00422
00423
00424
00425
00426
00427
00428 if ([player fuse] >= [player maxfuse]) {
00429
00430 if (([player status] == PLAYER_EXPLODE) &&
00431 ([player previousStatus] == PLAYER_EXPLODE)) {
00432
00433 if ([player isMe]) {
00434 [notificationCenter postNotificationName:@"PL_I_DIED" userInfo:player];
00435 }
00436
00437 [player setStatus:PLAYER_OUTFIT];
00438
00439 [player setFuse:0];
00440 [player setMaxFuse:[self maxFuseForMovingPlayer]];
00441
00442 continue;
00443 }
00444
00445
00446 [player setFuse:0];
00447 }
00448
00449
00450 if (([player status] == PLAYER_EXPLODE) &&
00451 ([player previousStatus] != PLAYER_EXPLODE)) {
00452
00453 [player setFuse:0];
00454 [player setMaxFuse:[self maxFuseForExplodingPlayer]];
00455
00456 [notificationCenter postNotificationName:@"PL_PLAYER_EXPLODED" userInfo:player];
00457 }
00458
00459
00460
00461 [player setPreviousStatus:[player status]];
00462
00463
00464
00465
00466
00467
00468 playerGameBounds.origin = [player predictedPosition];
00469 playerGameBounds.size = [[player ship] size];
00470
00471 playerGameBounds.origin.x -= playerGameBounds.size.width / 2;
00472 playerGameBounds.origin.y -= playerGameBounds.size.height / 2;
00473
00474
00475 playerViewBounds.size = [self viewSizeFromGameSize: playerGameBounds.size withScale: scale];
00476 playerViewBounds.origin = [self viewPointFromGamePoint: playerGameBounds.origin
00477 viewRect:viewBounds
00478 gamePosInCentreOfView:centreOfGameBounds
00479 withScale:scale];
00480
00481
00482 if (!NSIntersectsRect(playerViewBounds, drawingBounds)) {
00483 continue;
00484 }
00485
00486
00487 [self rotateAndDrawPlayer: player inRect:playerViewBounds];
00488
00489 [player increaseFuse];
00490
00491
00492
00493
00494
00495
00496 [self drawLabelForPlayer:player belowRect:playerViewBounds];
00497
00498 if (simple) {
00499 continue;
00500 }
00501
00502
00503
00504
00505
00506
00507 if (([player flags] & PLAYER_SHIELD) &&
00508 !([player previousFlags] & PLAYER_SHIELD)) {
00509
00510 [notificationCenter postNotificationName:@"PL_SHIELD_UP_PLAYER" userInfo:player];
00511 }
00512 if (!([player flags] & PLAYER_SHIELD) &&
00513 ([player previousFlags] & PLAYER_SHIELD)) {
00514
00515 [notificationCenter postNotificationName:@"PL_SHIELD_DOWN_PLAYER" userInfo:player];
00516 }
00517 [player setPreviousFlags:[player flags]];
00518
00519
00520 if ([player flags] & PLAYER_SHIELD) {
00521 float shieldStrenght = 100.0;
00522 if ([player isMe]) {
00523 shieldStrenght = [player shield] * 100 / [[player ship] maxShield];
00524 }
00525 [self drawShieldWithStrenght: shieldStrenght inRect:playerViewBounds];
00526 }
00527
00528
00529 NSPoint playerPositionInView = [self viewPointFromGamePoint: [player predictedPosition]
00530 viewRect:viewBounds
00531 gamePosInCentreOfView:centreOfGameBounds
00532 withScale:scale];
00533
00534
00535
00536
00537
00538 Phaser *phaser = [universe phaserWithId:[player phaserId]];
00539 NSPoint phaserEndPoint;
00540
00541 if ([phaser status] != PHASER_FREE) {
00542 if([phaser previousStatus] == PHASER_FREE) {
00543 if ([player isMe]) {
00544 [notificationCenter postNotificationName:@"PL_MY_PHASER_FIRING" userInfo:phaser];
00545 } else {
00546 [notificationCenter postNotificationName:@"PL_OTHER_PHASER_FIRING" userInfo:phaser];
00547 }
00548 }
00549
00550 float compute;
00551 switch ([phaser status]) {
00552 case PHASER_MISS:
00553
00554 compute = PHASER_MAX_DISTANCE * ([[player ship] phaserDamage ] / 100.0f);
00555
00556
00557
00558
00559
00560
00561 phaserEndPoint.x = (int)([player predictedPosition].x + (int)(compute * sinf([phaser dirInRad])));
00562 phaserEndPoint.y = (int)([player predictedPosition].y - (int)(compute * cosf([phaser dirInRad])));
00563 break;
00564
00565 case PHASER_HIT2:
00566 phaserEndPoint = [phaser predictedPosition];
00567 break;
00568 default:
00569 phaserEndPoint = [[phaser target] predictedPosition];
00570 break;
00571 }
00572
00573 NSPoint phaserStartPoint =[player predictedPosition];
00574
00575 if (phaserStartPoint.x != phaserEndPoint.x || phaserStartPoint.y != phaserEndPoint.y) {
00576 if ([phaser status] == PHASER_MISS || (([phaser fuse] % 2) == 0) || [player team] != [me team]) {
00577
00578 [[self colorForTeam:[player team]] set];
00579 }
00580 else {
00581 [[NSColor whiteColor] set];
00582 }
00583
00584
00585 phaserStartPoint = playerPositionInView;
00586
00587 phaserEndPoint = [self viewPointFromGamePoint: phaserEndPoint
00588 viewRect:viewBounds
00589 gamePosInCentreOfView:centreOfGameBounds
00590 withScale:scale];
00591
00592
00593
00594 [line removeAllPoints];
00595 [line moveToPoint:phaserStartPoint];
00596 [line lineToPoint:phaserEndPoint];
00597 [line stroke];
00598
00599
00600 [phaser increaseFuse];
00601 if([phaser fuse] > [phaser maxfuse]) {
00602 [phaser setStatus: PHASER_FREE];
00603 }
00604 }
00605 }
00606
00607
00608 [phaser setPreviousStatus:[phaser status]];
00609
00610
00611
00612
00613
00614
00615
00616 if(([player flags] & (PLAYER_TRACT | PLAYER_PRESS)) == 0 || [player status] != PLAYER_ALIVE) {
00617 continue;
00618 }
00619
00620
00621 Player *tractee = [player tractorTarget];
00622 if(tractee == nil) {
00623 continue;
00624 }
00625
00626
00627 if ([tractee status] != PLAYER_ALIVE) {
00628
00629
00630 continue;
00631 }
00632
00633 NSPoint tractorStartPoint = playerPositionInView;
00634 NSPoint tractorEndPoint = [self viewPointFromGamePoint: [tractee predictedPosition]
00635 viewRect:viewBounds
00636 gamePosInCentreOfView:centreOfGameBounds
00637 withScale:scale];
00638 if (tractorStartPoint.x == tractorEndPoint.x && tractorStartPoint.y == tractorEndPoint.y) {
00639 continue;
00640 }
00641
00642
00643
00644
00645
00646 double theta = atan2((double)(tractorEndPoint.x - tractorStartPoint.x),
00647 (double)(tractorStartPoint.y - tractorEndPoint.y)) + pi / 2.0;
00648
00649
00650
00651
00652
00653
00654
00655 if ([player flags] & PLAYER_PRESS) {
00656 [[NSColor purpleColor] set];
00657 } else {
00658 [[NSColor greenColor] set];
00659 }
00660
00661 NSSize tracteeSize = [self viewSizeFromGameSize: [[tractee ship] size] withScale: scale];
00662 int width = tracteeSize.width;
00663 int height = tracteeSize.height;
00664 double maxDim = ( width > height ? width : height) / 2.0;
00665 int yOffset = (int)(cos(theta) * maxDim);
00666 int xOffset = (int)(sin(theta) * maxDim);
00667
00668
00669
00670
00671 NSPoint p1 = NSMakePoint(tractorEndPoint.x + xOffset, tractorEndPoint.y + yOffset);
00672 NSPoint p2 = NSMakePoint(tractorEndPoint.x - xOffset, tractorEndPoint.y - yOffset);
00673 [dashedLine removeAllPoints];
00674 [dashedLine moveToPoint:p1];
00675 [dashedLine lineToPoint:tractorStartPoint];
00676 [dashedLine lineToPoint:p2];
00677 [dashedLine stroke];
00678 }
00679 }
00680
00681 - (void)drawTorpsInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00682
00683 NSRect torpGameBounds;
00684 NSRect torpViewBounds;
00685 Player *player;
00686 NSPoint centreOfGameBounds = [self centreOfRect:gameBounds];
00687
00688
00689 for (int i = 0; i < UNIVERSE_MAX_PLAYERS; i++) {
00690 player = [universe playerWithId:i];
00691
00692 NSArray *torps = [player torps];
00693 int freeTorps = UNIVERSE_MAX_TORPS;
00694 for (int t = 0; t < [torps count]; t++) {
00695
00696 Torp *torp = [torps objectAtIndex:t];
00697
00698
00699 if ([torp status] == TORP_FREE) {
00700 [torp setPreviousStatus:[torp status]];
00701 continue;
00702 }
00703
00704 freeTorps--;
00705
00706
00707
00708
00709
00710
00711
00712 if ([torp fuse] >= [torp maxfuse]) {
00713
00714 if (([torp status] == TORP_EXPLODE) &&
00715 ([torp previousStatus] == TORP_EXPLODE)) {
00716
00717 [torp setStatus:TORP_FREE];
00718
00719 [torp setFuse:0];
00720 [torp setMaxFuse:[self maxFuseForMovingTorp]];
00721
00722 continue;
00723 }
00724
00725
00726 [torp setFuse:0];
00727 }
00728
00729
00730 if (([torp status] == TORP_MOVE) &&
00731 ([torp previousStatus] != TORP_MOVE)) {
00732
00733 [torp setFuse:0];
00734 [torp setMaxFuse:[self maxFuseForMovingTorp]];
00735
00736 if ([player isMe]) {
00737 [notificationCenter postNotificationName:@"PL_TORP_FIRED_BY_ME" userInfo:torp];
00738 } else {
00739 [notificationCenter postNotificationName:@"PL_TORP_FIRED_BY_OTHER" userInfo:torp];
00740 }
00741 }
00742
00743
00744 if (([torp status] == TORP_EXPLODE) &&
00745 ([torp previousStatus] != TORP_EXPLODE)) {
00746
00747 [torp setFuse:0];
00748 [torp setMaxFuse:[self maxFuseForExplodingTorp]];
00749
00750 [notificationCenter postNotificationName:@"PL_TORP_EXPLODED" userInfo:torp];
00751 }
00752
00753
00754
00755 [torp setPreviousStatus:[torp status]];
00756
00757
00758
00759
00760
00761
00762 torpGameBounds.origin = [torp predictedPosition];
00763 if ([torp status] == TORP_EXPLODE) {
00764 torpGameBounds.size = [torp explosionSize];
00765 } else {
00766 torpGameBounds.size = [torp size];
00767 }
00768
00769 torpGameBounds.origin.x -= torpGameBounds.size.width / 2;
00770 torpGameBounds.origin.y -= torpGameBounds.size.height / 2;
00771
00772
00773 torpViewBounds.size = [self viewSizeFromGameSize: torpGameBounds.size withScale: scale];
00774 torpViewBounds.origin = [self viewPointFromGamePoint: torpGameBounds.origin
00775 viewRect:viewBounds
00776 gamePosInCentreOfView:centreOfGameBounds
00777 withScale:scale];
00778
00779
00780 if (!NSIntersectsRect(torpViewBounds, drawingBounds)) {
00781 continue;
00782 }
00783
00784
00785 [self drawTorp: torp inRect:torpViewBounds];
00786
00787
00788 [torp increaseFuse];
00789 }
00790 [player setTorpCount:freeTorps];
00791 }
00792 }
00793
00794 - (void)drawPlasmasInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00795
00796 NSRect plasmaGameBounds;
00797 NSRect plasmaViewBounds;
00798 Player *player;
00799 NSPoint centreOfGameBounds = [self centreOfRect:gameBounds];
00800
00801
00802 for (int i = 0; i < UNIVERSE_MAX_PLAYERS; i++) {
00803 player = [universe playerWithId:i];
00804 Plasma *plasma = [universe plasmaWithId:[player plasmaId]];
00805
00806 if ([plasma status] == PLASMA_FREE) {
00807 [plasma setPreviousStatus:[plasma status]];
00808 continue;
00809 }
00810
00811
00812
00813
00814
00815
00816 if ([plasma fuse] >= [plasma maxfuse]) {
00817
00818 if (([plasma status] == PLASMA_EXPLODE) &&
00819 ([plasma previousStatus] == PLASMA_EXPLODE)) {
00820
00821 [plasma setStatus:PLASMA_FREE];
00822
00823 [plasma setFuse:0];
00824 [plasma setMaxFuse:[self maxFuseForMovingPlasma]];
00825
00826 continue;
00827 }
00828
00829
00830 [plasma setFuse:0];
00831 }
00832
00833
00834 if (([plasma status] == PLASMA_MOVE) &&
00835 ([plasma previousStatus] != PLASMA_MOVE)) {
00836
00837 [plasma setFuse:0];
00838 [plasma setMaxFuse:[self maxFuseForMovingPlasma]];
00839
00840 if ([player isMe]) {
00841 [notificationCenter postNotificationName:@"PL_PLASMA_FIRED_BY_ME" userInfo:plasma];
00842 } else {
00843 [notificationCenter postNotificationName:@"PL_PLASMA_FIRED_BY_OTHER" userInfo:plasma];
00844 }
00845 }
00846
00847
00848 if (([plasma status] == PLASMA_EXPLODE) &&
00849 ([plasma previousStatus] != PLASMA_EXPLODE)) {
00850
00851 [plasma setFuse:0];
00852 [plasma setMaxFuse:[self maxFuseForExplodingPlasma]];
00853
00854 [notificationCenter postNotificationName:@"PL_PLASMA_EXPLODED" userInfo:plasma];
00855 }
00856
00857
00858
00859 [plasma setPreviousStatus:[plasma status]];
00860
00861
00862
00863
00864
00865
00866 plasmaGameBounds.origin = [plasma predictedPosition];
00867 if ([plasma status] == PLASMA_EXPLODE) {
00868 plasmaGameBounds.size = [plasma explosionSize];
00869 } else {
00870 plasmaGameBounds.size = [plasma size];
00871 }
00872
00873 plasmaGameBounds.origin.x -= plasmaGameBounds.size.width / 2;
00874 plasmaGameBounds.origin.y -= plasmaGameBounds.size.height / 2;
00875
00876
00877 plasmaViewBounds.size = [self viewSizeFromGameSize: plasmaGameBounds.size withScale: scale];
00878 plasmaViewBounds.origin = [self viewPointFromGamePoint: plasmaGameBounds.origin
00879 viewRect:viewBounds
00880 gamePosInCentreOfView:centreOfGameBounds
00881 withScale:scale];
00882
00883
00884 if (!NSIntersectsRect(plasmaViewBounds, drawingBounds)) {
00885 continue;
00886 }
00887
00888
00889 [self drawPlasma: plasma inRect:plasmaViewBounds];
00890
00891
00892 [plasma increaseFuse];
00893 }
00894 }
00895
00896 - (void)drawLockInRect:(NSRect)drawingBounds forGameRect:(NSRect)gameBounds ofViewBounds:(NSRect)viewBounds withScale:(int)scale {
00897
00898 Player *me = [universe playerThatIsMe];
00899 NSPoint triangleViewPoint;
00900 NSPoint triangleGamePoint;
00901
00902
00903 [[NSColor whiteColor] set];
00904
00905
00906 if ((([me flags] & PLAYER_PLOCK) != 0) ||
00907 (([me flags] & PLAYER_PLLOCK) != 0)) {
00908
00909 if (([me flags] & PLAYER_PLOCK) != 0) {
00910
00911 Player *player = [me playerLock];
00912
00913 if (([player flags] & PLAYER_CLOAK) == 0) {
00914
00915 if (NSPointInRect([player predictedPosition], gameBounds)) {
00916
00917 triangleGamePoint = [player predictedPosition];
00918
00919 triangleGamePoint.y -= [[player ship] size].height / 2;
00920 triangleViewPoint = [self viewPointFromGamePoint:triangleGamePoint
00921 viewRect:viewBounds
00922 gamePosInCentreOfView:[self centreOfRect:gameBounds]
00923 withScale:scale];
00924 } else {
00925 return;
00926 }
00927 } else {
00928 return;
00929 }
00930 } else {
00931
00932 Planet *planet = [me planetLock];
00933
00934 if (NSPointInRect([planet predictedPosition], gameBounds)) {
00935
00936 triangleGamePoint = [planet predictedPosition];
00937
00938 triangleGamePoint.y -= [planet size].height / 2;
00939 triangleViewPoint = [self viewPointFromGamePoint:triangleGamePoint
00940 viewRect:viewBounds
00941 gamePosInCentreOfView:[self centreOfRect:gameBounds]
00942 withScale:scale];
00943 } else {
00944 return;
00945 }
00946 }
00947
00948
00949 NSRect rect;
00950 rect.size.width = (PF_TRIANGLE_WIDTH) / scale;
00951 rect.size.height = (PF_TRIANGLE_HEIGHT) / scale;
00952
00953 rect.origin.x = triangleViewPoint.x - rect.size.width / 2;
00954 rect.origin.y = triangleViewPoint.y - rect.size.height;
00955
00956
00957 if (!NSIntersectsRect(rect, drawingBounds)) {
00958 return;
00959 }
00960
00961 [shapes drawTriangleNotchDownInRect:rect];
00962 }
00963 }
00964
00965 - (void) drawRect:(NSRect)drawingBounds ofViewBounds:(NSRect)viewBounds whichRepresentsGameBounds:(NSRect)gameBounds
00966 withScale:(int)scale {
00967
00968
00969 Player *me = [universe playerThatIsMe];
00970
00971
00972
00973
00974
00975 static NSTimeInterval start, stop;
00976 start = [NSDate timeIntervalSinceReferenceDate];
00977 if ((start-stop) > 0.1) {
00978 NSLog(@"PainterFactory.drawView: slept %f sec", (start-stop));
00979 }
00980
00981
00982
00983
00984 if (!simple) {
00985 [self drawAlertBorder:viewBounds forMe:me];
00986 }
00987
00988
00989
00990 viewBounds = NSInsetRect(viewBounds, PF_ALERT_BORDER_WIDTH, PF_ALERT_BORDER_WIDTH);
00991
00992
00993 [[NSBezierPath bezierPathWithRect:viewBounds] addClip];
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 if (!simple) {
01009 [self drawBackgroundInRect:drawingBounds ofViewBounds:viewBounds forMe:me];
01010 }
01011
01012
01013
01014
01015
01016 [self drawGalaxyEdgesInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01017
01018
01019
01020
01021 [self drawPlanetsInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01022
01023
01024
01025
01026
01027 [self drawPlayersInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01028
01029
01030
01031
01032 if (!simple) {
01033 [self drawTorpsInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01034 }
01035
01036
01037
01038
01039 if (!simple) {
01040 [self drawPlasmasInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01041 }
01042
01043
01044
01045
01046 [self drawLockInRect:drawingBounds forGameRect:gameBounds ofViewBounds:viewBounds withScale:scale];
01047
01048
01049
01050
01051 stop = [NSDate timeIntervalSinceReferenceDate];
01052 if ((stop - start) > 0.1) {
01053 NSLog(@"PainterFactory.drawView: %f sec", (stop-start));
01054 }
01055
01056 }
01057
01058 - (void) rotateAndDrawPlayer:(Player*) player inRect:(NSRect) Rect {
01059
01060 float course = [player course];
01061
01062
01063
01064 [[NSGraphicsContext currentContext] saveGraphicsState];
01065
01066
01067 NSAffineTransform *transform = [NSAffineTransform transform];
01068
01069
01070 NSPoint center = [self centreOfRect:Rect];
01071
01072 [transform translateXBy:center.x yBy:center.y];
01073 [transform rotateByDegrees:course];
01074
01075 [transform concat];
01076
01077
01078 Rect.origin = NSZeroPoint;
01079 [self drawPlayer:player inRect:[shapes createRectAroundOrigin:Rect]];
01080
01081
01082 [transform invert];
01083 [transform concat];
01084 [[NSGraphicsContext currentContext] restoreGraphicsState];
01085 }
01086
01087
01088
01089
01090
01091 - (void) drawPlayer:(Player*) player inRect:(NSRect) Rect {
01092
01093
01094
01095
01096 NSColor *col = [self colorForTeam:[player team]];
01097 if ([player cloakPhase] > 0) {
01098
01099
01100 float alpha = 1.0;
01101 alpha -= (((1.0 - PF_MIN_ALPHA_VALUE) * [player cloakPhase]) / PLAYER_CLOAK_PHASES);
01102 col = [col colorWithAlphaComponent:alpha];
01103 }
01104
01105 [col set];
01106
01107
01108
01109 [shapes drawSpaceShipInRect:NSInsetRect(Rect, Rect.size.width*0.1515, Rect.size.height*0.1515)];
01110
01111
01112
01113
01114
01115
01116 }
01117
01118 - (void) drawShieldWithStrenght: (float)shieldPercentage inRect:(NSRect) Rect {
01119
01120
01121 NSPoint centre = [self centreOfRect:Rect];
01122
01123 float radius = (Rect.size.width / 2) + 1;
01124
01125
01126 NSColor *shieldColor = [NSColor greenColor];
01127 if (shieldPercentage < 50.0) {
01128 shieldColor = [NSColor yellowColor];
01129 }
01130 if (shieldPercentage < 25.0) {
01131 shieldColor = [NSColor redColor];
01132 }
01133
01134
01135 float angle = (360.0 * shieldPercentage / 100);
01136
01137
01138
01139
01140 [shieldColor set];
01141
01142
01143 [line removeAllPoints];
01144 [line appendBezierPathWithArcWithCenter:centre radius:radius startAngle:0.0 endAngle:angle];
01145 [line stroke];
01146
01147 if (angle < 360.0) {
01148 [dashedLine removeAllPoints];
01149 [dashedLine appendBezierPathWithArcWithCenter:centre radius:radius startAngle:angle endAngle:360.0];
01150 [dashedLine stroke];
01151 }
01152
01153 }
01154
01155 - (void) drawPlanet:(Planet*) planet inRect:(NSRect) Rect {
01156
01157
01158
01159 [[self colorForTeam:[planet owner]] set];
01160
01161 [shapes drawDoubleCircleInRect:Rect];
01162 }
01163
01164 - (void) drawTorp:(Torp*) torp inRect:(NSRect) Rect {
01165
01166 [[self colorForTeam:[[torp owner] team]] set];
01167
01168
01169 float delta = 0.0;
01170
01171 if ([torp status] == TORP_EXPLODE) {
01172 delta += [torp fuse] * Rect.size.width;
01173 } else {
01174 delta += [torp fuse] * Rect.size.width / 2;
01175 }
01176
01177 Rect = NSInsetRect(Rect, -delta, -delta);
01178
01179
01180
01181
01182 [shapes drawCircleInRect:Rect];
01183 }
01184
01185 - (void) drawPlasma:(Plasma*) plasma inRect:(NSRect) Rect {
01186
01187
01188
01189 [[self colorForTeam:[plasma team]] set];
01190
01191 [shapes drawCircleInRect:Rect];
01192 }
01193
01194 - (void) drawBackgroundImageInRect:(NSRect) Rect {
01195
01196
01197
01198 }
01199
01200 - (void) drawLabelForPlanet:(Planet*)planet belowRect:(NSRect)planetViewBounds {
01201
01202
01203 NSString *label = [NSString stringWithString:[planet nameWithArmiesIndicator]];
01204
01205
01206 if ([planet showInfo] || debugLabels) {
01207 label = [NSString stringWithFormat:@"%@ %d [%c%c%c]",
01208 [planet name],
01209 [planet armies],
01210 ([planet flags] & PLANET_REPAIR ? 'R' : '-'),
01211 ([planet flags] & PLANET_FUEL ? 'F' : '-'),
01212 ([planet flags] & PLANET_AGRI ? 'A' : '-')
01213 ];
01214 }
01215
01216 [[NSColor whiteColor] set];
01217 NSPoint namePosition = planetViewBounds.origin;
01218 namePosition.y += planetViewBounds.size.height ;
01219
01220 int labelWidth = [label sizeWithAttributes:normalStateAttribute].width;
01221 namePosition.x += (planetViewBounds.size.width - labelWidth) / 2;
01222
01223 [label drawAtPoint: namePosition withAttributes:normalStateAttribute];
01224 }
01225
01226 - (void) drawLabelForPlayer:(Player*)player belowRect:(NSRect)playerViewBounds {
01227
01228
01229 NSString *label = [NSString stringWithFormat:@"%@", [player mapCharsWithKillIndicator]];
01230
01231
01232 if ([player showInfo] || debugLabels) {
01233 label = [NSString stringWithFormat:@"%@ %d(%d) %d %d [%c%c%c%c%c%c] %d %@",
01234 [player longNameWithKillIndicator],
01235 [player speed],
01236 [player requestedSpeed],
01237 [player kills],
01238 [player armies],
01239 ([player flags] & PLAYER_REPAIR ? 'R' : '-'),
01240 ([player flags] & PLAYER_BOMB ? 'B' : '-'),
01241 ([player flags] & PLAYER_ORBIT ? 'O' : '-'),
01242 ([player flags] & PLAYER_CLOAK ? 'C' : '-'),
01243 ([player flags] & PLAYER_BEAMUP ? 'U' : '-'),
01244 ([player flags] & PLAYER_BEAMDOWN ? 'D' : '-'),
01245 [player cloakPhase],
01246 (debugLabels ? [[player statusString] substringFromIndex:7] : @"")
01247 ];
01248 }
01249
01250 [[NSColor whiteColor] set];
01251 NSPoint namePosition = playerViewBounds.origin;
01252 int labelHeight = [label sizeWithAttributes:normalStateAttribute].height;
01253 namePosition.y += playerViewBounds.size.height;
01254
01255 int labelWidth = [label sizeWithAttributes:normalStateAttribute].width;
01256 namePosition.x += (playerViewBounds.size.width - labelWidth) / 2;
01257
01258 [label drawAtPoint: namePosition withAttributes:normalStateAttribute];
01259
01260 if (debugLabels) {
01261
01262 NSArray *torps = [player torps];
01263 label = [NSString stringWithFormat:@"T[%c(%c)%c%c%c%c%c%c%c] F[%d%d%d%d%d%d%d%d]",
01264 [[torps objectAtIndex:0] statusChar],
01265 [[torps objectAtIndex:0] previousStatusChar],
01266 [[torps objectAtIndex:1] statusChar],
01267 [[torps objectAtIndex:2] statusChar],
01268 [[torps objectAtIndex:3] statusChar],
01269 [[torps objectAtIndex:4] statusChar],
01270 [[torps objectAtIndex:5] statusChar],
01271 [[torps objectAtIndex:6] statusChar],
01272 [[torps objectAtIndex:7] statusChar],
01273 [[torps objectAtIndex:0] fuse],
01274 [[torps objectAtIndex:1] fuse],
01275 [[torps objectAtIndex:2] fuse],
01276 [[torps objectAtIndex:3] fuse],
01277 [[torps objectAtIndex:4] fuse],
01278 [[torps objectAtIndex:5] fuse],
01279 [[torps objectAtIndex:6] fuse],
01280 [[torps objectAtIndex:7] fuse]];
01281
01282 namePosition.y += labelHeight;
01283 [label drawAtPoint: namePosition withAttributes:normalStateAttribute];
01284
01285
01286 Plasma *plasma = [universe plasmaWithId:[player plasmaId]];
01287 Phaser *phaser = [universe phaserWithId:[player phaserId]];
01288 label = [NSString stringWithFormat:@"PH[%c][%d] PL[%c][%d]",
01289 [phaser statusChar],
01290 [phaser fuse],
01291 [plasma statusChar],
01292 [plasma fuse]];
01293
01294 namePosition.y += labelHeight;
01295 [label drawAtPoint: namePosition withAttributes:normalStateAttribute];
01296 }
01297 }
01298
01299 - (int) maxFuseForMovingTorp {
01300 return 2;
01301 }
01302
01303 - (int) maxFuseForExplodingTorp {
01304 return 10;
01305 }
01306
01307
01308 - (int) maxFuseForMovingPlasma {
01309 return 3;
01310 }
01311
01312 - (int) maxFuseForExplodingPlasma {
01313 return 12;
01314 }
01315
01316 - (int) maxFuseForMovingPlayer {
01317 return 1;
01318 }
01319
01320 - (int) maxFuseForExplodingPlayer {
01321 return 10;
01322 }
01323
01324 - (int) maxFuseForPlanet {
01325 return 1;
01326 }
01327
01328 @end