This is collisions.m in view mode; [Download] [Up]
#import "collisions.h" #import "Actor.h" #import "ActorMgr.h" #import "DisplayManager.h" #import "CacheManager.h" BOOL intersectsRect(NXRect *r1, NXRect *r2) { if ((NX_X(r1) > NX_MAXX(r2)) || (NX_X(r2) > NX_MAXX(r1)) || (NX_Y(r1) > NX_MAXY(r2)) || ((NX_Y(r2) > NX_MAXY(r1)))) return NO; return YES; } BOOL intersectsCircle(Actor *a1, Actor *a2) { float dx, dy, dist, sumrad; dx = a1->x - a2->x; dy = a1->y - a2->y; dist = dx*dx + dy*dy; sumrad = (a1->radius + a2->radius); if (dist > (sumrad * sumrad)) return NO; return YES; } void circleToLines(Actor *a1, NXPoint *pt) { pt[0].x = pt[2].x = pt[4].x = a1->x; pt[1].y = pt[3].y = a1->y; pt[0].y = pt[4].y = a1->y - a1->radius; pt[2].y = a1->y + a1->radius; pt[1].x = a1->x + a1->radius; pt[3].x = a1->x - a1->radius; } #define MINRECTSIZE 11 void rectToLines(NXRect *rO, NXPoint *pt, int minSize) { NXRect r = *rO; if (r.size.width < minSize) { r.origin.x -= (minSize-r.size.width)/2.0; r.size.width = minSize; } if (r.size.height < minSize) { r.origin.y -= (minSize-r.size.height)/2.0; r.size.height = minSize; } pt[0].x = pt[3].x = pt[4].x = r.origin.x; pt[0].y = pt[4].y = pt[1].y = r.origin.y; pt[1].x = pt[2].x = r.origin.x + r.size.width; pt[2].y = pt[3].y = r.origin.y + r.size.height; } // a macro for determining which side of a line a point is on // returns 0 for points on the line static inline float xSign(float px, float py, float lx1, float ly1, float lx2, float ly2) { return ((ly2 - ly1) * (px - lx1)) - ((lx2 - lx1) * (py - ly1)); } // macros for the points of 2 lines #define P1 ln1->x1,ln1->y1 #define P2 ln1->x2,ln1->y2 #define P3 ln2->x1,ln2->y1 #define P4 ln2->x2,ln2->y2 #define L1 P1,P2 #define L2 P3,P4 #define XDEBUG 0 XXLine *gln1, *gln2; // lines intersect if the end points of each line are on opposite sides // of the other line. Look ma, no division, no slope or parallel problems BOOL linesCollide(XXLine *ln1, int cnt1, BOOL packed1, XXLine *ln2s, int cnt2, BOOL packed2) { int i,j; NXPoint *tpp; for (i=0; i<cnt1; i++) { XXLine *ln2 = ln2s; for (j=0; j<cnt2; j++) { #if XDEBUG { float x1,y1,x2,y2; x1 = ln1->x1 - gx + xOffset; y1 = ln1->y1 - gy + yOffset; x2 = ln1->x2 - gx + xOffset; y2 = ln1->y2 - gy + yOffset; PSgsave(); PSsetrgbcolor(.1,.2,.6); PSnewpath(); PSmoveto(x1,y1); PSlineto(x2,y2); x1 = ln2->x1 - gx + xOffset; y1 = ln2->y1 - gy + yOffset; x2 = ln2->x2 - gx + xOffset; y2 = ln2->y2 - gy + yOffset; PSmoveto(x1,y1); PSlineto(x2,y2); PSstroke(); PSgrestore(); } #endif if (((xSign(P1,L2)*xSign(P2,L2)) <= 0) && ((xSign(P3,L1)*xSign(P4,L1)) <= 0)) { // lines intersect gln1 = ln1; gln2 = ln2; return YES; } if (packed2) { tpp = (NXPoint *)ln2; tpp++; ln2 = (XXLine *)tpp; } else ln2++; } if (packed1) { tpp = (NXPoint *)ln1; tpp++; ln1 = (XXLine *)tpp; } else ln1++; } return NO; } BOOL actorsCollide(Actor *a1, Actor *a2) { Actor *a3; int i,j; // if (a1->alliance == a2->alliance || if (a1 == a2 || a1->alliance == NEUTRAL || a2->alliance == NEUTRAL || !a1->employed || !a2->employed || !intersectsRect(&a1->collisionRect,&a2->collisionRect)) return NO; if (a2->collisionShape < a1->collisionShape) { a3=a1;a1=a2;a2=a3; } a1->collisionThing = a2; a2->collisionThing = a1; switch(a1->collisionShape) { case NOSHAPE: return NO; break; case RECTCIRC: switch(a2->collisionShape) { case RECTCIRC: case RECT: a1->collisionReason = a2->collisionReason = ACTORSRECT; return YES; case RECTARRAY: if (!a2->complexShapePtr) [a2 constructComplexShape]; for (i=0; i<a2->complexShapeCnt; i++) { if (intersectsRect(&a1->collisionRect,a2->complexShapePtr+i)) { a1->collisionReason = XRECT; a1->collisionThing = a2->complexShapePtr+i; a2->collisionReason = ACTORSRECT; return YES; } } return NO; case CIRCLE: if (intersectsCircle(a1,a2)) { a1->collisionReason = a2->collisionReason = ACTORSCIRC; return YES; } return NO; case LINEARRAY: if (!a1->complexShapePtr) { rectToLines(&a1->collisionRect,a1->shapeArray, MINRECTSIZE); a1->complexShapePtr = (NXRect *)a1->shapeArray; } if (!a2->complexShapePtr) [a2 constructComplexShape]; if (linesCollide((XXLine *)a1->shapeArray,4,YES, (XXLine *)a2->complexShapePtr,a2->complexShapeCnt,NO)) { a1->collisionReason = a2->collisionReason = XLINE; a1->collisionThing = gln2; a2->collisionThing = gln1; return YES; } return NO; default: return NO; } break; case RECT: switch(a2->collisionShape) { case RECT: a1->collisionReason = a2->collisionReason = ACTORSRECT; return YES; case RECTARRAY: if (!a2->complexShapePtr) [a2 constructComplexShape]; for (i=0; i<a2->complexShapeCnt; i++) { if (intersectsRect(&a1->collisionRect,a2->complexShapePtr+i)) { a1->collisionReason = XRECT; a1->collisionThing = a2->complexShapePtr+i; a2->collisionReason = ACTORSRECT; return YES; } } return NO; case CIRCLE: if (!a1->complexShapePtr) { rectToLines(&a1->collisionRect,a1->shapeArray, MINRECTSIZE); a1->complexShapePtr = (NXRect *)a1->shapeArray; } if (!a2->complexShapePtr) { circleToLines(a2,a2->shapeArray); a2->complexShapePtr = (NXRect *)a2->shapeArray; } if (linesCollide((XXLine *)a1->complexShapePtr,4,YES, (XXLine *)a2->complexShapePtr,4,YES)) { a1->collisionReason = a2->collisionReason = XLINE; a1->collisionThing = gln2; a2->collisionThing = gln1; return YES; } return NO; case LINEARRAY: if (!a1->complexShapePtr) { rectToLines(&a1->collisionRect,a1->shapeArray, MINRECTSIZE); a1->complexShapePtr = (NXRect *)a1->shapeArray; } if (!a2->complexShapePtr) [a2 constructComplexShape]; if (linesCollide((XXLine *)a1->complexShapePtr,4,YES, (XXLine *)a2->complexShapePtr,a2->complexShapeCnt,NO)) { a1->collisionReason = a2->collisionReason = XLINE; a1->collisionThing = gln2; a2->collisionThing = gln1; return YES; } return NO; default: return NO; } break; case RECTARRAY: if (!a1->complexShapePtr) [a1 constructComplexShape]; switch(a2->collisionShape) { case RECTARRAY: if (!a2->complexShapePtr) [a2 constructComplexShape]; for (i=0; i<a1->complexShapeCnt; i++) { for (j=0; j<a2->complexShapeCnt; j++) { if (intersectsRect(a1->complexShapePtr+i,a2->complexShapePtr+j)) { a1->collisionReason = a2->collisionReason = XRECT; a1->collisionThing = a2->complexShapePtr+j; a2->collisionThing = a1->complexShapePtr+i; return YES; } } } return NO; case CIRCLE: if (!a2->complexShapePtr) { circleToLines(a2,a2->shapeArray); a2->complexShapePtr = (NXRect *)a2->shapeArray; } for (i=0; i<a1->complexShapeCnt; i++) { rectToLines(a1->complexShapePtr+i,a1->shapeArray, MINRECTSIZE); if (linesCollide((XXLine *)a1->shapeArray,4,YES, (XXLine *)a2->complexShapePtr,4,YES)) { a1->collisionReason = a2->collisionReason = XLINE; a1->collisionThing = gln2; a2->collisionThing = gln1; return YES; } } return NO; case LINEARRAY: if (!a2->complexShapePtr) [a2 constructComplexShape]; for (i=0; i<a1->complexShapeCnt; i++) { rectToLines(a1->complexShapePtr+i,a1->shapeArray, MINRECTSIZE); if (linesCollide((XXLine *)a1->shapeArray,4,YES, (XXLine *)a2->complexShapePtr, a2->complexShapeCnt,NO)) { a1->collisionReason = a2->collisionReason = XLINE; a1->collisionThing = gln2; a2->collisionThing = gln1; return YES; } } return NO; default: return NO; } break; case CIRCLE: switch(a2->collisionShape) { case CIRCLE: return intersectsCircle(a1,a2); case LINEARRAY: if (!a1->complexShapePtr) { circleToLines(a1,a1->shapeArray); a1->complexShapePtr = (NXRect *)a1->shapeArray; } if (!a2->complexShapePtr) [a2 constructComplexShape]; if (linesCollide((XXLine *)a1->shapeArray,4,YES, (XXLine *)a2->complexShapePtr, a2->complexShapeCnt,NO)) { a1->collisionReason = a2->collisionReason = XLINE; a1->collisionThing = gln2; a2->collisionThing = gln1; return YES; } return NO; default: return NO; } break; case LINEARRAY: switch(a2->collisionShape) { case LINEARRAY: if (!a1->complexShapePtr) [a1 constructComplexShape]; if (!a2->complexShapePtr) [a2 constructComplexShape]; if (linesCollide((XXLine *)a1->shapeArray, a1->complexShapeCnt,NO, (XXLine *)a2->complexShapePtr, a2->complexShapeCnt,NO)) { a1->collisionReason = a2->collisionReason = XLINE; a1->collisionThing = gln2; a2->collisionThing = gln1; return YES; } return NO; default: return NO; } break; default: return NO; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.