//=========================================================================== // FLOCKING - Version 17c // AutoRun with Multiple Timers // 15 November 2011 // // EVERYTHING RUNS MORE SLOWLY IN WINDOWS 7 // // This application automatically expands to the size of the display: // Form1->AutoSize = NOT false; // Form1->BorderStyle = bsNone; // Form1 and PaintBox1 sizes are set to MonitorHeight and MonitorWidth. // // Since the standard Windows controls do not appear: // Event handlers must be created to execute Form1->Close(). // A PopUp Menu is used to show and hide the controls. // // To make the application run with continuously varying parameters: // Nine timers control the positions of ten TrackBars. // The suspect population timer has been disabled.* // // *Access Violations occur unpredictably //=========================================================================== // optimize by not computing z when not required // need option to make agents smaller as a function of depth #include #include #include // enables MIDI #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; #define POP 1000 // maximum population // still violation if 800 // ========================================================================== // ====================================================== VARIABLES & CLASSES // ========================================================================== int depth = 100; bool stop = true; bool move = false; bool anAgentHasBeenChosen = false; bool fixCursorXY = false; bool timers = false; bool anaglyph = false; bool solo = true; bool obstacles = false; // for throwing an agent double downX, downY; double upX, upY; double downUpX, downUpY; double timeUp, timeDown; double timeDownUp; double weightedAveDirection; double tangent; double sumXdistancesFromMe, sumYdistancesFromMe, sumZdistancesFromMe; double weightedAveSumXdistances, weightedAveSumYdistances; double weightedAveSumZdistances; double xDistanceFromMe, yDistanceFromMe, zDistanceFromMe; 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 i; int nn; int dist; int size = 10; int chosen = 0; int lastChosen = 1; int pop = 300; // running population <= POP int lastPop = 100; int rule = 0; int lastRule = 0; int radius = 20; int neighbors; int independence = 20; int cursorX, cursorY, cursorZ; int monitorWidth = 900; int monitorHeight = 900; int wheelClick = 0; int keyboard = 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; // -------------------------------------------------------------- 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 part = part % whole; if (whole == 0) whole++; note = (part * 47) / whole + 35; return note; } //--------------------------------------------------- Color Ramp Version 2011 TColor colorRamp(int part, int whole) { part = part % whole; // keep part <= whole if (whole == 0) whole++; // prevent divide by zero int pixelDistanceAlongEdges = (part * 1792) / whole; 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; } 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(int part, int whole) { part = part % whole; // keep part <= whole if (whole == 0) whole = 1; // prevent divide by zero int distance = ( part * 255 ) / whole; return static_cast(RGB(distance, distance, distance)); } //------------------------ declaration of an abstract class called agentClass class agentClass { public: double x, y, z ; double dx, dy, dz; double dxx, dyy, dzz; TPoint twoDPoints[3]; TPoint threeDPoints[3]; TColor color; float height, width; int tag; int seeking; void erase (void) { // size is dependent upon speed if (anaglyph) { // 3d Form1->PaintBox1->Canvas->Pen->Color = back; Form1->PaintBox1->Canvas->Brush->Color = back; Form1->PaintBox1->Canvas->Brush->Style = bsSolid; //bsClear; Form1->PaintBox1->Canvas->Polygon(twoDPoints, 2); Form1->PaintBox1->Canvas->Polygon(threeDPoints, 2); } else { // 2d Form1->PaintBox1->Canvas->Pen->Color = back; Form1->PaintBox1->Canvas->Brush->Color = back; Form1->PaintBox1->Canvas->Brush->Style = bsSolid; Form1->PaintBox1->Canvas->Polygon(twoDPoints, 2); } } void draw (void) { // size is dependent upon speed, use 10:4 or 2:1 // small, medium, large twoDPoints[0].x = x + dx * size; twoDPoints[0].y = y + dy * size; twoDPoints[1].x = x - dx * size + size / 2 * dy; twoDPoints[1].y = y - dy * size - size / 2 * dx; twoDPoints[2].x = x - dx * size - size / 2 * dy; twoDPoints[2].y = y - dy * size + size / 2 * dx; if (!anaglyph) { // 2D COLORING BY // agent-specific colors if (Form1->RadioGroupColor->ItemIndex == 0) { dynaColor = color; } // speed in colors if (Form1->RadioGroupColor->ItemIndex == 1) { dynaColor = colorRamp(getVelocity() * 300, 1000); } // speed in grays if (Form1->RadioGroupColor->ItemIndex == 2) { dynaColor = grayRamp(getVelocity() * 300, 1000); } // iterations in colors if (Form1->RadioGroupColor->ItemIndex == 3) { dynaColor = colorRamp(iterations + 5*tag, 5 * pop); } // iterations in grays if (Form1->RadioGroupColor->ItemIndex == 4) { dynaColor = grayRamp(iterations + 5*tag, 5 * pop); } // direction in colors if (Form1->RadioGroupColor->ItemIndex == 5) { dynaColor = colorRamp((getDirection() + 3) * 100, 628); } // direction in grays if (Form1->RadioGroupColor->ItemIndex == 6) { dynaColor = grayRamp((getDirection() + 3) * 100, 628); } // neighbors in colors if (Form1->RadioGroupColor->ItemIndex == 7) { dynaColor = colorRamp(neighbors + 5, 30); } // neighbors in grays if (Form1->RadioGroupColor->ItemIndex == 8) { dynaColor = grayRamp(neighbors + 5, 30); } // color trails and outline in black if (Form1->RadioGroupTrail->ItemIndex == 1) { Form1->PaintBox1->Canvas->Pen->Color = clBlack; } // color trails and outline in opposite color // Why, sincd dynaColor is used for both Brush and Pen? if (Form1->RadioGroupTrail->ItemIndex == 2) { Form1->PaintBox1->Canvas->Pen->Color = lastDynaColor; } // color trails and outline in same color if (Form1->RadioGroupTrail->ItemIndex == 3) { Form1->PaintBox1->Canvas->Pen->Color = dynaColor; } lastDynaColor = dynaColor; // remember color of last Brush Form1->PaintBox1->Canvas->Brush->Color = dynaColor; if (tag == chosen || tag == lastChosen) { Form1->PaintBox1->Canvas->Brush->Color = clWhite; } Form1->PaintBox1->Canvas->Polygon(twoDPoints, 2); } else { // 3D COLORING threeDPoints[0].x = x + dx * 10 + (monitorHeight / 2 - z)/ depth; threeDPoints[0].y = y + dy * 10; threeDPoints[1].x = x - dx * 10 + 4 * dy + (monitorHeight / 2 - z) / depth; threeDPoints[1].y = y - dy * 10 - 4 * dx; threeDPoints[2].x = x - dx * 10 - 4 * dy + (monitorHeight / 2 - z) / depth; threeDPoints[2].y = y - dy * 10 + 4 * dx; Form1->PaintBox1->Canvas->Pen->Color = clRed; Form1->PaintBox1->Canvas->Brush->Style = bsClear; Form1->PaintBox1->Canvas->Polygon(twoDPoints, 2); Application->ProcessMessages(); Form1->PaintBox1->Canvas->Pen->Color = clAqua; Form1->PaintBox1->Canvas->Brush->Style = bsClear; Form1->PaintBox1->Canvas->Polygon(threeDPoints, 2); } Application->ProcessMessages(); } void move (void) { x += dx; y += dy; if (anaglyph) z += dz; if (Form1->RadioGroupSpace->ItemIndex == 0) { // Bounce if ((x > monitorWidth) || (x < 0)) { // was 885, 155 dx = -dx; } if ((y > monitorHeight) || (y < 0)) { dy = -dy; } if (anaglyph && (z > monitorHeight || z < 0)) { dz = -dz; } } else { // Wrap if (x > monitorWidth) x = 0; // was 895, 5 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; } draw(); } double getDirection (void) { if (dx == 0) dx = .00001; return atan2(dy, dx); } double getVelocity (void) { // is a function of dy, dx double temp = sqrt(pow(dx, 2) + pow(dy, 2)); //if (anaglyph) temp = sqrt(pow(temp, 2) + pow(dz, 2)); return temp; } void setVelocity (double v) { dx = cos(v); dy = sin(v); } }; agentClass agent[POP]; // creates an array "agent" of type "agentClass" agentClass circles[4]; agentClass cursor; // ========================================================================== // ================================================================ FUNCTIONS // ========================================================================== // ========================================================================== int mv (int i) { if (i < 0) i = pop; if (i < pop) i = 0; return i; } // ==================================================================== RESET void reset (void) { //Form1->PaintBox1->Refresh(); Form1->PaintBox1->Canvas->Refresh(); // get depth for 3d if (anaglyph) depth = Form1->TrackBarDepth->Position; iterations = 0; wheelClick = 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].seeking = random(pop); //agent[i].color = defaultColor; //agent[i].direction = 0; //double(i) / 3; computed from dy, dx agent[i].x = random(monitorWidth) - 1; agent[i].y = random(monitorHeight) - 1; agent[i].z = random(monitorHeight) - 1; agent[i].dy = double(random(100) - 50) / 25.00; // -2 to +2 agent[i].dx = double(random(100) - 50) / 25.00; // -2 to +2 agent[i].dz = double(random(100) - 50) / 25.00; // -2 to +2 agent[i].draw(); if (rule == 5) { 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 = clWhite; } else agent[i].color = clWhite; } } // =============================================================== INITIALIZE void initialize (void) { for (int i = 0; i < POP; i++) { agent[i].tag = i; agent[i].erase(); agent[i].height = 10; agent[i].width = 10; agent[i].color = defaultColor; //agent[i].direction = 0; // double(i) / 3; computed from dy, dx agent[i].x = random(monitorWidth) - 1; agent[i].y = random(monitorHeight) - 1; agent[i].z = random(monitorHeight) - 1; agent[i].dy = double(random(100) - 50) / 25.00; // -2 to +2 agent[i].dx = double(random(100) - 50) / 25.00; // -2 to +2 agent[i].dz = double(random(100) - 50) / 25.00; // -2 to +2 agent[i].draw(); } Form1->TrackBarSimSpeed->Position = Form1->TrackBarSimSpeed->Max; } // ========================================================= 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; } // ==================================================== AVERAGE WITHIN RADIUS void averageInRadius (int me) { // square distance neighbors = 0; sumXdistancesFromMe = 0; sumYdistancesFromMe = 0; sumZdistancesFromMe = 0; sum_dH = 0; xDistanceFromMe = 0; yDistanceFromMe = 0; zDistanceFromMe = 0; for (int i = 0; i < pop; i++) { // look at everyone else if (i == me) continue; // but skip me xDistanceFromMe = abs(agent[i].x - agent[me].x); yDistanceFromMe = abs(agent[i].y - agent[me].y); zDistanceFromMe = abs(agent[i].z - agent[me].z); if ((xDistanceFromMe < radius) && (yDistanceFromMe < radius) && (zDistanceFromMe < radius)) { neighbors++; sumXdistancesFromMe += agent[i].dx; sumYdistancesFromMe += agent[i].dy; sumZdistancesFromMe += agent[i].dz; } } } // ===================================================================== STEP void step (void) { iterations ++; for (int i = 0; i < pop; i++) { // draw trails or not if (Form1->RadioGroupTrail->ItemIndex == 0) { agent[i].erase(); } //######################### beginning of rules ################## //######################### beginning of rules ################## // ####################################################### RULE 1 if (rule == 1) { // adopt nearest neighbors direction and speed agent[i].dx = agent[nneighbor(i)].dx; agent[i].dy = agent[nneighbor(i)].dy; } // ####################################################### RULE 2 // adopt weighted average direction and speed of those // within a square radius if (rule == 2) { averageInRadius(i); // look around // add all x & y components weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (neighbors + independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (neighbors + independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (neighbors + independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ####################################################### RULE 3 if (rule == 3) { // flock to cursor sumXdistancesFromMe = cursorX - agent[i].x; sumYdistancesFromMe = cursorY - agent[i].y; sumZdistancesFromMe = cursorZ - agent[i].z; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ####################################################### RULE 4 if (rule == 4) { // flee from cursor sumXdistancesFromMe = agent[i].x - cursorX; sumYdistancesFromMe = agent[i].y - cursorY; sumYdistancesFromMe = agent[i].z - cursorZ; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ####################################################### RULE 5 if (rule == 5) { // assimilate if (agent[i].color == clAqua) agent[nneighbor(i)].color = clAqua; if (agent[i].color == clFuchsia) agent[nneighbor(i)].color = clFuchsia; if (agent[i].color == clYellow) agent[nneighbor(i)].color = clYellow; if (agent[i].color == clWhite) agent[nneighbor(i)].color = clWhite; } // ####################################################### RULE 6 if (rule == 6) { // seek assigned random individual sumXdistancesFromMe = agent[agent[i].seeking].x - agent[i].x; sumYdistancesFromMe = agent[agent[i].seeking].y - agent[i].y; sumZdistancesFromMe = agent[agent[i].seeking].z - agent[i].z; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ####################################################### RULE 7 if (rule == 7) { // follow in line, seek in order sumXdistancesFromMe = agent[mv(i+1)].x - agent[i].x; sumYdistancesFromMe = agent[mv(i+1)].y - agent[i].y; sumZdistancesFromMe = agent[mv(i+1)].z - agent[i].z; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ####################################################### RULE 8 if(rule == 8) { // Seek nearest neighbor sumXdistancesFromMe = agent[nneighbor(i)].x - agent[i].x; sumYdistancesFromMe = agent[nneighbor(i)].y - agent[i].y; sumZdistancesFromMe = agent[nneighbor(i)].z - agent[i].z; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ####################################################### RULE 9 if (rule == 9) { //flee nearest neighbor nneighbor(i); sumXdistancesFromMe = agent[i].x - agent[nn].x; sumYdistancesFromMe = agent[i].y - agent[nn].y; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ###################################################### RULE 10 if (rule == 10) { // Odd (.y and .x switched from seek cursor) sumXdistancesFromMe = cursorX - agent[i].y; sumYdistancesFromMe = cursorY - agent[i].x; sumZdistancesFromMe = cursorZ - agent[i].z; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ###################################################### RULE 11 if (rule == 11) { // Sarah Van Name's Four Corners if (fixCursorXY == false) { if (agent[i].x < 840 && agent[i].y < 525) { sumXdistancesFromMe = 420 - agent[i].x; sumYdistancesFromMe = 262.5 - agent[i].y; sumZdistancesFromMe = 100 - agent[i].z; } if (agent[i].x < 840 && agent[i].y > 525) { sumXdistancesFromMe = 420 - agent[i].x; sumYdistancesFromMe = 787.5 - agent[i].y; sumZdistancesFromMe = 100 - agent[i].z; } if (agent[i].x > 840 && agent[i].y < 525) { sumXdistancesFromMe = 1260 - agent[i].x; sumYdistancesFromMe = 262.5 - agent[i].y; sumZdistancesFromMe = 100 - agent[i].z; } if (agent[i].x > 840 && agent[i].y > 525) { sumXdistancesFromMe = 1260 - agent[i].x; sumYdistancesFromMe = 787.5 - agent[i].y; sumZdistancesFromMe = 100 - agent[i].z; } dynaColor = colorRamp(125, 255); } if (fixCursorXY == true) { if (agent[i].x < 840 && agent[i].y < 525) { sumXdistancesFromMe = 420 + agent[i].x; sumYdistancesFromMe = 262.5 + agent[i].y; sumZdistancesFromMe = 100 + agent[i].z; } if (agent[i].x < 840 && agent[i].y > 525) { sumXdistancesFromMe = 420 + agent[i].x; sumYdistancesFromMe = 787.5 + agent[i].y; sumZdistancesFromMe = 100 + agent[i].z; } if (agent[i].x > 840 && agent[i].y < 525) { sumXdistancesFromMe = 1260 + agent[i].x; sumYdistancesFromMe = 262.5 + agent[i].y; sumZdistancesFromMe = 100 + agent[i].z; } if (agent[i].x > 840 && agent[i].y > 525) { sumXdistancesFromMe = 1260 + agent[i].x; sumYdistancesFromMe = 787.5 + agent[i].y; sumZdistancesFromMe = 100 + agent[i].z; } dynaColor = colorRamp(0, 125); } weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ###################################################### RULE 12 if (rule == 12) { // Seek hierarchically sumXdistancesFromMe = agent[agent[i].seeking].x - agent[i].x; sumYdistancesFromMe = agent[agent[i].seeking].y - agent[i].y; sumZdistancesFromMe = agent[agent[i].seeking].z - agent[i].z; if (i == 0) { sumXdistancesFromMe = cursorX - agent[i].x; sumYdistancesFromMe = cursorY - agent[i].y; sumZdistancesFromMe = cursorZ - agent[i].z; } weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ###################################################### RULE 13 if (rule == 13) { // Sarah Van Name's Lissajou Figure agent[mv(i+1)].x = 840 + .45 * tan(i * 20) *512; agent[mv(i+1)].y = 525 + 0.3 * sin(i* 20) *512; sumXdistancesFromMe = agent[mv(i+1)].x - agent[i].x; sumYdistancesFromMe = agent[mv(i+1)].y - agent[i].y; sumZdistancesFromMe = agent[mv(i+1)].z - agent[i].z; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ###################################################### RULE 14 if(rule == 14) { // Flee Larger, Seek Smaller if(agent[nneighbor(i)].getVelocity() > agent[i].getVelocity()) { sumXdistancesFromMe = -1 * (agent[nneighbor(i)].x - agent[i].x); sumYdistancesFromMe = -1 * (agent[nneighbor(i)].y - agent[i].y); sumZdistancesFromMe = -1 * (agent[nneighbor(i)].z - agent[i].z); } else { sumXdistancesFromMe = agent[nneighbor(i)].x - agent[i].x; sumYdistancesFromMe = agent[nneighbor(i)].y - agent[i].y; sumZdistancesFromMe = agent[nneighbor(i)].z - agent[i].z; } weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); weightedAveSumZdistances = (independence * agent[i].dz + sumZdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; if (weightedAveSumZdistances == 0) weightedAveSumZdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } // ###################################################### RULE 15 if (rule == 15) { // approach/avoid circle if (distanceToCursor(i) < 10 * radius) { // flee sumXdistancesFromMe = agent[i].x - cursorX; sumYdistancesFromMe = agent[i].y - cursorY; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } else { // flock sumXdistancesFromMe = cursorX - agent[i].x; sumYdistancesFromMe = cursorY - agent[i].y; weightedAveSumXdistances = (independence * agent[i].dx + sumXdistancesFromMe) / (independence); weightedAveSumYdistances = (independence * agent[i].dy + sumYdistancesFromMe) / (independence); if (weightedAveSumXdistances == 0) weightedAveSumXdistances = .00001; if (weightedAveSumYdistances == 0) weightedAveSumYdistances = .00001; // compute noise directionVariance = 0.001 * ((random(variance + 1)) - 0.5 * variance); weightedAveDirection = atan2(weightedAveSumYdistances, weightedAveSumXdistances) + directionVariance; my_H = agent[i].getVelocity(); weightedAveVelocity = (independence * my_H + sum_dH) / (neighbors + independence); agent[i].dx = my_H * cos(weightedAveDirection); agent[i].dy = my_H * sin(weightedAveDirection); } } //############################### end of rules ################## //############################### end of rules ################## if (obstacles) { if (Form1->Shape1->Visible && (((agent[i].x - Form1->Shape1->Left < 10) && (agent[i].x - Form1->Shape1->Left > 0)) || ((agent[i].x - (Form1->Shape1->Left + Form1->Shape1->Width) > -10) && (agent[i].x - (Form1->Shape1->Left + Form1->Shape1->Width) < 0))) && ((agent[i].y > Form1->Shape1->Top) && (agent[i].y < Form1->Shape1->Top + Form1->Shape1->Height))) { agent[i].dx = -agent[i].dx; } if (Form1->Shape1->Visible && (((agent[i].y - Form1->Shape1->Top < 10) && (agent[i].y - Form1->Shape1->Top > 0)) || ((agent[i].y - (Form1->Shape1->Top + Form1->Shape1->Height) > -10) && (agent[i].y - (Form1->Shape1->Top + Form1->Shape1->Height) < 0))) && ((agent[i].x > Form1->Shape1->Left) && (agent[i].x < Form1->Shape1->Left + Form1->Shape1->Width))) { agent[i].dy = -agent[i].dy; } if (Form1->Shape2->Visible && (((agent[i].x - Form1->Shape2->Left < 10) && (agent[i].x - Form1->Shape2->Left > 0)) || ((agent[i].x - (Form1->Shape2->Left + Form1->Shape2->Width) > -10) && (agent[i].x - (Form1->Shape2->Left + Form1->Shape2->Width) < 0))) && ((agent[i].y > Form1->Shape2->Top) && (agent[i].y < Form1->Shape2->Top + Form1->Shape2->Height))) { agent[i].dx = -agent[i].dx; } if (Form1->Shape2->Visible && (((agent[i].y - Form1->Shape2->Top < 10) && (agent[i].y - Form1->Shape2->Top > 0)) || ((agent[i].y - (Form1->Shape2->Top + Form1->Shape2->Height) > -10) && (agent[i].y - (Form1->Shape2->Top + Form1->Shape2->Height) < 0))) && ((agent[i].x > Form1->Shape2->Left) && (agent[i].x < Form1->Shape2->Left + Form1->Shape2->Width))) { agent[i].dy = -agent[i].dy; } if (Form1->Shape3->Visible && (((agent[i].x - Form1->Shape3->Left < 10) && (agent[i].x - Form1->Shape3->Left > 0)) || ((agent[i].x - (Form1->Shape3->Left + Form1->Shape3->Width) > -10) && (agent[i].x - (Form1->Shape3->Left + Form1->Shape3->Width) < 0))) && ((agent[i].y > Form1->Shape3->Top) && (agent[i].y < Form1->Shape3->Top + Form1->Shape3->Height))) { agent[i].dx = -agent[i].dx; } if (Form1->Shape3->Visible && (((agent[i].y - Form1->Shape3->Top < 10) && (agent[i].y - Form1->Shape3->Top > 0)) || ((agent[i].y - (Form1->Shape3->Top + Form1->Shape3->Height) > -10) && (agent[i].y - (Form1->Shape3->Top + Form1->Shape3->Height) < 0))) && ((agent[i].x > Form1->Shape3->Left) && (agent[i].x < Form1->Shape3->Left + Form1->Shape3->Width))) { agent[i].dy = -agent[i].dy; } } agent[i].move(); } Form1->Shape1->BringToFront(); Form1->Shape2->BringToFront(); Form1->Shape3->BringToFront(); Sleep(delay); } // ================================================================== REFRESH void refresh (void) { Form1->PaintBox1->Refresh(); for (int i = 0; i < pop; i++) { agent[i].draw(); } } // ====================================================================== RUN void run (void) { stop = false; while (stop == false) { Application->ProcessMessages(); // get depth for 3d if (anaglyph) depth = Form1->TrackBarDepth->Position; iterations++; step(); } } // ========================================================================== // =========================================================== EVENT HANDLERS // ========================================================================== //---------------------------------------------------------- FORM CONSTRUCTOR __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { DoubleBuffered = true; // MakeFullyVisible(); // See also Screen->Height, Width // See also Monitor->Height, Width monitorHeight = Monitor->Height; Form1->Height = monitorHeight; Form1->PaintBox1->Height = monitorHeight; monitorWidth = Monitor->Width; Form1->Width = monitorWidth; Form1->PaintBox1->Width = monitorWidth; randomize(); initialize(); 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); } //----------------------------------------------------------------- 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 shft = Shift.ToInt(); // shft values: Left Right Wheel // no key 8 16 32 // Shift 9 17 33 // Alt 10 18 34 // Ctrl 12 20 36 // e.g.: if (shft == 20) { /* doSomething() */ } // Cntrl / Right Click if (shft == 8) { // Left button #0 to set, unset, cursor X and Y fixCursorXY = !fixCursorXY; // clicks alternate between fixed & moving if (fixCursorXY == true) { cursorX = X; cursorY = Y; cursorZ = monitorHeight / 2; } } // Right Button #1 is reserved for the Popup Menu if (shft == 9) { // Shift left button allows the user choose an agent // for coloring or to recruit its voice // click towards the nose of the agent int shortestDistance = 1000; lastChosen = chosen; for (i = 0; i < pop; i++) { int distance = abs(X - agent[i].x) + abs(Y - agent[i].y); if (distance < shortestDistance) { shortestDistance = distance; chosen = i; } } if( shortestDistance < agent[chosen].width / 2) { agent[chosen].color = userColor; agent[chosen].draw(); } } if (shft == 12) { // Control Left Click to enter obstacles wheelClick = wheelClick % 4; circles[wheelClick].x = X; circles[wheelClick].y = Y; if (wheelClick == 0) { Form1->Shape1->Left = X - 15; Form1->Shape1->Top = Y - 15; Form1->Shape1->Visible = true; } if (wheelClick == 1) { Form1->Shape2->Left = X - 15; Form1->Shape2->Top = Y - 15; Form1->Shape2->Visible = true; } if (wheelClick == 2) { Form1->Shape3->Left = X - 15; Form1->Shape3->Top = Y - 15; Form1->Shape3->Visible = true; } if (wheelClick == 3) { Form1->Shape1->Visible = false; Form1->Shape2->Visible = false; Form1->Shape3->Visible = false; } wheelClick++; } } //------------------------------------------------------ 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 Form1->EditStart->Text = Time(); Form1->EditEnd->Text = ""; run(); } //--------------------------------------------------------------- STEP BUTTON void __fastcall TForm1::ButtonStepClick(TObject *Sender) { stop = true; Form1->EditEnd->Text = Time(); step(); } //--------------------------------------------------------------- STOP BUTTON void __fastcall TForm1::ButtonStopClick(TObject *Sender) { stop = true; Form1->EditEnd->Text = Time(); } //-------------------------------------------------------------- RESET BUTTON void __fastcall TForm1::ButtonResetClick(TObject *Sender) { reset(); //Form1->Refresh(); } //------------------------------------------------------- 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::ButtonEqualizeSpeedClick(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) { Form1->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) { stop = true; 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) { Form1->Refresh(); } //--------------------------------------------------------- TRAIL RADIO GROUP void __fastcall TForm1::RadioGroupTrailClick(TObject *Sender) { //Form1->Refresh(); } //--------------------------------------------------------- RULES RADIO GROUP void __fastcall TForm1::RadioGroupRulesClick(TObject *Sender) { lastRule = rule; // to initialize hierarchical seeking rule = RadioGroupRules->ItemIndex; if (rule == 12 && rule != lastRule) { for (int i = pop - 1; i >= 0; i--) { agent[i].seeking = (i - 1) / 3; } agent[0].seeking = random(pop); } for (int i = 0; i < pop; i++) { if (rule == 5) { 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 = clWhite; } else agent[i].color = clWhite; } } //--------------------------------------------------------- COLOR RADIO GROUP void __fastcall TForm1::RadioGroupColorClick(TObject *Sender) { for (int i = 0; i < pop; i++) { agent[i].erase(); } if (RadioGroupColor->ItemIndex == 9) anaglyph = true; else anaglyph = false; } //----------------------------------------------------- PEN WIDTH RADIO GROUP void __fastcall TForm1::RadioGroupPenWidthClick(TObject *Sender) { if (RadioGroupPenWidth->ItemIndex == 0) Form1->PaintBox1->Canvas->Pen->Width = 1; if (RadioGroupPenWidth->ItemIndex == 1) Form1->PaintBox1->Canvas->Pen->Width = 2; if (RadioGroupPenWidth->ItemIndex == 2) Form1->PaintBox1->Canvas->Pen->Width = 3; } //--------------------------------------------------------- SOUND RADIO GROUP void __fastcall TForm1::RadioGroupSoundClick(TObject *Sender) { if (RadioGroupSound->ItemIndex == 0) { Form1->TimerSound->Enabled = false; } else Form1->TimerSound->Enabled = 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) { timers = !timers; cursorX = random(monitorWidth - 10); cursorY = random(monitorHeight - 10); if (timers == true) { 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; } else { 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; } } //----------------------------------------------------- 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 = TrackBarDepth->Position; Form1->ShapeRed->Height = radius; Form1->ShapeRed->Width = radius; Form1->ShapeRed->Left = (850 + (monitorHeight / 2 + radius) / depth); Form1->ShapeCyan->Left = (850 + (monitorHeight / 2 - radius) / depth); //(monitorHeight / 2 - z) / depth Form1->ShapeCyan->Height = radius; Form1->ShapeCyan->Width = radius; step(); } //------------------------------------------------ SIMULATION SPEED TRACK BAR void __fastcall TForm1::TrackBarSimSpeedChange(TObject *Sender) { delay = TrackBarSimSpeed->Max - TrackBarSimSpeed->Position; } //------------------------------------------------------ POPULATION TRACK BAR void __fastcall TForm1::TrackBarPopulationChange(TObject *Sender) { lastPop = pop; // remember previous population pop = TrackBarPopulation->Position; Form1->EditPop->Text = pop; if (pop < lastPop) // if new pop smaller, erase excess agents Form1->PaintBox1->Refresh(); reset(); } //----------------------------------------------------------- RADIUS TRACKBAR void __fastcall TForm1::TrackBarRadiusChange(TObject *Sender) { radius = TrackBarRadius->Position; Form1->EditRadius->Text = radius; // Form1->ShapeRed->Height = radius; // Form1->ShapeRed->Width = radius; // Form1->ShapeRed->Left = (850 + (monitorHeight / 2 + radius) / depth); // Form1->ShapeCyan->Left = (850 + (monitorHeight / 2 - radius) / depth); // //(monitorHeight / 2 - z) / depth // Form1->ShapeCyan->Height = radius; // Form1->ShapeCyan->Width = radius; // //step(); } //----------------------------------------------------- INDEPENDENCE TRACKBAR void __fastcall TForm1::TrackBarIndependenceChange(TObject *Sender) { independence = TrackBarIndependence->Position; Form1->EditStubbornness->Text = independence; } //--------------------------------------------------------- VARIANCE TRACKBAR void __fastcall TForm1::TrackBarVarianceChange(TObject *Sender) { variance = TrackBarVariance->Position; 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(3) + 1; } //--------------------------------------------------------------- RULES TIMER void __fastcall TForm1::TimerRulesTimer(TObject *Sender) { Form1->RadioGroupRules->ItemIndex = random(3) + 1; } //-------------------------------------------------------------- RADIUS TIMER void __fastcall TForm1::TimerRadiusTimer(TObject *Sender) { Form1->TrackBarRadius->Position = random(100); } //-------------------------------------------------------- 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(3); } //-------------------------------------------------------------- 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 = 100 + random(800); // Access Violation if pop < 100 } //---------------------------------------------------------- ONE SECOND TIMER void __fastcall TForm1::TimerOneSecondTimer(TObject *Sender) { Form1->EditEnd->Text = Time(); } //--------------------------------------------------------------- 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) { stop = true; Form1->Close(); } //---------------------------------------------------------------- FORM CLOSE void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { midiOutClose(&device); } //---------------------------------------------------------- That's all folks