This is Tracker.m in view mode; [Download] [Up]
#import "Tracker.h"
#import "Actor.h"
@implementation Tracker
double normAngle(double theta)
{
if (theta > M_PI)
return normAngle(theta - 2.0*M_PI);
else if (theta < -M_PI)
return normAngle(theta + 2.0*M_PI);
else
return theta;
}
- initFor:aShip
{
[super init];
resolution = 0.1;
ship = aShip;
return self;
}
- track:target
{
to = target;
return [self update];
}
- ship
{
return ship;
}
- target
{
return ship;
}
- setResolution:(float) res
{
resolution = res;
return self;
}
- update
{
// Egads this is slopppy; plus it hardwires wrap around!
if (to) {
int n = N_AXIS;
int off[] = {xOffset, yOffset};
while (n--) {
x[n] = [ship distance:to axis:n];
v[n] = [ship velocity:to axis:n];
if (x[n] > off[n])
x[n] -= 2*off[n];
else if (x[n] < -off[n])
x[n] += 2*off[n];
}
} else {
x[0] = x[1] = 0.0;
v[0] = v[1] = 0.0;
}
return self;
}
- projectForward:(float)time
{
int n = 2;
while (n--)
x[n] += n*v[n];
return self;
}
-(float) angle
{
register float at = atan2(x[1],x[0]);
return normAngle(at - [ship angle]);
}
- (float) distance
{
return sqrt(x[0]*x[0] + x[1]*x[1]);
}
- (float) velocity
{
return sqrt(v[0]*v[0] + v[1]*v[1]);
}
-(float) Vangle
{
register float at = atan2(v[1],v[0]);
return normAngle(at - [ship angle]);
}
/*
* Control sequences
*/
- (BOOL) isFacing:(float)angle
{
float target_angle = to->radius / [self distance];
return (fabs(angle) < resolution) || (fabs(angle) < target_angle);
}
- (BOOL) turnTowards
{
return [self turnTowards:[self angle]];
}
- (BOOL) turnTowards:(float)angle
{
if ([self isFacing:angle]) {
[ship setTurning:LEFT down:NO time:timeInMS];
[ship setTurning:RIGHT down:NO time:timeInMS];
return YES;
} else {
ROTATION LR = (angle > 0.0) ? LEFT : RIGHT;
float norm = fabs(angle) / M_PI;
[ship setTurning:LR down:YES time:timeInMS];
if (norm < 0.5) {
int rot = 1000 * norm; // scale amount to turn so don't overshoot
[ship setTurning:LR down:NO time:timeInMS+rot];
}
return NO;
}
}
- (BOOL) thrustTowards
{
return [self thrustTowards:[self angle]];
}
- (BOOL) thrustTowards:(float)angle
{
BOOL isFacing = [self turnTowards:angle];
[ship setThrusting:isFacing time:timeInMS];
return isFacing;
}
- (BOOL) matchVelocity
{
if ([self thrustTowards:[self Vangle]] && ([self velocity] < 5.0)) {
int vscale = 1000 * [self velocity] * timeScale;
#ifdef DEBUG_MATCH
printf("Match: %d for %f at %d\n",vscale, [self velocity], timeInMS);
#endif
[ship setThrusting:NO time:timeInMS+vscale];
}
return [self isFacing:[self angle]];
}
- (BOOL) shieldsWithin:(float)distance
{
BOOL flag = ([self distance] < distance);
[ship setShields:flag];
return flag;
}
- (BOOL) fireBetween:(float)far :(float)near
{
float dist = [self distance];
if (dist < far && dist > near) {
[ship setShields:NO];
[ship fire];
return YES;
}
return NO;
}
- (BOOL) projectToHit
{
extern float xw_bulletSpeed;
float oldDist = 0;
float d;
int n = 0;
// do {
float t;
d = [self distance] - oldDist;
t = d / xw_bulletSpeed;
[self projectForward:t];
// } while (d > 10.0 && ++n < 10);
return (n<10);
}
@end
@implementation Ship (Tracker)
- (float) distance:(Actor*)to axis:(AXIS)xy;
{
return (xy == X_AXIS) ? to->x - x : to->y - y;
}
- (float) velocity:(Actor*)to axis:(AXIS)xy;
{
return (xy == X_AXIS) ? to->xv - xv : to->yv - yv;
}
- (float) angle
{
return theta + M_PI_2;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.