This is RotBox.m in view mode; [Download] [Up]
#import "RotBox.h" #import "ActorMgr.h" #import "SoundMgr.h" #import "Explosion.h" #import "Xoxeroids.h" extern int xx_ship; @implementation RotBox - activate:sender :(int)tag { NXSize tsize = {124,149}; NXSize tsize2 = {62,75}; Actor *dude = (Actor *)sender; char *whatImage = tag ? "rotBox2" : "rotBox1"; [super activate:sender :tag]; [self reinitWithImage:whatImage frameSize:&tsize numFrames:1 shape: LINEARRAY alliance: DESTROYALL radius: tsize2.width buffered: YES x: ((!tag) ? (randBetween(gx+xOffset/2, gx+5.5*xOffset-151)) : dude->x + 150) y: ((!tag) ? (randBetween(gy+yOffset/2, gy+5.5*yOffset-61)) : dude->y + 60) theta: ((!tag) ? (randBetween(0,2*PI)) : dude->theta) vel: ((!tag) ? (randBetween(2,4)) : 0) interval: ((!tag) ? 12345678 : 10000000) distToCorner: &tsize2]; // a cave is deconstructed into 8 lines for further collision testing complexShapeCnt = 6; myBall = [actorMgr newActor:(int)[RotBall class] for:self tag:tag]; if (!tag) myBuddy = [actorMgr newActor:(int)[RotBox class] for:self tag:1]; else myBuddy = sender; return self; } - buddy { return myBuddy; } - positionChanged { [super positionChanged]; if (vel) { [self wrapAtDistance: (3*xOffset) :(3*yOffset)]; [myBuddy moveTo:(x + 150) :(y + 60)]; } [myBall moveTo:x :y]; return self; } - performCollisionWith:(Actor *) dude { // [soundMgr playSound: FUTILITYSND at:0.5]; return self; } static XXLine myShape[] = { 0,117,54,0, // left 12,109,57,16, // left mid 0,117,67,149, // top 5,104,73,136, // mid top 47,12,117,43, // mid bottom 54,0,123,31, // bottom 71,135,113,42, // right mid 67,149,123,28, // right }; - constructComplexShape { int i; int offset = ((interval == 12345678) ? 0 : 2); for (i=0; i<6; i++) { outline[i] = myShape[i+offset]; outline[i].x1 += x - 62; outline[i].x2 += x - 62; outline[i].y1 += y - 75; outline[i].y2 += y - 75; } complexShapePtr = (NXRect *)(&outline[0]); return self; } - (BOOL) doYouHurt:sender { Actor *dude = (Actor *)sender; // fix me! This should be done using dot products... // ie the reflection of vector v on line l with normal n // where l and n are normalized is and the result is v' is: // v' = (v.l)l - (v.n)n // screw these slow transcendentals... // here is the line the bullet collided with XXLine *myLine = (XXLine *)dude->collisionThing; float myAngle = atan2(myLine->y2 - myLine->y1, myLine->x2 - myLine->x1); float bulletsAngle = atan2(dude->yv,dude->xv); float newTheta = (2.0 * myAngle) - bulletsAngle - (PI/2.0); float xfactor = -sin(newTheta), yfactor = cos(newTheta); float oldVel = sqrt(dude->xv*dude->xv + dude->yv*dude->yv); // first back off bullet [dude moveBy: (-0.5 * timeScale * dude->xv) : (-0.5 * timeScale * dude->yv)]; // shots reflected around normal of collision line [dude setXvYv:oldVel * xfactor :oldVel * yfactor sync:NO]; [dude setVel:oldVel]; [dude positionChanged]; if (dude->actorType == xx_ship) return YES; [dude setTheta:newTheta]; return NO; } @end @implementation RotBall - activate:sender :(int)tag { NXSize tsize = {32,32}; NXSize tsize2 = {16,16}; Actor *dude = (Actor *)sender; [super activate:sender :tag]; [self reinitWithImage:"rotBall" frameSize:&tsize numFrames:10 shape: CIRCLE alliance: EVIL radius: tsize2.width buffered: YES x: dude->x y: dude->y theta: dude->theta vel: 0 interval: 70 distToCorner: &tsize2]; pointValue = 400; kind = tag; frame = (int) (randBetween(0,9.9)); return self; } - positionChanged { [super positionChanged]; if (frame == 6) interval = 160; else if (frame == 7) interval = 70; // [self wrapAtDistance: (3*xOffset) :(3*yOffset)]; return self; } - performCollisionWith:(Actor *) dude { id ret = self; Actor *mine; Actor *myBox = (Actor *)scoreTaker; if (dude->actorType == xx_ship) { // [soundMgr playSound: (EXP3SND) at:0.5]; mine = (Actor *)[actorMgr newActor:xx_mine for:self tag:0]; [mine moveTo:(x + (kind ? -35 : 35)) :(y + (kind ? -132 : 132))]; if (myBox->xv == 0) myBox = [(RotBox*)myBox buddy]; mine->xv = myBox->xv; mine->yv = myBox->yv; ret = [super performCollisionWith: dude]; } return ret; } - (BOOL) doYouHurt:sender { Actor *dude = (Actor *)sender; if (dude->actorType == xx_ship) { return NO; } return YES; } - moveBy:(float)dx :(float)dy { // just ignore, wait for the moveTo:: return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.