//=========================================================================== // FLOCKING POLYGONS - Version 30 // AutoRun with Multiple Timers // 6 November 2013 //=========================================================================== // // EVERYTHING RUNS MORE SLOWLY IN WINDOWS 7 // // This application expands the display to the size of the monitor: // Form1->AutoSize = false; // Form1->BorderStyle = bsNone; // Form1 and PaintBox1 sizes are set to MonitorHeight and MonitorWidth. // // Since the standard Windows controls do not appear: // Form1->Close() is executed when the label "[X]" is clicked. // Right-Click makes a PopUp Menu appear which controls a panel. // // To make the application run with continuously varying parameters: // More than 13 timers change positions of the TrackBars. // // Directions are reckoned in Radians, not degrees as follows: // // North // -pi/2 // -1.57 // // West East // pi + 0 // +/-3.14 0 // // South // +pi/2 // +1.57 // //=========================================================================== // // FOR 3D: // We should optimize by not computing z when it is not required // We should make agents smaller as a function of their depths #include #include #include // enables MIDI #pragma hdrstop #include "Unit1.h" //#include #include // YOU NEED TO TYPE THIS IN // with fstream.h use fabs instead of abs for absolute value //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; #define POP 1000 // maximum population // still violation if 800 // ========================================================================== // ====================================================== VARIABLES & CLASSES // ========================================================================== Graphics::TBitmap* worldBMP = new Graphics::TBitmap(); // for back gravity long double sumSidesSquared; long double gravForce; long double gravHypot; // for good gravity long double gravityScaler, R, RR, RRR, centerX, centerY; // temporary for debugging int dirX, velX; bool stop = true; bool move = false; bool anAgentHasBeenChosen = false; bool fixCursorXY = false; bool timers = false; bool anaglyph = false; bool solo = false; bool obstacles = false; bool readyToDrag = false; bool setDirAll = false; bool setVelAll = false; bool agent0FollowsCursor = false; bool box = false; // draw a triangle or a box bool playMelody = false; bool trail = false; bool outline = false; bool track = false; bool alternate; // for tracking // for throwing an agent double downX, downY; double upX, upY; double downUpX, downUpY; double timeUp, timeDown; double timeDownUp; double weightedAveDirection; double tangent; double sumXdistancesFromWho, sumYdistancesFromWho, sumZdistancesFromWho; double adjustedAveSumXdistances, adjustedAveSumYdistances; double adjustedAveSumZdistances; double xDistanceFromWho, yDistanceFromWho, zDistanceFromWho; double ave_abs_dX, ave_abs_dY; double weightedAveVelocity, sum_dH, my_H; double noiseX, noiseY; int variance; double directionVariance; int iterations; int delay = 0; int depth = 70; int i; int nn; int dist; int size = 10; int who; int chosen = 0; int lastChosen = 15; int lastLastChosen; //int chosenMidi; int pop = 300; // running population <= POP int lastPop = 100; int rule = 2; int lastRule = 0; int radius = 200; int numberOfNeighbors; int maxNeighbors, lastMaxNeighbors; int independence = 300; int cursorX, cursorY, cursorZ; int monitorWidth = 900; int monitorHeight = 900; int leftClick = 0; int keyboard = 1; int colorChoice = 1; int lastColorChoice = 1; int controlDownX, controlDownY; int agentViz = 0; int colorRange = 500; int spectrum = 0; int space = 1; int renderEvery = 1; int agentToTrack = 0; TColor back = clBlack; TColor fore = clWhite; TColor userColor = clWhite; // user chosen color TColor dynaColor = clWhite; // dynamically chosen color TColor lastDynaColor = dynaColor; // set Pen to color of last Brush TColor defaultColor = clWhite; TColor cyanColor = clAqua; // to allow adjusting the shade of cyan // -------------------------------------------------------------- For the MIDI int midiport = 0; HMIDIOUT device; union { public: unsigned long word; unsigned char data[4]; } message; int instrument1 = 10; // music box int instrument2 = 4; // rhodes piano int note, note1, note2, lastNote1, lastNote2, part, whole; //------------------------------------------------------- 2010.01.20 midiRamp int midiRamp(int part, int whole) { // there are 47 good MIDI musicbox notes ranging from 35 to 81 if (whole == 0) whole++; part = part % whole; note = (part * 47) / whole + 35; return note; } //--------------------------------------------------- Color Ramp Version 2013 TColor colorRamp(float part, float whole, int spectrum) { if (whole == 0) whole = 1; // prevent divide by zero while (part > whole) part = part - whole; // keep part <= whole float pixelDistanceAlongEdges; if (spectrum == 0) { // if all edges of the color cube pixelDistanceAlongEdges = (part * 1792) / whole; } else { // else only one edge of the color cube pixelDistanceAlongEdges = (part * 255) / whole; if (spectrum == 1) pixelDistanceAlongEdges += 0; if (spectrum == 2) pixelDistanceAlongEdges += 256; if (spectrum == 3) pixelDistanceAlongEdges += 512; if (spectrum == 4) pixelDistanceAlongEdges += 768; if (spectrum == 5) pixelDistanceAlongEdges += 1024; if (spectrum == 6) pixelDistanceAlongEdges += 1280; if (spectrum == 7) pixelDistanceAlongEdges += 1536; } int red, green, blue; // Which edge of the color cube are we on? if (pixelDistanceAlongEdges < 256) { // from BLACK to BLUE red = 0; green = 0; blue = pixelDistanceAlongEdges; if (blue < 230) blue = 230; } else if (pixelDistanceAlongEdges < 512) { // from BLUE to CYAN red = 0; green = pixelDistanceAlongEdges - 256; blue = 255; } else if (pixelDistanceAlongEdges < 768) { // from CYAN to GREEN red = 0; green = 255; blue = 255 - (pixelDistanceAlongEdges - 512); } else if (pixelDistanceAlongEdges < 1024) { // from GREEN to YELLOW red = (pixelDistanceAlongEdges - 768); green = 255; blue = 0; } else if (pixelDistanceAlongEdges < 1280) { // from YELLOW to RED red = 255; green= 255-(pixelDistanceAlongEdges - 1024); blue = 0; } else if (pixelDistanceAlongEdges < 1536) { // from RED to MAGENTA red = 255; green= 0; blue = pixelDistanceAlongEdges - 1280; } else { // from MAGENTA to WHITE red = 255; green = pixelDistanceAlongEdges - 1537; blue = 255; } return static_cast(RGB(red, green, blue)); } //-------------------------------------------------------- GRAY RAMP FUNCTION TColor grayRamp(float part, float whole) { if (whole == 0) whole = 1; // prevent divide by zero if (part > whole) part = part - whole; // keep part <= whole float distance = ( part * 255 ) / whole; return static_cast(RGB(distance, distance, distance)); } //------------------------ declaration of an abstract class called agentClass class agentClass { public: long double lastX, lastY, lastZ; long double x, y, z ; long double dx, dy, dz; long double dxx, dyy, dzz; TPoint twoDPoints[3]; TPoint threeDPoints[3]; TPoint boxPoints[5]; TColor color; float height, width; float scale; // for visualized shape size int tag; int seeking; int age, sex, hunger, wealth, live; int pointAx, pointAy; int pointBx, pointBy; int pointCx, pointCy; void erase (void) { // size is dependent upon speed if (anaglyph) { // 3d worldBMP->Canvas->Pen->Color = back; worldBMP->Canvas->Brush->Color = back; worldBMP->Canvas->Brush->Style = bsSolid; //bsClear; worldBMP->Canvas->Polygon(twoDPoints, 2); worldBMP->Canvas->Polygon(threeDPoints, 2); } else { if (box == false) { // 2d triangle worldBMP->Canvas->Pen->Color = back; worldBMP->Canvas->Brush->Color = back; worldBMP->Canvas->Brush->Style = bsSolid; worldBMP->Canvas->Polygon(twoDPoints, 2); } if (box == true) { // 2d box worldBMP->Canvas->Pen->Color = back; worldBMP->Canvas->Brush->Color = back; worldBMP->Canvas->Brush->Style = bsSolid; worldBMP->Canvas->Polygon(boxPoints, 3); } } } void draw (void) { if (!anaglyph) { // 2D COLORING BY // agent-specific colors if (colorChoice == 0) { dynaColor = color; } // speed in colors if (colorChoice == 1) { dynaColor = colorRamp(getVelocity() * 300 + 50, colorRange, spectrum); } // speed in grays if (colorChoice == 2) { dynaColor = grayRamp(getVelocity() * 300 + 50, colorRange); } // iterations in colors synchronous if (colorChoice == 3) { dynaColor = colorRamp(iterations, colorRange, spectrum); } // iterations in grays synchronous if (colorChoice == 4) { dynaColor = grayRamp(iterations, colorRange); } // iterations in colors asynchronous if (colorChoice == 5) { dynaColor = colorRamp(iterations + 5*tag, colorRange, spectrum); } // iterations in grays asynchronous if (colorChoice == 6) { dynaColor = grayRamp(iterations + 5*tag, colorRange); } // direction in colors if (colorChoice == 7) { dynaColor = colorRamp((getDirection() + 3) * 100, 628, spectrum); } // direction in grays if (colorChoice == 8) { dynaColor = grayRamp((getDirection() + 3) * 100, 628); } // numberOfNeighbors in colors if (colorChoice == 9) { dynaColor = colorRamp(numberOfNeighbors, maxNeighbors, spectrum); } // numberOfNeighbors in grays if (colorChoice == 10) { dynaColor = grayRamp(numberOfNeighbors, maxNeighbors); } // agent ID color by colorRamp if (colorChoice == 12) { dynaColor = colorRamp(tag, pop, spectrum); } // agent ID gray by grayRamp if (colorChoice == 13) { dynaColor = grayRamp(tag, pop); } // color outline in black // OUTLINE COLOR OR PEN if (outline == 0) { worldBMP->Canvas->Pen->Color = clBlack; } // color outline in agent's chosen color if (outline == 1) { worldBMP->Canvas->Pen->Color = dynaColor; } // color outline in last agent's chosen color if (outline == 2) { worldBMP->Canvas->Pen->Color = lastDynaColor; } // remember color of last brush lastDynaColor = dynaColor; // FILL COLOR OR BRUSH // color fill in agent's chosen color worldBMP->Canvas->Brush->Color = dynaColor; // color instrument players white if they are playing if (playMelody) { if (tag == chosen || tag == lastChosen) { worldBMP->Canvas->Brush->Color = clWhite; } } // TRACK AGENT // track agent (gray out everyone else) if (track) { if (tag != agentToTrack) { worldBMP->Canvas->Brush->Color = clGray; worldBMP->Canvas->Pen->Color = clGray; } else { worldBMP->Canvas->Brush->Color = clLime; worldBMP->Canvas->Pen->Color = clLime; } } // TRIANGLE, SQUARE, OR LINE // visualize agent as triangle, box or line if (agentViz == 0) { // constant sized triangle scale = size / sqrtl(pow(dx, 2.0) + pow(dy, 2.0)); twoDPoints[0].x = x + scale * dx; twoDPoints[0].y = y + scale * dy; twoDPoints[1].x = x - scale * (dx - dy / 2); twoDPoints[1].y = y - scale * (dy + dx / 2); twoDPoints[2].x = x - scale * (dx + dy / 2); twoDPoints[2].y = y - scale * (dy - dx / 2); worldBMP->Canvas->Polygon(twoDPoints, 2); } if (agentViz == 1) { // variable sized triangle twoDPoints[0].x = x + size * dx; twoDPoints[0].y = y + size * dy; twoDPoints[1].x = x - size * (dx - dy / 2); twoDPoints[1].y = y - size * (dy + dx / 2); twoDPoints[2].x = x - size * (dx + dy / 2); twoDPoints[2].y = y - size * (dy - dx / 2); worldBMP->Canvas->Polygon(twoDPoints, 2); } if (agentViz == 2) { // constant sized box boxPoints[0].x = x + size; boxPoints[0].y = y + size; boxPoints[1].x = x - size; boxPoints[1].y = y + size; boxPoints[2].x = x - size; boxPoints[2].y = y - size; boxPoints[3].x = x + size; boxPoints[3].y = y - size; worldBMP->Canvas->Polygon(boxPoints, 3); } if (agentViz == 3) { // thin line worldBMP->Canvas->MoveTo(lastX, lastY); worldBMP->Canvas->LineTo(x, y); } } else { // 3D STEREO ANAGLYPH // RED is twoDPoints and is OK worldBMP->Canvas->Pen->Color = clRed; worldBMP->Canvas->Brush->Style = bsClear; twoDPoints[0].x = x + size * dx; twoDPoints[0].y = y + size * dy; twoDPoints[1].x = x - size * (dx - dy / 2); twoDPoints[1].y = y - size * (dy + dx / 2); twoDPoints[2].x = x - size * (dx + dy / 2); twoDPoints[2].y = y - size * (dy - dx / 2); worldBMP->Canvas->Polygon(twoDPoints, 2); // compute CYAN threeDPoints[0].x = x + dx * size + (monitorHeight / 2 - z) / depth;; threeDPoints[0].y = y + dy * size; threeDPoints[1].x = x - dx * size + size / 2 * dy + (monitorHeight / 2 - z) / depth; threeDPoints[1].y = y - dy * size - size / 2 * dx; threeDPoints[2].x = x - dx * size - size / 2 * dy + (monitorHeight / 2 - z) / depth; threeDPoints[2].y = y - dy * size + size / 2 * dx; // CYAN is threeDPoints and OK worldBMP->Canvas->Pen->Color = cyanColor; worldBMP->Canvas->Brush->Style = bsClear; worldBMP->Canvas->Polygon(threeDPoints, 2); } //Application->ProcessMessages(); } void move (void) { x += dx; y += dy; if (anaglyph) z += dz; // if world is bounded then BOUNCE if (space == 0) { if ((x > monitorWidth) || (x < 0)) { dx = -dx; } if ((y > monitorHeight) || (y < 0)) { dy = -dy; } if (anaglyph && (z > monitorHeight || z < 0)) { dz = -dz; } } // if world is toroidal then WRAP if (space == 1) { if (x > monitorWidth) x = 0; if (x < 0) x = monitorWidth; if (y > monitorHeight) y = 0; if (y < 0) y = monitorHeight; if (anaglyph && (z > monitorHeight)) z = 0; if (anaglyph && (z < 0)) z = monitorHeight; } // if world is infinite, then DO NOTHING // if (space == 2 { // do nothing // } // randomize any agent that strays outside of the display if (space == 3) { if (x < 0 || x > monitorWidth || y < 0 || y > monitorHeight) { x = random(monitorWidth) - 1; y = random(monitorHeight) - 1; lastX = x; lastY = y; dy = double(random(1000) - 500) / 250.00; // -2 to +2 dx = double(random(1000) - 500) / 250.00; // -2 to +2 } } draw(); lastX = x; lastY = y; } long double getDirection (void) { // ok //if (dx == 0.0) dx = .000000001; // doesn't matter // return atan2(dy, dx); // original return ((dx == 0) && (dy == 0)) ? 0 : atan2(dy,dx); // doesn't matter } long double getVelocity (void) { // ok long double velo = sqrtl(pow(dx, 2.0) + pow(dy, 2.0)); //long double velo = hypotl(dx, dy); // doesn't matter //if (anaglyph) velo = sqrt(pow(velo, 2) + pow(dz, 2)); return velo; } // velocities skew towards minimal at +/- pi/2 (N & S) // all continue to shrink on repeated changes and don't recover void setDirection (long double dir) { dx = getVelocity() * cosl(dir); dy = getVelocity() * sinl(dir); } // directions skew towards the horizontal as velocities increase // all continue to skew on repated changes and don't recover void setVelocity (long double vel) { dx = vel * cosl(getDirection()); dy = vel * sinl(getDirection()); // dx *= vel; // this works OK // dy *= vel; } }; agentClass agent[POP]; // creates an array "agent" of type "agentClass" agentClass circles[4]; agentClass cursor; // for orbital models agentClass orbits1sun; long double orbits1sunDistance; agentClass orbits2sun1, orbits2sun2; long double orbits2sun1Distance; long double orbits2sun2Distance; agentClass orbits3sun; agentClass orbits3mars; agentClass orbits3jupiter; long double orbits3sunDistance; long double orbits3marsDistance; long double orbits3jupiterDistance; long double orbits3marsMass; long double orbits3jupiterMass; long double velocityScale = 1; int me; // ========================================================================== // ================================================================ FUNCTIONS // ========================================================================== // =============================================================== MAKE VALID int mv (int i) { if (i < 0) i = pop; if (i < pop) i = 0; return i; } // ==================================================================== RESET void reset (void) { Form1->Refresh(); worldBMP->Canvas->Refresh(); worldBMP->Canvas->Brush->Color = clBlack; worldBMP->Canvas->Pen->Color = clBlack; worldBMP->Canvas->Rectangle(0, 0, monitorWidth, monitorHeight); // worldBMP->Canvas->FloodFill(0, 0, clWhite, fsSurface); // // x, y, where the floodfill begins to spread // // fsSurface fills all the area of the designated color // // fsBorder fills all NOT of the designated color // get depth for 3d //if (anaglyph) depth = Form1->TrackBarDepth->Position; iterations = 0; leftClick = 0; maxNeighbors = 0; lastMaxNeighbors = 0; for (int i = 0; i < pop; i++) { agent[i].tag = i; agent[i].erase(); agent[i].height = 10; agent[i].width = 10; agent[i].x = random(monitorWidth) - 1; agent[i].y = random(monitorHeight) - 1; agent[i].z = random(monitorHeight) - 1; agent[i].lastX = agent[i].x; agent[i].lastY = agent[i].y; agent[i].lastZ = agent[i].z; agent[i].dy = double(random(1000) - 500) / 500.00; // -2 to +2 // was /250 agent[i].dx = double(random(1000) - 500) / 500.00; // -2 to +2 agent[i].dz = double(random(1000) - 500) / 500.00; // -2 to +2 agent[i].age = 0; agent[i].sex = random(2); agent[i].hunger = 0; agent[i].wealth = 0; agent[i].live = 1; agent[i].draw(); // // orbits // // clockwork Mars orbit // orbits3mars.x = 0.2279 * .5 * monitorHeight * cos(iterations / 227.9) + orbits3sun.x; // orbits3mars.y = 0.2279 * .5 * monitorHeight * sin(iterations / 227.9) + orbits3sun.y; // // // clockwork Jupiter orbit // orbits3jupiter.x = 0.7786 * .5 * monitorHeight * cos(iterations / 778.6) + orbits3sun.x; // orbits3jupiter.y = 0.7786 * .5 * monitorHeight * sin(iterations / 778.6) + orbits3sun.y; // // // // agent[i].x = orbits3jupiter.x; // agent[i].y = orbits3jupiter.y; // agent[i].lastX = agent[i].x; // agent[i].lastY = agent[i].y; // // end orbits } // // orbits 3 // orbits3mars.x = orbits3sun.x; // orbits3mars.y = .2278 * (monitorHeight / 2) + orbits3sun.y; // orbits3marsMass = (0.642 / 1989100) * gravityScaler; // as f(Sun) // orbits3mars.dx = .00241; //24.1 * velocityScale; // orbits3mars.dy = 0; // orbits3mars.color = clRed; // // orbits3jupiter.x = orbits3sun.x; // orbits3jupiter.y = .7786 * (monitorHeight / 2) + orbits3sun.y; // orbits3jupiterMass = (1899.0 / 1989100) * gravityScaler; // as f(Sun) // orbits3jupiter.dx = .00131; //13.1 * velocityScale; // orbits3jupiter.dy = 0; // orbits3jupiter.color = clWhite; } // ========================================================= NEAREST NEIGHBOR int nneighbor (int me) { // suspect nn; int minDist = 10000; for (int i = 0; i < pop; i++) { if (i == me) continue; // don't count yourself dist = sqrt( // true Pythagorean distance pow((agent[i].x - agent[me].x), 2) + pow((agent[i].y - agent[me].y), 2) ); if (anaglyph) { dist = sqrt( pow((agent[i].z - agent[me].z), 2) + pow(dist, 2) ); } if (dist < minDist) { minDist = dist; nn = i;} } return nn; } // ======================================================= DISTANCE TO CURSOR double distanceToCursor(int i) { int dist = sqrt(pow((agent[i].x - cursorX), 2) + pow((agent[i].y - cursorY), 2)); return dist; } // =================== SUM THE NEIGHBORS VECTORS WITHIN A RADIUS FROM SOMEONE void sumNeighborsVectorsFrom (int who) { // square, not Pythagorean, radius numberOfNeighbors = 0; sumXdistancesFromWho = 0; sumYdistancesFromWho = 0; sumZdistancesFromWho = 0; sum_dH = 0; xDistanceFromWho = 0; yDistanceFromWho = 0; zDistanceFromWho = 0; for (int neigh = 0; neigh < pop; neigh++) { // look at everyone else if (neigh == who) continue; // but skip who xDistanceFromWho = fabs(agent[neigh].x - agent[who].x); yDistanceFromWho = fabs(agent[neigh].y - agent[who].y); zDistanceFromWho = fabs(agent[neigh].z - agent[who].z); if ((xDistanceFromWho < radius) && (yDistanceFromWho < radius) && (zDistanceFromWho < radius)) { numberOfNeighbors++; sumXdistancesFromWho += agent[neigh].dx; sumYdistancesFromWho += agent[neigh].dy; sumZdistancesFromWho += agent[neigh].dz; } } } // ======================================== ADJUST INFLUENCE BY INDEPENDENCE void adjustNeighborsVectorsByIndependence (void) { adjustedAveSumXdistances = (independence * agent[me].dx + sumXdistancesFromWho) / (numberOfNeighbors + independence); adjustedAveSumYdistances = (independence * agent[me].dy + sumYdistancesFromWho) / (numberOfNeighbors + independence); adjustedAveSumZdistances = (independence * agent[me].dz + sumZdistancesFromWho) / (numberOfNeighbors + independence); if (adjustedAveSumXdistances == 0) adjustedAveSumXdistances = .00001; if (adjustedAveSumYdistances == 0) adjustedAveSumYdistances = .00001; if (adjustedAveSumZdistances == 0) adjustedAveSumZdistances = .00001; } // ================================================================ ADD NOISE void addNoise (void) { directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(adjustedAveSumYdistances, adjustedAveSumXdistances) + directionVariance; my_H = agent[me].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (numberOfNeighbors + independence); agent[me].dx = my_H * cos(weightedAveDirection); agent[me].dy = my_H * sin(weightedAveDirection); } // ===================================================================== STEP void step (void) { iterations ++; lastMaxNeighbors = maxNeighbors; maxNeighbors = 0; for (me = 0; me < pop; me++) { if (numberOfNeighbors > maxNeighbors) maxNeighbors = numberOfNeighbors; // draw trails or not if (trail == 0) { agent[me].erase(); } //######################### beginning of rules ################## //######################### beginning of rules ################## // ####################################################### RULE 1 if (rule == 1) { // adopt nearest neighbors direction and speed agent[me].dx = agent[nneighbor(me)].dx; agent[me].dy = agent[nneighbor(me)].dy; } // ####################################################### RULE 2 // adopt weighted average direction and speed of those // within a square radius if (rule == 2) { // calculates numberOfNeighbors and... sumNeighborsVectorsFrom(me); // also calculates numberOfNeighbors // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ####################################################### RULE 3 if (rule == 3) { // flock to cursor sumXdistancesFromWho = cursorX - agent[me].x; sumYdistancesFromWho = cursorY - agent[me].y; sumZdistancesFromWho = cursorZ - agent[me].z; numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ####################################################### RULE 4 if (rule == 4) { // flee from cursor sumXdistancesFromWho = agent[me].x - cursorX; sumYdistancesFromWho = agent[me].y - cursorY; sumYdistancesFromWho = agent[me].z - cursorZ; numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ####################################################### RULE 5 if (rule == 5) { // assimilate to nearest neighbor's color agent[me].color = agent[nneighbor(me)].color; } // ####################################################### RULE 6 if (rule == 6) { // follow assigned individual if (agent0FollowsCursor && me == 0) { // if 0 follows cursor sumXdistancesFromWho = cursorX - agent[me].x; sumYdistancesFromWho = cursorY - agent[me].y; sumZdistancesFromWho = cursorZ - agent[me].z; } else { sumXdistancesFromWho = agent[agent[me].seeking].x - agent[me].x; sumYdistancesFromWho = agent[agent[me].seeking].y - agent[me].y; sumZdistancesFromWho = agent[agent[me].seeking].z - agent[me].z; } numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ####################################################### RULE 7 if (rule == 7) { // empty } // ####################################################### RULE 8 if(rule == 8) { // Seek nearest neighbor nneighbor(me); // calculates nn and dist sumXdistancesFromWho = agent[nn].x - agent[me].x; sumYdistancesFromWho = agent[nn].y - agent[me].y; sumZdistancesFromWho = agent[nn].z - agent[me].z; numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ####################################################### RULE 9 if (rule == 9) { //flee nearest neighbor nneighbor(me); // calculates nn and dist sumXdistancesFromWho = agent[me].x - agent[nn].x; sumYdistancesFromWho = agent[me].y - agent[nn].y; sumZdistancesFromWho = agent[me].z - agent[nn].z; numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ###################################################### RULE 10 if (rule == 10) { // Odd (.y and .x switched from seek cursor) sumXdistancesFromWho = cursorX - agent[me].y; sumYdistancesFromWho = cursorY - agent[me].x; sumZdistancesFromWho = cursorZ - agent[me].z; numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ###################################################### RULE 11 if (rule == 11) { // Sarah Van Name's Four Corners if (agent[me].x < 840 && agent[me].y < 525) { sumXdistancesFromWho = 420 - agent[me].x; sumYdistancesFromWho = 262.5 - agent[me].y; sumZdistancesFromWho = 100 - agent[me].z; } if (agent[me].x < 840 && agent[me].y > 525) { sumXdistancesFromWho = 420 - agent[me].x; sumYdistancesFromWho = 787.5 - agent[me].y; sumZdistancesFromWho = 100 - agent[me].z; } if (agent[me].x > 840 && agent[me].y < 525) { sumXdistancesFromWho = 1260 - agent[me].x; sumYdistancesFromWho = 262.5 - agent[me].y; sumZdistancesFromWho = 100 - agent[me].z; } if (agent[me].x > 840 && agent[me].y > 525) { sumXdistancesFromWho = 1260 - agent[me].x; sumYdistancesFromWho = 787.5 - agent[me].y; sumZdistancesFromWho = 100 - agent[me].z; } dynaColor = colorRamp(125, 255, spectrum); numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ###################################################### RULE 12 if(rule == 12) { // Flee near, seek far nneighbor(me); // calculates nn and dist if (dist > radius) { // seek far sumXdistancesFromWho = agent[nn].x - agent[me].x; sumYdistancesFromWho = agent[nn].y - agent[me].y; sumZdistancesFromWho = agent[nn].z - agent[me].z; } if (dist < radius) { // flee near sumXdistancesFromWho = agent[me].x - agent[nn].x; sumYdistancesFromWho = agent[me].y - agent[nn].y; sumZdistancesFromWho = agent[me].z - agent[nn].z; } numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ###################################################### RULE 13 if (rule == 13) { // Sarah Van Name's Lissajou Figure agent[mv(me + 1)].x = 840 + .45 * tan(me * 20) * 512; agent[mv(me + 1)].y = 525 + 0.3 * sin(me * 20) * 512; sumXdistancesFromWho = agent[mv(me + 1)].x - agent[me].x; sumYdistancesFromWho = agent[mv(me + 1)].y - agent[me].y; sumZdistancesFromWho = agent[mv(me + 1)].z - agent[me].z; numberOfNeighbors = 1; // weight vectors by independence adjustNeighborsVectorsByIndependence(); // add noise addNoise(); } // ###################################################### RULE 14 if(rule == 14) { // Flee Larger, Seek Smaller if(agent[nneighbor(me)].getVelocity() > agent[me].getVelocity()) { sumXdistancesFromWho = -1 * (agent[nneighbor(me)].x - agent[me].x); sumYdistancesFromWho = -1 * (agent[nneighbor(me)].y - agent[me].y); sumZdistancesFromWho = -1 * (agent[nneighbor(me)].z - agent[me].z); } else { sumXdistancesFromWho = agent[nneighbor(me)].x - agent[me].x; sumYdistancesFromWho = agent[nneighbor(me)].y - agent[me].y; sumZdistancesFromWho = agent[nneighbor(me)].z - agent[me].z; } numberOfNeighbors = 1; // weight vectors by independence adjustNeighborsVectorsByIndependence(); // add noise addNoise(); } // ###################################################### RULE 15 if (rule == 15) { // circle: seek radius from cursor if (distanceToCursor(me) < radius) { // flee sumXdistancesFromWho = agent[me].x - cursorX; sumYdistancesFromWho = agent[me].y - cursorY; } else { // flock sumXdistancesFromWho = cursorX - agent[me].x; sumYdistancesFromWho = cursorY - agent[me].y; } numberOfNeighbors = 1; // weight vectors by independence adjustNeighborsVectorsByIndependence(); // add noise addNoise(); } // ###################################################### RULE 16 if (rule == 16) { // Gravitational attraction to cursor sumSidesSquared = pow(cursorX - agent[me].x, 2) + pow(cursorY -agent[me].y, 2); gravForce = (radius * 10000) / sumSidesSquared; gravHypot = sqrt(sumSidesSquared); sumXdistancesFromWho = (gravForce / gravHypot) * (cursorX - agent[me].x); sumYdistancesFromWho = (gravForce / gravHypot) * (cursorY - agent[me].y); numberOfNeighbors = 1; // adjusts vector sums by independence adjustNeighborsVectorsByIndependence(); // adds noise addNoise(); } // ###################################################### RULE 17 if (rule == 17) { // Orbits 1 with Sun at Center // gravityScaler is symonymous with independence // z is ignored orbits1sunDistance = sqrt(pow(orbits1sun.x - agent[me].x, 2) + pow(orbits1sun.y - agent[me].y, 2)); agent[me].dx -= (gravityScaler) / pow(orbits1sunDistance, 3) * (agent[me].x - orbits1sun.x); agent[me].dy -= (gravityScaler) / pow(orbits1sunDistance, 3) * (agent[me].y - orbits1sun.y); // color Sun worldBMP->Canvas->Pen->Color = clYellow; worldBMP->Canvas->Brush->Color = clYellow; worldBMP->Canvas->Ellipse (orbits1sun.x -10, orbits1sun.y -10, orbits1sun.x +10, orbits1sun.y +10); } // ###################################################### RULE 18 if (rule == 18) { // Orbits 2 with two Suns // gravityScaler is symonymous with independence // z is ignored orbits2sun1Distance = sqrt(pow(orbits2sun1.x - agent[me].x, 2) + pow(orbits2sun1.y - agent[me].y, 2)); orbits2sun2Distance = sqrt(pow(orbits2sun2.x - agent[me].x, 2) + pow(orbits2sun2.y - agent[me].y, 2)); agent[me].dx -= ((gravityScaler) / pow(orbits2sun1Distance, 3) * (agent[me].x - orbits2sun1.x)) + ((gravityScaler) / pow(orbits2sun2Distance, 3) * (agent[me].x - orbits2sun2.x)); agent[me].dy -= ((gravityScaler) / pow(orbits2sun1Distance, 3) * (agent[me].y - orbits2sun1.y)) + ((gravityScaler) / pow(orbits2sun2Distance, 3) * (agent[me].y - orbits2sun2.y)); // color two Suns worldBMP->Canvas->Pen->Color = clYellow; worldBMP->Canvas->Brush->Color = clYellow; worldBMP->Canvas->Ellipse (orbits2sun1.x -10, orbits2sun1.y -10, orbits2sun1.x +10, orbits2sun1.y +10); worldBMP->Canvas->Ellipse (orbits2sun2.x -10, orbits2sun2.y -10, orbits2sun2.x +10, orbits2sun2.y +10); } // ###################################################### RULE 18 if (rule == 19) { // Orbits 3 with one Sun, Mars and Jupiter // gravityScaler is symonymous with independence // z is ignored // // true Mars orbit // orbits3sunDistance = sqrt(pow(orbits3sun.x - orbits3mars.x, 2) + pow(orbits3sun.y - orbits3mars.y, 2)); // orbits3mars.dx -= // ((gravityScaler) / pow(orbits3sunDistance, 3) * (orbits3mars.x - orbits3sun.x)); // orbits3mars.dy -= // ((gravityScaler) / pow(orbits3sunDistance, 3) * (orbits3mars.y - orbits3sun.y)); // orbits3mars.move(); // // // true Jupiter orbit // orbits3sunDistance = sqrt(pow(orbits3sun.x - orbits3jupiter.x, 2) + pow(orbits3sun.y - orbits3jupiter.y, 2)); // orbits3jupiter.dx -= // ((gravityScaler) / pow(orbits3sunDistance, 3) * (orbits3jupiter.x - orbits3sun.x)); // orbits3jupiter.dy -= // ((gravityScaler) / pow(orbits3sunDistance, 3) * (orbits3jupiter.y - orbits3sun.y)); // orbits3jupiter.move(); // // erase Mars // Form1->PaintBox1->Canvas->Pen->Color = back; // Form1->PaintBox1->Canvas->Brush->Color = back; // Form1->PaintBox1->Canvas->Ellipse // (orbits3mars.x -3, orbits3mars.y -3, orbits3mars.x +3, orbits3mars.y +3); // // // erase Jupiter // Form1->PaintBox1->Canvas->Pen->Color = back; // Form1->PaintBox1->Canvas->Brush->Color = back; // Form1->PaintBox1->Canvas->Ellipse // (orbits3jupiter.x -7, orbits3jupiter.y -7, orbits3jupiter.x +7, orbits3jupiter.y +7); // clockwork Mars orbit orbits3mars.x = 0.2279 * .5 * monitorHeight * cos(iterations / 227.9) + orbits3sun.x; orbits3mars.y = 0.2279 * .5 * monitorHeight * sin(iterations / 227.9) + orbits3sun.y; // clockwork Jupiter orbit orbits3jupiter.x = 0.7786 * .5 * monitorHeight * cos(iterations / 778.6) + orbits3sun.x; orbits3jupiter.y = 0.7786 * .5 * monitorHeight * sin(iterations / 778.6) + orbits3sun.y; // asteroid orbits orbits3sunDistance = sqrt(pow(orbits3sun.x - agent[me].x, 2) + pow(orbits3sun.y - agent[me].y, 2)); orbits3marsDistance = sqrt(pow(orbits3mars.x - agent[me].x, 2) + pow(orbits3mars.y - agent[me].y, 2)); orbits3jupiterDistance = sqrt(pow(orbits3jupiter.x - agent[me].x, 2) + pow(orbits3jupiter.y - agent[me].y, 2)); agent[me].dx -= ((gravityScaler) / pow(orbits3sunDistance, 3) * (agent[me].x - orbits3sun.x)) + ((0.1 * gravityScaler) / pow(orbits3marsDistance, 3) * (agent[me].x - orbits3mars.x)) + ((0.3 * gravityScaler) / pow(orbits3jupiterDistance, 3) * (agent[me].x - orbits3jupiter.x)); agent[me].dy -= ((gravityScaler) / pow(orbits3sunDistance, 3) * (agent[me].y - orbits3sun.y)) + ((0.1 * gravityScaler) / pow(orbits3marsDistance, 3) * (agent[me].y - orbits3mars.y)) + ((0.3 * gravityScaler) / pow(orbits3jupiterDistance, 3) * (agent[me].y - orbits3jupiter.y)); // color sun and planets worldBMP->Canvas->Pen->Color = clYellow; worldBMP->Canvas->Brush->Color = clYellow; worldBMP->Canvas->Ellipse (orbits3sun.x -10, orbits3sun.y -10, orbits3sun.x +10, orbits3sun.y +10); worldBMP->Canvas->Pen->Color = colorRamp(iterations, colorRange, 5); worldBMP->Canvas->Brush->Color = colorRamp(iterations, colorRange, 5); worldBMP->Canvas->Ellipse (orbits3mars.x -2, orbits3mars.y -2, orbits3mars.x +2, orbits3mars.y +2); worldBMP->Canvas->Pen->Color = colorRamp(iterations, 2.7 * colorRange, 2); worldBMP->Canvas->Brush->Color = colorRamp(iterations, 2.7 * colorRange, 2); worldBMP->Canvas->Ellipse (orbits3jupiter.x -2, orbits3jupiter.y -2, orbits3jupiter.x +2, orbits3jupiter.y +2); } // Application->ProcessMessages(); // doesn't help to coordinate explosions //############################### end of rules ################## //############################### end of rules ################## if (obstacles) { if (Form1->Shape1->Visible && (((agent[me].x - Form1->Shape1->Left < 10) && (agent[me].x - Form1->Shape1->Left > 0)) || ((agent[me].x - (Form1->Shape1->Left + Form1->Shape1->Width) > -10) && (agent[me].x - (Form1->Shape1->Left + Form1->Shape1->Width) < 0))) && ((agent[me].y > Form1->Shape1->Top) && (agent[me].y < Form1->Shape1->Top + Form1->Shape1->Height))) { agent[me].dx = -agent[me].dx; } if (Form1->Shape1->Visible && (((agent[me].y - Form1->Shape1->Top < 10) && (agent[me].y - Form1->Shape1->Top > 0)) || ((agent[me].y - (Form1->Shape1->Top + Form1->Shape1->Height) > -10) && (agent[me].y - (Form1->Shape1->Top + Form1->Shape1->Height) < 0))) && ((agent[me].x > Form1->Shape1->Left) && (agent[me].x < Form1->Shape1->Left + Form1->Shape1->Width))) { agent[me].dy = -agent[me].dy; } if (Form1->Shape2->Visible && (((agent[me].x - Form1->Shape2->Left < 10) && (agent[me].x - Form1->Shape2->Left > 0)) || ((agent[me].x - (Form1->Shape2->Left + Form1->Shape2->Width) > -10) && (agent[me].x - (Form1->Shape2->Left + Form1->Shape2->Width) < 0))) && ((agent[me].y > Form1->Shape2->Top) && (agent[me].y < Form1->Shape2->Top + Form1->Shape2->Height))) { agent[me].dx = -agent[me].dx; } if (Form1->Shape2->Visible && (((agent[me].y - Form1->Shape2->Top < 10) && (agent[me].y - Form1->Shape2->Top > 0)) || ((agent[me].y - (Form1->Shape2->Top + Form1->Shape2->Height) > -10) && (agent[me].y - (Form1->Shape2->Top + Form1->Shape2->Height) < 0))) && ((agent[me].x > Form1->Shape2->Left) && (agent[me].x < Form1->Shape2->Left + Form1->Shape2->Width))) { agent[me].dy = -agent[me].dy; } if (Form1->Shape3->Visible && (((agent[me].x - Form1->Shape3->Left < 10) && (agent[me].x - Form1->Shape3->Left > 0)) || ((agent[me].x - (Form1->Shape3->Left + Form1->Shape3->Width) > -10) && (agent[me].x - (Form1->Shape3->Left + Form1->Shape3->Width) < 0))) && ((agent[me].y > Form1->Shape3->Top) && (agent[me].y < Form1->Shape3->Top + Form1->Shape3->Height))) { agent[me].dx = -agent[me].dx; } if (Form1->Shape3->Visible && (((agent[me].y - Form1->Shape3->Top < 10) && (agent[me].y - Form1->Shape3->Top > 0)) || ((agent[me].y - (Form1->Shape3->Top + Form1->Shape3->Height) > -10) && (agent[me].y - (Form1->Shape3->Top + Form1->Shape3->Height) < 0))) && ((agent[me].x > Form1->Shape3->Left) && (agent[me].x < Form1->Shape3->Left + Form1->Shape3->Width))) { agent[me].dy = -agent[me].dy; } } // end of all rules agent[me].move(); } // end of poll everyone in current population Form1->Shape1->BringToFront(); Form1->Shape2->BringToFront(); Form1->Shape3->BringToFront(); // don't necessarily render every iteration if (iterations % renderEvery == 0) { Form1->PaintBox1->Canvas->Draw(0, 0, worldBMP); Form1->EditIterations->Text = iterations; } Sleep(delay); } // ================================================================== REFRESH void refresh (void) { Form1->PaintBox1->Refresh(); worldBMP->Canvas->Brush->Color = clBlack; worldBMP->Canvas->Pen->Color = clBlack; //worldBMP->Canvas->FloodFill(0, 0, clOlive, fsBorder); // x, y, where the floodfill begins to spread // fsSurface fills all the area of the designated color // fsBorder fills all NOT of the designated color worldBMP->Canvas->Rectangle(0, 0, monitorWidth, monitorHeight); for (int i = 0; i < pop; i++) { agent[i].draw(); } Form1->PaintBox1->Canvas->Draw(0, 0, worldBMP); } // ====================================================================== RUN void run (void) { stop = false; while (stop == false) { Application->ProcessMessages(); iterations++; step(); } } //================================================================== AUTO RUN void autoRun (void) { } //---------------------------------------------------------------- SAVE STUFF void save (void) { if (Form1->SaveDialog1->Execute()) { ofstream outfile(Form1->SaveDialog1->FileName.c_str()); outfile << pop << endl; outfile << rule << endl; outfile << iterations << endl; if (rule == 19) { outfile << orbits3sun.x << " " << orbits3sun.y << endl; outfile << orbits3mars.x << " " << orbits3mars.y << endl; outfile << orbits3jupiter.x << " " << orbits3jupiter.y << endl; } for (int i = 0; i < pop; i++) { outfile << i << " " << agent[i].x << " " << agent[i].y << " " << agent[i].dx << " " << agent[i].dy << endl; } outfile.close(); } } //---------------------------------------------------------------- OPEN STUFF void open (void) { if (Form1->OpenDialog1->Execute()) { ifstream infile(Form1->OpenDialog1->FileName.c_str()); refresh(); infile >> pop; infile >> rule; infile >> iterations; if (rule == 19) { infile >> orbits3sun.x >> orbits3sun.y; infile >> orbits3mars.x >> orbits3mars.y; infile >> orbits3jupiter.x >> orbits3jupiter.y; } Form1->TrackBarPopulation->Position = pop; for (int i = 0; i < pop; i++) { infile >> i >> agent[i].x >> agent[i].y >> agent[i].dx >> agent[i].dy; } infile.close(); } step(); // LineTo is drawn from last x and last y which we don't have refresh(); // so let's erase that last step } // ========================================================================== // =========================================================== EVENT HANDLERS // ========================================================================== //---------------------------------------------------------- FORM CONSTRUCTOR __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { Randomize(); DoubleBuffered = true; // MakeFullyVisible(); // See also Screen->Height, Width // See also Monitor->Height, Width monitorWidth = Monitor->Width; centerX = monitorWidth / 2; Form1->Width = monitorWidth; Form1->PaintBox1->Width = monitorWidth; worldBMP->Width = monitorWidth; cursorX = monitorWidth / 2; monitorHeight = Monitor->Height; centerY = monitorHeight / 2; Form1->Height = monitorHeight; Form1->PaintBox1->Height = monitorHeight; worldBMP->Height = monitorHeight; cursorY = monitorHeight / 2; // Orbits 1 initialization orbits1sun.x = monitorWidth / 2; orbits1sun.y = monitorHeight / 2; // Orbits 2 initialization orbits2sun1.x = 2 * monitorWidth / 5; orbits2sun1.y = monitorHeight / 2; orbits2sun2.x = 3 * monitorWidth / 5; orbits2sun2.y = monitorHeight / 2; // Orbits 3 initialization orbits3sun.x = monitorWidth / 2; orbits3sun.y = monitorHeight / 2; // clockwork Mars orbit orbits3mars.x = 0.2279 * .5 * monitorHeight * cos(iterations / 227.9) + orbits3sun.x; orbits3mars.y = 0.2279 * .5 * monitorHeight * sin(iterations / 227.9) + orbits3sun.y; // clockwork Jupiter orbit orbits3jupiter.x = 0.7786 * .5 * monitorHeight * cos(iterations / 778.6) + orbits3sun.x; orbits3jupiter.y = 0.7786 * .5 * monitorHeight * sin(iterations / 778.6) + orbits3sun.y; randomize(); // reset(); Form1->PaintBox1->Canvas->Pen->Width = 1; // for the MIDI system midiOutOpen(&device, midiport, 0, 0, CALLBACK_NULL); message.data[0] = 0xC0; // choose instrument command message.data[1] = instrument1; // instrument message.data[2] = 100; // once set, no need to repeat message.data[3] = 0; // once set, no need to repeat midiOutShortMsg(device, message.word); reset(); } //----------------------------------------------------------------- SHOW FORM void __fastcall TForm1::FormShow(TObject *Sender) { refresh(); } //------------------------------------------------------------- ACTIVATE FORM void __fastcall TForm1::FormActivate(TObject *Sender) { refresh(); } //------------------------------------------------------ PAINT BOX MOUSE DOWN void __fastcall TForm1::PaintBox1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { int shift = Shift.ToInt(); // shft values: | Left Right Wheel // -------------------------------------------------------------- // no key | 8 cursor 16 popup 32 // Shift | 9 musicians 17 33 probe // Alt | 10 color 18 34 // Ctrl | 12 obstacles 20 36 // -------------------------------------------------------------- // Left button #0 to set and unset, cursor X and Y // Clicks alternate between a fixed & moving cursor if (shift == 8) { fixCursorXY = !fixCursorXY; if (fixCursorXY == true) { cursorX = X; cursorY = Y; cursorZ = monitorHeight / 2; } } // Right Button #1 (shft 16) is reserved for the Popup Menu // Shift left button to set the nearest agent as a musician // Two musical agents will be colored white if (shift == 9) { int shortestDistance = 1000; lastLastChosen = lastChosen; lastChosen = chosen; for (i = 0; i < pop; i++) { int distance = fabs(X - agent[i].x) + fabs(Y - agent[i].y); if (distance < shortestDistance) { shortestDistance = distance; chosen = i; } } agent[lastLastChosen].draw(); agent[chosen].draw(); } // Alt left button to color the nearest agent // This only shows with color rule 0, "color by agent color" if (shift == 10) { int shortestDistance = 1000; for (i = 0; i < pop; i++) { int distance = fabs(X - agent[i].x) + fabs(Y - agent[i].y); if (distance < shortestDistance) { shortestDistance = distance; who = i; } } agent[who].color = userColor; agent[who].draw(); } // Control Left Click to enter obstacles in order // Obstacles must be enabled if (shift == 12) { leftClick = leftClick % 4; circles[leftClick].x = X; circles[leftClick].y = Y; if (leftClick == 0) { Form1->Shape1->Left = X - 15; Form1->Shape1->Top = Y - 15; Form1->Shape1->Visible = true; } if (leftClick == 1) { Form1->Shape2->Left = X - 15; Form1->Shape2->Top = Y - 15; Form1->Shape2->Visible = true; } if (leftClick == 2) { Form1->Shape3->Left = X - 15; Form1->Shape3->Top = Y - 15; Form1->Shape3->Visible = true; } if (leftClick == 3) { Form1->Shape1->Visible = false; Form1->Shape2->Visible = false; Form1->Shape3->Visible = false; } leftClick++; } // Wheel Click Hides or Shows Control Panel if (shift == 32) { GroupBoxControls->Visible = ! GroupBoxControls->Visible; } // Shift Wheel Click to probe nearest agent if (shift == 33) { int shortestDistance = 1000; for (i = 0; i < pop; i++) { int distance = fabs(X - agent[i].x) + fabs(Y - agent[i].y); if (distance < shortestDistance) { shortestDistance = distance; who = i; } } // Edit->Text cannot convert a long double to a string double tempDX = agent[who].dx; double tempDY = agent[who].dy; Form1->EditWho->Text = agent[who].tag; Form1->EditDX->Text = tempDX; Form1->EditDY->Text = tempDY; double tempDirection = agent[who].getDirection(); double tempVelocity = agent[who].getVelocity(); Form1->EditDir->Text = tempDirection; Form1->EditVel->Text = tempVelocity; double tempX = agent[who].x; double tempY = agent[who].y; Form1->EditX->Text = tempX; Form1->EditY->Text = tempY; Form1->EditAlive->Text = agent[who].live; Form1->EditAge->Text = agent[who].age; Form1->EditSex->Text = agent[who].sex; Form1->EditHunger->Text = agent[who].hunger; Form1->EditWealth->Text = agent[who].wealth; } Form1->PaintBox1->Canvas->Draw(0, 0, worldBMP); } //------------------------------------------------------ PAINT BOX MOUSE MOVE void __fastcall TForm1::PaintBox1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { if (fixCursorXY == false) { cursorX = X; // useful for some rules cursorY = Y; } } //---------------------------------------------------------------- RUN BUTTON void __fastcall TForm1::ButtonRunClick(TObject *Sender) { Refresh(); // without this initial refresh, the sim runs slowly run(); } //--------------------------------------------------------------- STEP BUTTON void __fastcall TForm1::ButtonStepClick(TObject *Sender) { stop = true; step(); } //--------------------------------------------------------------- STOP BUTTON void __fastcall TForm1::ButtonStopClick(TObject *Sender) { stop = true; } //-------------------------------------------------------------- RESET BUTTON void __fastcall TForm1::ButtonResetClick(TObject *Sender) { reset(); } //------------------------------------------------------- SELECT COLOR BUTTON void __fastcall TForm1::ButtonSelectColorClick(TObject *Sender) { if(Form1->ColorDialog1->Execute()) { userColor = ColorDialog1->Color; Form1->ShapeColor->Brush->Color = userColor; } } //---------------------------------------------------- EQUALIZE SPEED BUTTON void __fastcall TForm1::ButtonEqualizeSpeedRandomizeDirectionClick (TObject *Sender) { for (int i = 0; i < POP; i++) { double dir = (random(M_PI * 2000)/1000 - double(M_PI)); agent[i].dx = cos(dir) * 2; agent[i].dy = sin(dir) * 2; } } //------------------------------------------------------- CLEAR SCREEN BUTTON void __fastcall TForm1::ButtonClearClick(TObject *Sender) { refresh(); } //---------------------------------------------------------------- RUN POPUP void __fastcall TForm1::Exit1Click(TObject *Sender) { run(); } //--------------------------------------------------------------- STEP POPUP void __fastcall TForm1::Step1Click(TObject *Sender) { stop = true; } //--------------------------------------------------------------- STOP POPUP void __fastcall TForm1::Run1Click(TObject *Sender) { stop = true; step(); } //--------------------------------------------------------------- CLOSE POPUP void __fastcall TForm1::Exit2Click(TObject *Sender) { Form1->Close(); } //------------------------------------------------------------- VISIBLE POPUP void __fastcall TForm1::Visible1Click(TObject *Sender) { Form1->GroupBoxControls->Visible = true; } //-------------------------------------------------------------- HIDDEN POPUP void __fastcall TForm1::Hidden1Click(TObject *Sender) { Form1->GroupBoxControls->Visible = false; } //--------------------------------------------------------------- RESET POPUP void __fastcall TForm1::Reset1Click(TObject *Sender) { reset(); Form1->Refresh(); } //-------------------------------------------------------- CLEAR SCREEN POPUP void __fastcall TForm1::ClearScreen1Click(TObject *Sender) { refresh(); } //---------------------------------------------------------= RULES RADIO GROUP void __fastcall TForm1::RadioGroupRulesClick(TObject *Sender) { rule = RadioGroupRules->ItemIndex; // if gravitational orbits set space to infinite if (rule == 17 || rule == 18 || rule == 19) { Form1->RadioGroupSpace->ItemIndex = 3; // infinite Form1->Label5->Caption = "Gravitation"; // change label Form1->RadioGroupAgentViz->ItemIndex = 3; // line Form1->TrackBarSize->Position = 1; // size = 1 Form1->RadioGroupTrail->ItemIndex = 3; // trail in same color Form1->TrackBarIndependence->Position = 1000; // a good setting Form1->RadioGroupColor->ItemIndex = 1; // color by agent tag Form1->RadioGroupSound->ItemIndex = 0; // Form1->TrackBarPopulation->Position = 10; Form1->RadioGroupOutline->ItemIndex = 1; Form1->TrackBarColorRange->Position = 3000; } else { // Form1->RadioGroupSpace->ItemIndex = 1; // wrapped Form1->Label5->Caption = "Independence"; // change label Form1->TrackBarColorRange->Position = 500; // Form1->RadioGroupAgentViz->ItemIndex = 0; // triangle // Form1->TrackBarSize->Position = 10; // size = 10 // Form1->RadioGroupTrail->ItemIndex = 0; // trail off // Form1->RadioGroupColor->ItemIndex = 1; // color by speed // Form1->TrackBarPopulation->Position = 300; } } //--------------------------------------------------------- COLOR RADIO GROUP void __fastcall TForm1::RadioGroupColorClick(TObject *Sender) { Form1->Refresh(); colorChoice = RadioGroupColor->ItemIndex; if (colorChoice == 11) anaglyph = true; else anaglyph = false; for (int i = 0; i < pop; i++) { agent[i].erase(); agent[i].draw(); } } //----------------------------------------------------- PEN WIDTH RADIO GROUP void __fastcall TForm1::RadioGroupPenWidthClick(TObject *Sender) { Form1->PaintBox1->Canvas->Pen->Width = RadioGroupPenWidth->ItemIndex + 1; } //--------------------------------------------------------- SOUND RADIO GROUP void __fastcall TForm1::RadioGroupSoundClick(TObject *Sender) { if (RadioGroupSound->ItemIndex == 0) { playMelody = false; Form1->TimerSound->Enabled = false; } else { Form1->TimerSound->Enabled = true; playMelody = true; } } //-------------------------------------------------- INSTRUMENT 1 RADIO GROUP void __fastcall TForm1::RadioGroupInstrument1Click(TObject *Sender) { if (RadioGroupInstrument1->ItemIndex == 0) instrument1 = 10; if (RadioGroupInstrument1->ItemIndex == 1) instrument1 = 9; if (RadioGroupInstrument1->ItemIndex == 2) instrument1 = 4; if (RadioGroupInstrument1->ItemIndex == 3) instrument1 = 121; } //-------------------------------------------------- INSTRUMENT 2 RADIO GROUP void __fastcall TForm1::RadioGroupInstrument2Click(TObject *Sender) { if (RadioGroupInstrument2->ItemIndex == 0) instrument2 = 10; if (RadioGroupInstrument2->ItemIndex == 1) instrument2 = 9; if (RadioGroupInstrument2->ItemIndex == 2) instrument2 = 4; if (RadioGroupInstrument2->ItemIndex == 3) instrument2 = 121; } //-------------------------------------------------------- Voices Radio Group void __fastcall TForm1::RadioGroupVoicesClick(TObject *Sender) { if (RadioGroupVoices->ItemIndex == 0) { solo = true; } else solo = false; } //------------------------------------------------------ Keyboard Radio Group void __fastcall TForm1::RadioGroupKeyboardClick(TObject *Sender) { keyboard = RadioGroupKeyboard->ItemIndex; } //------------------------------------------------- ON/OFF TIMERS RADIO GROUP void __fastcall TForm1::RadioGroupTimersClick(TObject *Sender) { if (RadioGroupTimers->ItemIndex == 0) { // timers off timers = false; Form1->GroupBoxControls->Visible = true; Form1->TimerColor->Enabled = false; Form1->TimerRules->Enabled = false; Form1->TimerRadius->Enabled = false; Form1->TimerIndependence->Enabled = false; Form1->TimerVariance->Enabled = false; Form1->TimerReset->Enabled = false; Form1->TimerTrails->Enabled = false; Form1->TimerCursor->Enabled = false; Form1->TimerPopulation->Enabled = false; Form1->TimerOneSecond->Enabled = false; Form1->TimerRefresh->Enabled = false; Form1->TimerSize->Enabled = false; Form1->TimerBeatsPerSecond->Enabled = false; } if (RadioGroupTimers->ItemIndex == 1) { // timers random rules timers = true; cursorX = random(monitorWidth - 10); cursorY = random(monitorHeight - 10); Form1->GroupBoxControls->Visible = false; Form1->TimerColor->Enabled = true; Form1->TimerRules->Enabled = true; Form1->TimerRadius->Enabled = true; Form1->TimerIndependence->Enabled = true; Form1->TimerVariance->Enabled = true; Form1->TimerReset->Enabled = true; Form1->TimerTrails->Enabled = true; Form1->TimerCursor->Enabled = true; Form1->TimerPopulation->Enabled = true; Form1->TimerOneSecond->Enabled = true; Form1->TimerRefresh->Enabled = true; Form1->TimerSize->Enabled = true; Form1->TimerBeatsPerSecond->Enabled = true; } if (RadioGroupTimers->ItemIndex == 2) { // for another timer } run(); } //----------------------------------------------------- OBSTACLES RADIO GROUP void __fastcall TForm1::RadioGroupObstaclesClick(TObject *Sender) { obstacles = RadioGroupObstacles->ItemIndex; if (RadioGroupObstacles->ItemIndex == 0) { Form1->Shape1->Visible = false; Form1->Shape2->Visible = false; Form1->Shape3->Visible = false; } } //---------------------------------------------------- DEPTH CHANGE TRACK BAR void __fastcall TForm1::TrackBarDepthChange(TObject *Sender) { depth = 220 - Form1->TrackBarDepth->Position; Form1->EditDepth->Text = depth; } //------------------------------------------------ SIMULATION SPEED TRACK BAR void __fastcall TForm1::TrackBarSimSpeedChange(TObject *Sender) { delay = TrackBarSimSpeed->Max - TrackBarSimSpeed->Position; Form1->EditDelay->Text = delay; } //------------------------------------------------------ POPULATION TRACK BAR void __fastcall TForm1::TrackBarPopulationChange(TObject *Sender) { // remember previous population lastPop = pop; pop = TrackBarPopulation->Position; Form1->EditPop->Text = pop; // if new pop smaller, erase excess agents if (pop < lastPop) Form1->PaintBox1->Refresh(); reset(); } //----------------------------------------------------------- RADIUS TRACKBAR void __fastcall TForm1::TrackBarRadiusChange(TObject *Sender) { radius = TrackBarRadius->Position; Form1->EditRadius->Text = radius; } //----------------------------------------------------- INDEPENDENCE TRACKBAR void __fastcall TForm1::TrackBarIndependenceChange(TObject *Sender) { independence = TrackBarIndependence->Position; gravityScaler = independence; Form1->EditStubbornness->Text = independence; } //--------------------------------------------------------- VARIANCE TRACKBAR void __fastcall TForm1::TrackBarVarianceChange(TObject *Sender) { variance = TrackBarVariance->Position; velocityScale = (variance - 100) / 1000; Form1->EditVariance->Text = variance; } //------------------------------------------------------ CHANGE SIZE TRACKBAR void __fastcall TForm1::TrackBarSizeChange(TObject *Sender) { size = TrackBarSize->Position; Form1->EditSize->Text = size; } //--------------------------------------------------------------- COLOR TIMER void __fastcall TForm1::TimerColorTimer(TObject *Sender) { Form1->RadioGroupColor->ItemIndex = random(10) + 1; } //--------------------------------------------------------------- RULES TIMER void __fastcall TForm1::TimerRulesTimer(TObject *Sender) { Form1->RadioGroupRules->ItemIndex = random(15) + 1; } //-------------------------------------------------------------- RADIUS TIMER void __fastcall TForm1::TimerRadiusTimer(TObject *Sender) { Form1->TrackBarRadius->Position = random(400); } //-------------------------------------------------------- INDEPENDENCE TIMER void __fastcall TForm1::TimerIndependenceTimer(TObject *Sender) { Form1->TrackBarIndependence->Position = random(2000) + 1; } //------------------------------------------------------------ VARIANCE TIMER void __fastcall TForm1::TimerVarianceTimer(TObject *Sender) { Form1->TrackBarVariance->Position = random(200); } //--------------------------------------------------------------- RESET TIMER void __fastcall TForm1::TimerResetTimer(TObject *Sender) { reset(); } //-------------------------------------------------------------- TRAILS TIMER void __fastcall TForm1::TimerTrailsTimer(TObject *Sender) { Form1->RadioGroupTrail->ItemIndex = random(4); } //-------------------------------------------------------------- CURSOR TIMER void __fastcall TForm1::TimerCursorTimer(TObject *Sender) { cursorX = random(monitorWidth - 20) + 10; cursorY = random(monitorHeight - 20) + 10; } //---------------------------------------------------------- POPULATION TIMER void __fastcall TForm1::TimerPopulationTimer(TObject *Sender) { Form1->TrackBarPopulation->Position = 20 + random(675); // Access Violation if pop < 100 } //------------------------------------------------------------ REFRESH TIMER void __fastcall TForm1::TimerRefreshTimer(TObject *Sender) { Form1->Refresh(); } //---------------------------------------------------------------- SIZE TIMER void __fastcall TForm1::TimerSizeTimer(TObject *Sender) { Form1->TrackBarSize->Position = random(47) + 2; } //--------------------------------------------------------------- SOUND TIMER void __fastcall TForm1::TimerSoundTimer(TObject *Sender) { // direction ranges from -3.14 to +3.14 // note = midiRamp(agent[0].getDirection(),32); // note ranges from 33-37 if (keyboard == 0) { // 7 note keyboard note1 = midiRamp(agent[chosen].getDirection() + 3.14159, 7); note2 = midiRamp(agent[lastChosen].getDirection() + 3.14159, 7); } if (keyboard == 1) { // 47 note keyboard note1 = midiRamp((agent[chosen].getDirection() + 3) * 100, 628); note2 = midiRamp((agent[lastChosen].getDirection() + 3) * 100, 628); } if (note1 != lastNote1) { Form1->MemoProbe->Lines->Append(IntToStr(chosen) + " " + IntToStr(note1) + " " + FloatToStr(agent[chosen].getDirection())); message.data[0] = 0xC0; // choose instrument command message.data[1] = instrument1; // instrument midiOutShortMsg(device, message.word); message.data[0] = 0x90; // note on message.data[1] = note; // note # midiOutShortMsg(device, message.word); // tell midi } lastNote1 = note1; if (solo == false) { if (note2 != lastNote2) { Form1->MemoProbe->Lines->Append(IntToStr(lastChosen) + " " + IntToStr(note2) + " " + FloatToStr(agent[lastChosen].getDirection())); message.data[0] = 0xC0; // choose instrument command message.data[1] = instrument2; // instrument midiOutShortMsg(device, message.word); message.data[0] = 0x90; // note on message.data[1] = note; // note # midiOutShortMsg(device, message.word); // tell midi } lastNote2 = note2; } } //--------------------------------------------------------------- CLOSE LABEL void __fastcall TForm1::LabelCloseClick(TObject *Sender) { Form1->Close(); } //---------------------------------------------------------------- FORM CLOSE void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { midiOutClose(&device); delete worldBMP; } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioGroupBeatsPerSecondClick(TObject *Sender) { int beats = RadioGroupBeatsPerSecond->ItemIndex; Form1->TimerSound->Interval = 1000 / (beats + 1); } //--------------------------------------------------------------------------- void __fastcall TForm1::TimerBeatsPerSecondTimer(TObject *Sender) { int choice = random(6); if (choice == 5) Form1->RadioGroupSound->ItemIndex = !Form1->RadioGroupSound->ItemIndex; else Form1->RadioGroupBeatsPerSecond->ItemIndex = random(5); } //--------------------------------------------------------------------------- void __fastcall TForm1::GroupBoxControlsMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { readyToDrag = true; controlDownX = X; controlDownY = Y; } //--------------------------------------------------------------------------- void __fastcall TForm1::GroupBoxControlsMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { if (readyToDrag) { GroupBoxControls->Left = GroupBoxControls->Left + X - controlDownX; GroupBoxControls->Top = GroupBoxControls->Top + Y - controlDownY; } } //--------------------------------------------------------------------------- void __fastcall TForm1::GroupBoxControlsMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { readyToDrag = false; } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonSetAllToCMYGClick(TObject *Sender) { for (int i = 0; i < pop; i++) { if (i % 4 == 0) agent[i].color = clAqua; if (i % 4 == 1) agent[i].color = clFuchsia; if (i % 4 == 2) agent[i].color = clYellow; if (i % 4 == 3) agent[i].color = clGray; RadioGroupColor->ItemIndex = 0; colorChoice = 0; agent[i].draw(); } } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarCyanChange(TObject *Sender) { int darkness = 255 - TrackBarCyan->Position; cyanColor = static_cast(RGB(0, darkness, darkness)); Form1->EditCyan->Text = darkness; } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarSetDirectionChange(TObject *Sender) { //setDirAll = true; dirX++; Form1->EditDirX->Text = dirX; long double ldSetDir; for (int i = 0; i < POP; i++) { ldSetDir = TrackBarSetDirection->Position / 10000.00; agent[i].setDirection(ldSetDir); //agent[i].draw(); } double dSetDir = ldSetDir; Form1->EditSetDirection->Text = String(dSetDir); } //--------------------------------------------------------------------------- void __fastcall TForm1::EditSetDirectionClick(TObject *Sender) { for (int i = 0; i < POP; i++) { agent[i].setDirection(-0.4); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-0.8); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-1.2); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-1.6); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-2.0); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-2.4); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-2.8); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-2.4); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-2.0); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-1.6); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-1.2); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-0.8); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setDirection(-0.4); } step(); } //--------------------------------------------------------------------------- // How do we prevent this from firing more than once? void __fastcall TForm1::TrackBarSetVelocityChange(TObject *Sender) { //setVelAll = true; velX++; Form1->EditVelX->Text = velX; long double ldSetVel; for (int i = 0; i < POP; i++) { ldSetVel = TrackBarSetVelocity->Position / 1000.00; agent[i].setVelocity(ldSetVel); //agent[i].draw(); } double dSetVel = ldSetVel; Form1->EditSetVelocity->Text = String(dSetVel); } //--------------------------------------------------------------------------- // this works OK but the skewing still exists void __fastcall TForm1::EditSetVelocityClick(TObject *Sender) { for (int i = 0; i < POP; i++) { agent[i].setVelocity(.8); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setVelocity(2.0); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setVelocity(4.0); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setVelocity(8.0); } step(); Sleep(500); for (int i = 0; i < POP; i++) { agent[i].setVelocity(.8); } } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonFollowRandomAgentClick(TObject *Sender) { for (int i = 0; i < pop; i++) { agent[i].seeking = random(pop); } } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonFollowNextClick(TObject *Sender) { for (int i = 0; i < pop - 1; i++) { agent[i].seeking = i + 1; } agent[pop - 1].seeking = 0; } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonFollowThreeClick(TObject *Sender) { for (int i = 0; i < pop; i++) { agent[i].seeking = random(3); } } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonFollow139HierarchyClick(TObject *Sender) { // to initialize 1:3:9:27... hierarchical seeking for (int i = pop - 1; i >= 0; i--) { agent[i].seeking = (i - 1) / 3; } agent[0].seeking = random(pop); } //---------------------------------------------------------- That's all folks void __fastcall TForm1::RadioGroupAgent0FollowsClick(TObject *Sender) { if (RadioGroupAgent0Follows->ItemIndex == 0) { agent0FollowsCursor = true; } } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioGroupAgentVizClick(TObject *Sender) { agentViz = RadioGroupAgentViz->ItemIndex; } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarColorRangeChange(TObject *Sender) { colorRange = TrackBarColorRange->Position; Form1->EditColorRange->Text = colorRange; } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioGroupTrailClick(TObject *Sender) { trail = RadioGroupTrail->ItemIndex; } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioGroupOutlineClick(TObject *Sender) { outline = RadioGroupOutline->ItemIndex; } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioGroupSpectrumClick(TObject *Sender) { spectrum = RadioGroupSpectrum->ItemIndex; } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioGroupSpaceClick(TObject *Sender) { space = RadioGroupSpace->ItemIndex; } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonSaveImageClick(TObject *Sender) { if (Form1->SavePictureDialog1->Execute()) { worldBMP->SaveToFile(Form1->SavePictureDialog1->FileName); } } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarRenderEveryChange(TObject *Sender) { if (TrackBarRenderEvery->Position == 1) renderEvery = 1; if (TrackBarRenderEvery->Position == 2) renderEvery = 5; if (TrackBarRenderEvery->Position == 3) renderEvery = 10; if (TrackBarRenderEvery->Position == 4) renderEvery = 50; if (TrackBarRenderEvery->Position == 5) renderEvery = 100; if (TrackBarRenderEvery->Position == 6) renderEvery = 500; if (TrackBarRenderEvery->Position == 7) renderEvery = 1000; if (TrackBarRenderEvery->Position == 8) renderEvery = 5000; if (TrackBarRenderEvery->Position == 9) renderEvery = 10000; Form1->EditRenderEvery->Text = renderEvery; } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonSavePopulationClick(TObject *Sender) { save(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonOpenPopulationClick(TObject *Sender) { open(); } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBarTrackAgentChange(TObject *Sender) { refresh(); agentToTrack = TrackBarTrackAgent->Position; Form1->EditAgentToTrack->Text = agentToTrack; } //--------------------------------------------------------------------------- void __fastcall TForm1::EditAgentToTrackChange(TObject *Sender) { Form1->TrackBarTrackAgent->Position = StrToInt(EditAgentToTrack->Text); } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioGroupTrackClick(TObject *Sender) { refresh(); track = RadioGroupTrack->ItemIndex; } void __fastcall TForm1::ButtonExplodeMarsClick(TObject *Sender) { refresh(); for (int i = 0; i < pop; i++) { agent[i].x = orbits3mars.x; agent[i].y = orbits3mars.y; } // // clockwork Mars orbit // orbits3mars.x = 0.2279 * .5 * monitorHeight * cos(iterations / 227.9) + orbits3sun.x; // orbits3mars.y = 0.2279 * .5 * monitorHeight * sin(iterations / 227.9) + orbits3sun.y; // // // clockwork Jupiter orbit // orbits3jupiter.x = 0.7786 * .5 * monitorHeight * cos(iterations / 778.6) + orbits3sun.x; // orbits3jupiter.y = 0.7786 * .5 * monitorHeight * sin(iterations / 778.6) + orbits3sun.y; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonExplodeJupiterClick(TObject *Sender) { refresh(); for (int i = 0; i < pop; i++) { agent[i].x = orbits3jupiter.x; agent[i].y = orbits3jupiter.y; } // // clockwork Mars orbit // orbits3mars.x = 0.2279 * .5 * monitorHeight * cos(iterations / 227.9) + orbits3sun.x; // orbits3mars.y = 0.2279 * .5 * monitorHeight * sin(iterations / 227.9) + orbits3sun.y; // // // clockwork Jupiter orbit // orbits3jupiter.x = 0.7786 * .5 * monitorHeight * cos(iterations / 778.6) + orbits3sun.x; // orbits3jupiter.y = 0.7786 * .5 * monitorHeight * sin(iterations / 778.6) + orbits3sun.y; } //--------------------------------------------------------------------------- void __fastcall TForm1::TimerClearScreenTimer(TObject *Sender) { refresh(); } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioGroupClearScreenTimerClick(TObject *Sender) { if (RadioGroupClearScreenTimer->ItemIndex == 0) { Form1->TimerClearScreen->Enabled = false; } if (RadioGroupClearScreenTimer->ItemIndex == 1) { Form1->TimerClearScreen->Interval = 30000; Form1->TimerClearScreen->Enabled = true; } if (RadioGroupClearScreenTimer->ItemIndex == 2) { Form1->TimerClearScreen->Interval = 60000; Form1->TimerClearScreen->Enabled = true; } if (RadioGroupClearScreenTimer->ItemIndex == 3) { Form1->TimerClearScreen->Interval = 90000; Form1->TimerClearScreen->Enabled = true; } } //---------------------------------------------------------------------------