This is PlanetView.m in view mode; [Download] [Up]
/* Standard Includes */
#import "Thinker.h"
#import <appkit/NXImage.h>
#import <appkit/Panel.h> /* for NXRunAlertPanel() */
#import <appkit/appkit.h>
#import <dpsclient/wraps.h>
#import <libc.h>
#import <math.h>
#import <appkit/NXColorWell.h>
#import <appkit/Form.h>
#import <appkit/Slider.h>
/* For those of you who want to know what version you are using. */
/* Includes for this project. */
#import "PlanetView.h"
@implementation PlanetView
- initFrame:(NXRect *)frameRect
{
int i;
printf("SD %d\n", SPACEDIST);
[super initFrame:frameRect];
srandom(getpid());
if (!myPrefWindow)
{
myPrefWindow = [NXApp loadNibSection:"PlanetPrefs.nib" owner:self];
}
numplanets = 1;
if (!myplanets)
{
myplanets = (aplanet *) malloc(numplanets * sizeof(aplanet));
}
for (i = 0; i < numplanets; i++)
{
[self newPlanet:&myplanets[i] :bounds.size.width:bounds.size.height];
}
winNum = [[self window] windowNum];
return self;
}
/* Animate() */
/* Move the planets around. */
- oneStep
{
register int i, j; /* planet index */
register double xfactor, yfactor;
/* These variables are related to mouse control of the wasp. */
PScurrentmouse(winNum, &curX, &curY);
/* Test the cursor */
if (bounds.size.width - curX + bounds.size.height - curY <= 10.0)
[self showPanel];
/* Erase previous, draw current, sync for smoothness. */
PSsetlinecap(1);
PSsetinstance(1);
PSnewinstance();
/* Do physics... */
if (numplanets < (j = [numplanetForm intValueAt:0]))
{
myplanets = (aplanet *) realloc(myplanets, (j + 1) * sizeof(aplanet));
for (i = numplanets; i < j; i++)
[self newPlanet:&myplanets[i] :bounds.size.width:bounds.size.height];
numplanets = j;
}
i = -1;
while (++i < numplanets)
{
myplanets[i].x += myplanets[i].xv;
myplanets[i].y += myplanets[i].yv;
if (abs(myplanets[i].x) > bounds.size.width
|| abs(myplanets[i].y) > bounds.size.height)
myplanets[i] = myplanets[--numplanets];
NXSetColor(myplanets[i].planetcolor);
PSmoveto(myplanets[i].x + bounds.size.width / 2, myplanets[i].y + bounds.size.height / 2);
if (myplanets[i].gravity <= 0)
{
myplanets[i].gravity += 1.0;
PSsetlinewidth(SPACEDIST * sqrt(abs(myplanets[i].gravity)));
}
else
PSsetlinewidth(SPACEDIST * sqrt(myplanets[i].gravity));
PSrlineto(1, 0);
PSstroke();
for (j = i + 1; j < numplanets; j++)
{
float dist = sqrt(SQR(deltaX(i, j)) + SQR(deltaY(i, j))) / SPACEDIST;
/* printf("j %d %f\n", j, dist); */
if (dist * 2 < sqrt(myplanets[i].gravity)
+ sqrt(myplanets[j].gravity))
{
[self merge:i :j];
continue;
}
myplanets[i].xv += (xfactor = deltaX(i, j) / (SQR(dist) * dist)) * myplanets[j].gravity;
myplanets[i].yv += (yfactor = deltaY(i, j) / (SQR(dist) * dist)) * myplanets[j].gravity;
myplanets[j].xv -= xfactor * myplanets[i].gravity;
myplanets[j].yv -= yfactor * myplanets[i].gravity;
}
if (cursortime)
{
float grav = [cursorGravity floatValue];
float dist = sqrt(SQR(((curX - bounds.size.width / 2) - myplanets[i].x)) + SQR(((curY - bounds.size.height / 2) - myplanets[i].y))) / SPACEDIST;
if (dist < sqrt(grav))
continue;
;
/*
* printf("%d x %f y %f cx %f cy %f grav %f dist %f xpull %f\n", i,
* myplanets[i].x, myplanets[i].y, (curX - bounds.size.width / 2),
* (curY - bounds.size.height / 2), grav, dist, ((curX -
* bounds.size.width / 2) - myplanets[i].x) * grav / (SQR(dist) *
* dist));
*/
myplanets[i].xv += ((curX - bounds.size.width / 2) - myplanets[i].x) * grav / (SQR(dist) * dist);
myplanets[i].yv += ((curY - bounds.size.height / 2) - myplanets[i].y) * grav / (SQR(dist) * dist);
}
}
PSstroke();
return self;
}
- setCursorhasGravity:sender
{
cursortime = !cursortime;
return self;
}
- (BOOL)useBufferedWindow
{
return NO;
}
- showPanel
{
int inspectedPlanet;
[myPrefWindow orderFront:nil];
inspectedPlanet = MIN(numplanets - 1,[planetnumForm intValueAt:0]);
[numplanetForm setIntValue:[numplanetSlider intValue] at:0];
[numplanetSlider setIntValue:MIN(numplanets,[numplanetSlider intValue])];
[planetnumForm setIntValue:inspectedPlanet at:0];
[planetnumSlider setIntValue:inspectedPlanet];
[planetnumSlider setMaxValue:numplanets - 1];
[planetSpecs setFloatValue:myplanets[inspectedPlanet].gravity at:0];
[planetgravitySlider setFloatValue:myplanets[inspectedPlanet].gravity];
[planetSpecs setFloatValue:myplanets[inspectedPlanet].x at:1];
[planetSpecs setFloatValue:myplanets[inspectedPlanet].y at:2];
[planetSpecs setFloatValue:myplanets[inspectedPlanet].xv at:3];
[planetSpecs setFloatValue:myplanets[inspectedPlanet].yv at:4];
[planetColor setColor:myplanets[inspectedPlanet].planetcolor];
return self;
}
- setPlanetNumber:sender
{
int inspectedPlanet = MIN(numplanets - 1,[sender intValue]);
[planetnumForm setIntValue:inspectedPlanet at:0];
[planetnumSlider setIntValue:inspectedPlanet];
[self showPanel];
return self;
}
- setNumberPlanets:sender
{
int numberPlanets = [sender intValue];
[numplanetForm setIntValue:numberPlanets at:0];
[numplanetSlider setIntValue:numberPlanets];
return self;
}
- setPlanetSpex:sender
{
int inspectedPlanet;
inspectedPlanet = MIN(numplanets - 1,[planetnumSlider intValue]);
myplanets[inspectedPlanet].gravity = [planetSpecs floatValueAt:0];
myplanets[inspectedPlanet].x = [planetSpecs floatValueAt:1];
myplanets[inspectedPlanet].y = [planetSpecs floatValueAt:2];
myplanets[inspectedPlanet].xv = [planetSpecs floatValueAt:3];
myplanets[inspectedPlanet].yv = [planetSpecs floatValueAt:4];
myplanets[inspectedPlanet].planetcolor = [planetColor color];
[self showPanel];
return self;
}
- setPlanetGravity:sender
{
int inspectedPlanet;
inspectedPlanet = MIN(numplanets - 1,[planetnumSlider intValue]);
myplanets[inspectedPlanet].gravity = [sender floatValue];
[self showPanel];
return self;
}
- setFollow:sender
{
cursortime = [sender intValue];
return self;
}
- merge:(int)planetA :(int)planetB
{
myplanets[planetA].gravity = myplanets[planetA].gravity + myplanets[planetB].gravity;
myplanets[planetA].xv = (myplanets[planetA].xv * myplanets[planetA].gravity + MIN(100,myplanets[planetB].xv) * myplanets[planetB].gravity) / (myplanets[planetA].gravity + myplanets[planetB].gravity);
myplanets[planetA].yv = (myplanets[planetA].yv * myplanets[planetA].gravity + MIN(100,myplanets[planetB].yv) * myplanets[planetB].gravity) / (myplanets[planetA].gravity + myplanets[planetB].gravity);
myplanets[planetB] = myplanets[--numplanets];
if ((int)myplanets[planetA].gravity > 100)
[self blowPlanet:planetA];
return self;
}
- newPlanet:(aplanet *) newplanet :(float)width :(float)height
{
newplanet->x = 1.0 * RAND(1100);
newplanet->y = 1.0 * RAND(1100);
newplanet->gravity = DEFAULTGRAV;
newplanet->planetcolor = NXConvertGrayToColor(NX_WHITE);
newplanet->xv = SPACEDIST * RAND(300) / 200.0;
newplanet->yv = SPACEDIST * RAND(300) / 200.0;
return self;
}
- doBOOM:sender
{
[self blowPlanet:MIN(numplanets - 1,[planetnumSlider intValue])];
[self showPanel];
return self;
}
- blowPlanet:(int)planetNum
{
int i, newplanets = abs(myplanets[planetNum].gravity), newplanetnum;
double newxd, newyd, newradius;
newradius = newplanets / PI;
newplanetnum = numplanets + newplanets;
myplanets = (aplanet *) realloc(myplanets, (newplanetnum + 5) *
sizeof(aplanet));
for (i = numplanets; i < newplanetnum; i++)
{
myplanets[i] = myplanets[planetNum];
newxd = sin(PI * 2 * (i - numplanets) / (newplanets)) * newradius;
newyd = cos(PI * 2 * (i - numplanets) / (newplanets)) * newradius;
/* myplanets[i].xv = newxv / 2 * sqrt(myplanets[planetNum].gravity); */
/* myplanets[i].yv = newyv / 2 * sqrt(myplanets[planetNum].gravity); */
myplanets[i].x += newxd / 0.5;
myplanets[i].y += newyd / 0.5;
myplanets[i].gravity = DEFAULTGRAV;
/* myplanets[i].planetcolor = myplanets[planetNum].planetcolor; */
}
myplanets[planetNum].gravity *= -1.0 / 2;
numplanets = newplanetnum;
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.