This is ActorMatrix.m in view mode; [Download] [Up]
#import "ActorMatrix.h"
#import "ActorMgr.h"
#import "CacheManager.h"
#import "collisions.h"
@implementation Storage (gimmeTheData)
- (id *) idAt:(int)ndx
{
id *actorArray = (id *)dataPtr;
return actorArray + ndx;
}
- actorAt:(int)ndx
{
return *([self idAt:ndx]);
}
- replaceActorAt:(unsigned int)index with:theActor
{
id *theActorPtr = [self idAt:index];
*theActorPtr = theActor;
return self;
}
@end
@implementation ActorMatrix
// if ActorMatrix was sender, don't add objects to employed list
// (they're subcontractors, so they work cheaper...)
- (BOOL) addToEmployedList:dude
{ return NO;
}
- (BOOL) isGroup
{ return YES;
}
- init
{
[super init];
formation = [[Storage allocFromZone:[self zone]]
initCount:8
elementSize: sizeof(id)
description: "@"];
return self;
}
- activate:sender :(int)tag
{
NXSize t2;
NXSize t1;
MatrixData *md = (MatrixData *)tag;
int numActors = (md->columns * md->rows);
int i,j;
[super activate:sender :tag];
rows = md->rows;
columns = md->columns;
actWidth = md->actWidth;
actHeight = md->actHeight;
xgap = md->xgap;
ygap = md->ygap;
t2.width = columns * (actWidth + xgap) - xgap;
t2.height = rows * (actHeight + ygap) - ygap;
t1.width = t2.width / 2.0;
t1.height = t2.height / 2.0;
[self reinitWithImage:"none"
frameSize:&t2
numFrames:1
shape: RECT
alliance: md->alliance
radius: 1.0
buffered: YES
x: md->x
y: md->y
theta: md->theta
vel: md->vel
interval: md->interval
distToCorner: &t1];
modifyThetas = md->modifyThetas;
[formation setNumSlots:numActors];
if (md->autofill)
{
id dude;
float ox = x, oy = y;
for (j=0; j<rows; j++)
for (i=0; i<columns; i++)
{
x = ox - t1.width + (i*(actWidth+xgap)) + (actWidth/2.0);
y = oy - t1.height + (j*(actHeight+ygap)) + (actHeight/2.0);
dude = [actorMgr newActor:(int)md->whichClass
for:self tag:tag];
[formation replaceActorAt:j*columns+i with:dude];
}
x = ox; y = oy;
actorCount = numActors;
}
else
{
bzero([formation idAt:0],numActors * sizeof(id));
actorCount = 0;
}
return self;
}
- addToFormation: whichClass tag:(int)tag at:(int)col :(int)row
{
float ox = x, oy = y;
id dude;
x = ox + (col*(actWidth+xgap)) + (actWidth/2.0);
y = oy + (row*(actHeight+ygap)) + (actHeight/2.0);
dude = [actorMgr newActor:(int)whichClass
for:self tag:tag];
[formation replaceActorAt:row*columns+col with:dude];
x = ox; y = oy;
actorCount++;
return dude;
}
- nukeActorAt:(int)col :(int)row
{
[formation replaceActorAt:row*columns+col with:nil];
if (--actorCount <= 0) [actorMgr destroyActor:self];
return self;
}
- free
{
[formation free];
return [super free];
}
- makeActorsPerform:(SEL)func
{
int numActors = columns * rows;
int i;
id dude;
for (i=0; i<numActors; i++)
{
if (dude = [formation actorAt:i]) [dude perform:func];
}
return self;
}
- perform:(SEL)func cols:(int)begc :(int)endc rows:(int)begr :(int)endr
{
int i,j;
id dude;
for (j=begr; j<=endr; j++)
for (i=begc; i<=endc; i++)
{
if (dude = [formation actorAt:j*columns+i]) [dude perform:func];
}
return self;
}
// determine if a collision happended into the matrix, and if so, what the
// beginning and ending rows and columns are.
- (BOOL) rowsNcols:(NXRect *)r myRect:(NXRect *)myRect
:(int *)begc :(int *)endc :(int *)begr :(int *)endr
{
int t;
if (!intersectsRect(myRect, r)) return NO;
t = (NX_X(r) - NX_X(myRect)) / (actWidth + xgap);
if (NX_X(r) > (NX_X(myRect) + (t+1) * (actWidth + xgap) - xgap))
t++;
if (t < 0) t = 0;
*begc = t;
t = (NX_MAXX(r) - NX_X(myRect)) / (actWidth + xgap);
if (t >= columns) t = columns - 1;
if (t < *begc) return NO;
*endc = t;
t = (NX_Y(r) - NX_Y(myRect)) / (actHeight + ygap);
if (NX_Y(r) > (NX_Y(myRect) + (t+1) * (actHeight + ygap) - ygap))
t++;
if (t < 0) t = 0;
*begr = t;
t = (NX_MAXY(r) - NX_Y(myRect)) / (actHeight + ygap);
if (t >= rows) t = rows - 1;
if (t < *begr) return NO;
*endr = t;
return YES;
}
//-----------------------------------------
- retire
{
[self makeActorsPerform:@selector(retire)];
employed = NO;
return self;
}
- oneStep
{
NXPoint dXdY;
int i,j;
Actor *dude;
float bx, by;
if (rNc)
{
[self perform:@selector(erase) cols:bc :ec rows:br :er];
}
[self calcDxDy: &dXdY];
[self moveBy:dXdY.x :dXdY.y];
complexShapePtr = NULL;
[self positionChanged];
bx = x - distToCorner.width + (actWidth/2.0);
by = y - distToCorner.height + (actHeight/2.0);
rNc = [self rowsNcols:&screenRect myRect:&drawRect :&bc :&ec :&br :&er];
for (j=0; j<rows; j++)
for (i=0; i<columns; i++)
{
if (dude = [formation actorAt:j*columns+i])
{
[dude moveTo: bx + (i*(actWidth+xgap))
:by + (j*(actHeight+ygap))];
dude->complexShapePtr = NULL;
if (modifyThetas) dude->theta = theta;
[dude positionChanged];
if ((dude->eraseRect.size.width > 0) &&
((!rNc) || ((j<br) || (j>er) || (i<bc) || (i>ec))))
{
[cacheMgr displayRect:&dude->eraseRect];
dude->eraseRect.size.width = 0;
}
}
}
return self;
}
- scheduleDrawing
{
int i,j;
Actor *dude;
if (rNc)
{
for (j=br; j<=er; j++)
for (i=bc; i<=ec; i++)
{
if ((dude = [formation actorAt:j*columns+i]) && dude->employed)
{
[cacheMgr draw:dude];
[dude addFlushRects];
// dude->eraseRect = dude->drawRect;
}
}
}
return self;
}
- (BOOL) doYouHurt:sender
{ return NO;
}
- performCollisionWith:(Actor *) dude
{
int i,j;
id myActor;
int tbc, tec, tbr, ter;
if ([self rowsNcols:&dude->collisionRect myRect:&collisionRect :&tbc :&tec :&tbr :&ter])
{
for (j=tbr; j<=ter; j++)
for (i=tbc; i<=tec; i++)
{
if (myActor = [formation actorAt:j*columns+i])
{
if (actorsCollide(dude,myActor))
{
BOOL h1, h2;
h1 = [myActor doYouHurt:dude];
h2 = [dude doYouHurt:myActor];
if (h1) [dude performCollisionWith:myActor];
if (h2)
{
if (![myActor performCollisionWith:dude]) [self nukeActorAt:i :j];
}
}
}
}
}
return employed ? self : nil;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.