//plants grow and react to wind //plants create seeds //seeds grow with plants until they stop growing //seeds fall to the ground, reacting to wind //seeds create plants //press left and right arrow keys to control wind. //press up arrow to enable mouse attraction, down arrow to disable Plant[] _myPlants; Seed[] _mySeeds; Person _myPerson; //JMyron m; Vector3f ourWind; Vector3f ourPersonsWind; Vector3f ourGravity; //tracking int mySens = 160; int myColor = 70; int myDens = 30; int mySavedColor = 0; boolean drawInfo = false; boolean followMouse = true; int myScanWidth = 160; int myScanHeight = 120; int myTrackingTolerance = 10 ; //developer only ;) properties can be changed when applet is running /* void handleProperties() { if (keyPressed) { switch(key) { case 'x': saveFrame(); println("screenshot taken"); break; case '1': myColor = mySavedColor; myColor--; mySavedColor = myColor; println("Tracking Color" + myColor); break; case '2': myColor = mySavedColor; myColor++; mySavedColor = myColor; println("Color" + myColor); break; case '3': mySens--; println("Sensitivity " + mySens); break; case '4': mySens++; println("Sensitivity " + mySens); break; case '5': myDens--; println("Density " + myDens); break; case '6': myDens++; println("Density " + myDens); break; case 'w': mySavedColor = myColor; myColor = 255; mySens = 200; myDens = 0; println("Tracking White / IR"); break; case 'i': if (drawInfo){ drawInfo = false; println("hide info"); } else { drawInfo = true; println("show info"); } break; case 'm': if (followMouse){ followMouse = false; println("Cam Tracking"); } else { followMouse = true; println("Mouse Tracking"); } break; case '7': gravity -= 0.01; println("Gravity is " + gravity); break; case '8': gravity += 0.01; println("Gravity is " + gravity); break; case '9': ourPersonWindReaction -= 0.001; println("PersonWindInfluence is " + ourPersonWindReaction); break; case '0': ourPersonWindReaction += 0.001; println("PersonWindInfluence is " + ourPersonWindReaction); break; case 'e': ourFallEventChance -= 0.1; println("ourFallEventChance is " + ourFallEventChance); break; case 'r': ourFallEventChance += 0.1; println("ourFallEventChance is " + ourFallEventChance); break; case 't': ourSeedAttractionFactor -= 0.01; println("Seed Attraction Factor" + ourSeedAttractionFactor); break; case 'z': ourSeedAttractionFactor += 0.01; println("Seed Attraction Factor" + ourSeedAttractionFactor); break; case 'g': ourWindInfluenceFactor += 1; println("WindInfluence Divided by " + ourWindInfluenceFactor); break; case 'h': ourWindInfluenceFactor -= 1; println("WindInfluence Divided by " + ourWindInfluenceFactor); break; } } } */ /* //globale parameter//***************/ final int FOLLOW=1; final int FALL=2; final int GROWANDBOW = 3; final int DIE = 4; final int DEAD = 5; final int WAITING = 6; final int MOVING = 7; float ourPlantAttractionFactor = 3; float gravity = 0.1; float ourMaximumSpeed = 10; float ourWindKeyValue = 0; int ourAttractionRadius= 150; int ourPersonStandTime = 9000; int SeedAmount = 100000; //max amount of seeds in world int SeedCounter = 0; int NUMBER_OF_SEEDS = 50; //amount of seeds created by a new plant int PlantAmount = 100; int PlantCounter = 0; float ourWindMax = 5; float ourWindCurrent = 0; float ourWindInfluenceFactor = 35; float ourPersonWindReaction = 0.02; boolean ourPersonHere = false; float ourSeedWindFactor = 0.5; float ourFertilityThreshold; float ourFertilityPercentage = 2; //no plants, 3 percent of newly created seeds are fertile. float ourFallEventChance = 1.8; //the Percentage of the Chance that a Seed starts falling by Wind or a Person passing by float ourSeedAttractionFactor = 0.05; float ourDecaySpeedFactor = 10; //used at camera tracking float _myPersonX = 0; float _myPersonY = 0; /* //globale parameter ende//**************/ void setup() { background(0); size(400, 300); framerate(30); /* m = new JMyron();//make a new instance of the xtra m.start(myScanWidth,myScanHeight);//start a capture m.settings();//video settings are called at startup println("Myron " + m.version()); */ noFill(); ourWind = new Vector3f(); ourGravity = new Vector3f(); _myPerson = new Person(); _mySeeds = new Seed[SeedAmount]; _myPlants = new Plant[PlantAmount]; //20 Plants Level 0 are created for (int i=0; i<20; i++){ _myPlants[i] = new Plant(random(30, width-30), 0, i); PlantCounter++; } } void loop() { //handleProperties(); background(0); ourGravity.set(0,gravity,0); //webcam tracking/////////////////////////////////////// /* m.trackColor(myColor,myColor,myColor,mySens); m.minDensity(myDens); m.update(); int[][] b = m.globBoxes();//get the boxes _myPersonX = 0; _myPersonY = 0; for(int i=0;i= 50 && _myPerson._myPosition.x <= width - 50){ ourPersonHere = true; } else { ourPersonHere = false; } // if no person is there, the program runs with a delay. /* if (ourPersonHere == false){ delay(40); } */ //Person is looped//////////////////////////////////////// _myPerson.move(); //PersonWind is added to wind Vector3f myAdditionalPersonWind; myAdditionalPersonWind = new Vector3f(); myAdditionalPersonWind.set( _myPerson._myPersonWind()); myAdditionalPersonWind.multiply(ourPersonWindReaction);//factor to weaken wind a little ourWind.add(myAdditionalPersonWind); if (drawInfo){ _myPerson.draw(); } //Person is looped//////////////////////////////////////// //show amounts of seeds and plants by pressing p if (keyPressed){ if(key == 'p'){ println(SeedCounter + " Seed(s) existing." + ourFertilityThreshold + "% Fertile" + "---" + PlantCounter + " Plant(s) existing."); println("Wind is " + ourWind.x); } } //WIND //wind controlled by left and right arrows and person*/ if (keyPressed){ if (key == RIGHT){ ourWindKeyValue += 0.1; } if (key == LEFT){ ourWindKeyValue -= 0.1; } } //decreases wind step by step if (ourWind.x - ourWindKeyValue > 0){ ourWind.x -= ourWind.x * 0.01; } if (ourWind.x - ourWindKeyValue < 0){ ourWind.x += ourWind.x * -0.01; } //sets Wind to 0 when too weak. if (abs(ourWind.x - ourWindKeyValue)<0.0001){ ourWind.x = 0; } //wind is CLAMPED to _windMax ourWindCurrent = ourWind.length(); if (ourWindCurrent > ourWindMax){ ourWind.normalize(); ourWind.multiply(ourWindMax); } //PLANTS for (int i=0; i<_myPlants.length; i++){ //Dead plants are removed if (_myPlants[i] != null && _myPlants[i]._myState == DEAD){ _myPlants[i] = null; PlantCounter--; } //existing plants are looped if (_myPlants[i] != null){ _myPlants[i].loop(); _myPlants[i].draw(); } } //SEEDS for (int i=0; i<_mySeeds.length; i++){ //dead seeds are removed if(_mySeeds[i] != null && _mySeeds[i]._myState == DEAD){ _mySeeds[i] = null; SeedCounter--; } //existing seeds are looped if (_mySeeds[i] != null){ _mySeeds[i].loop(); _mySeeds[i].draw(); } } } ///*SEEED*//////////////////////////////////////////////////////////////////////////////////////////////////// class Seed { Vector3f _myPosition; Vector3f _myVelocity; Vector3f _myAcceleration; Vector3f _myPersonAttractor; Vector3f _myStemDistance; float _myAerodynamicResistance = random(0.5,0.1); float _myMaximumSpeed; float _myAttractionRadius = ourAttractionRadius; float _myWholeRotation; int _myLevel; int _myParentPlant; int _myState; int _myArrayID; boolean FERTILE = false; //int _myFertilityDecider; int _myStartWaitTime; boolean _myStartWaitTimeChecked = false; boolean _startedFalling = false; int _myWaitTime = int(random(1000, 200000)); //constructor Seed(int theParentPlant, int theLevel, int theState, int theArrayID) { _myArrayID=theArrayID; _myParentPlant=theParentPlant; _myLevel=theLevel; _myState=theState; _myPosition = new Vector3f(); _myVelocity = new Vector3f(); _myAcceleration = new Vector3f(); _myPersonAttractor = new Vector3f(); _myStemDistance = new Vector3f(); _myStemDistance.set(random(-1, 1),random(-1, 1),0);//set random direction from stem _myStemDistance.normalize(); _myStemDistance.multiply(random(3, 40+(2*(1+_myLevel)))); //set random distance to stem //_myFertilityDecider = int(random(0, 100)); //0-100 percent. //decides if seed is fertile while being created /* if (_myFertilityDecider <= ourFertilityThreshold){ FERTILE = true; } */ setVelocity(0, 0, 0); } void setPosition(float theX, float theY, float theZ) { _myPosition.set(theX, theY, theZ); } void setVelocity(float theX, float theY, float theZ) { _myVelocity.set(theX, theY, theZ); } void setAcceleration(float theX, float theY, float theZ) { _myAcceleration.set(theX, theY, theZ); } void setMaximumSpeed(float theMaximumSpeed) { _myMaximumSpeed = theMaximumSpeed; } void loop() { setMaximumSpeed(ourMaximumSpeed); ///state1:follow the parent plant******************************************************************************************************************************** if ( _myState == FOLLOW ){ //detects distance to person Vector3f myPersonPosition; myPersonPosition = _myPerson.getPosition(); float myPersonDistance = myPersonPosition.x -_myPosition.x;//Distance can be negative or positive //sets the seeds state to "fall" when the plant has stopped growing if (_myPlants[_myParentPlant]._myPlantCurrentHeight <= _myPlants[_myParentPlant]._myPlantMaxHeight){ //sets a random wait time before actually falling if (_myStartWaitTimeChecked == false){ _myStartWaitTime = millis(); _myStartWaitTimeChecked = true; } if (_myStartWaitTimeChecked && millis() > (_myStartWaitTime + _myWaitTime)){ _myState = FALL; } //special fall event when person is near seed or wind is getting strong if (abs(myPersonDistance) < 5 || abs(ourWindMax - ourWindCurrent) < 0.09 ){ int myFallDecider = int(random(0,100)); if (myFallDecider < ourFallEventChance){ _myState = FALL; } } } //seed gets coordinates from last stem in plant _myPosition.x = _myPlants[_myParentPlant]._myPlantStengel[9].x; _myPosition.y = _myPlants[_myParentPlant]._myPlantStengel[9].y; _myPosition.add(_myStemDistance); } ///state1:folgen:ende******************************************************************************************************************************** ///state2:fallen****************************************************************************************************************************** if(_myState == FALL){ //gets own position and scale factor (see blossom scaler in draw method) if (_startedFalling == false){ _myPosition.x = _myPlants[_myParentPlant]._myPlantStengel[9].x; _myPosition.y = _myPlants[_myParentPlant]._myPlantStengel[9].y; Vector3f myPositionScaleVector = new Vector3f(); float myPositionScaler = (_myPlants[_myParentPlant]._myPlantCurrentHeight / _myPlants[_myParentPlant]._myPlantMaxHeight) * (0.2 + (0.01*_myLevel)); // Exactly Like Blossom scaler. myPositionScaleVector.set(_myStemDistance); myPositionScaleVector.multiply(myPositionScaler); _myPosition.sub(myPositionScaleVector); _startedFalling = true; } Vector3f _myOffsetVector;//offset vector is created _myOffsetVector = new Vector3f();//offset vector is created _myOffsetVector.add(ourWind);//wind is added to offset vector _myOffsetVector.multiply(_myAerodynamicResistance / ourWindInfluenceFactor);//applies aerodynamic resistance to wind //person attraction is calculated Vector3f myPersonPosition; myPersonPosition = _myPerson.getPosition(); float myPersonDistance = myPersonPosition.x -_myPosition.x;//Distance can be negative or positive if (abs(myPersonDistance) < _myAttractionRadius) { float myAttractionStrength = myPersonDistance / _myAttractionRadius; myAttractionStrength = sin(PI * myAttractionStrength); _myPersonAttractor.set(myAttractionStrength * ourSeedAttractionFactor, 0, 0); } else { _myPersonAttractor.set(0, 0, 0); } _myOffsetVector.add(_myPersonAttractor); _myOffsetVector.add(ourGravity); _myOffsetVector.y = _myOffsetVector.y * (_myAerodynamicResistance * _myAerodynamicResistance); //applies Aerodynamic resistance to gravity _myVelocity.add(_myOffsetVector); //velocity vector is set to maximum speed before added to position float mySpeed = _myVelocity.length(); if (mySpeed > _myMaximumSpeed) { _myVelocity.normalize(); _myVelocity.multiply(_myMaximumSpeed); } _myPosition.add(_myVelocity); //decreases Velocity = BRAKE///////////////////////////////// _myVelocity.x = _myVelocity.x * 0.99; //new plants are created here when seeds hit ground(height) if (_myPosition.y >= height){ _myPlants[_myParentPlant]._mySeedCounter--; int myFertilityDecider = int(random(0, 100)); //0-100 percent. if (myFertilityDecider <= ourFertilityThreshold + 0.5 * _myLevel){ FERTILE = true; println("fertile"); } if (PlantCounter < PlantAmount && FERTILE){ for (int i = 0; i < _myPlants.length; i++) { if (_myPlants[i] == null) { _myPlants[i] = new Plant( _myPosition.x, _myLevel-1, i/*the Plant ID*/); PlantCounter++; FERTILE = false; break; } } } _myState = DEAD; } else { if (_myPosition.x >= width || _myPosition.x <= 0){ _myPlants[_myParentPlant]._mySeedCounter--; _myState = DEAD; } } ///state2:fallen: ende*************************************************************************** } } void draw() { float _mySeedLength = -5; float _myBlossomScaler = (_myPlants[_myParentPlant]._myPlantCurrentHeight / _myPlants[_myParentPlant]._myPlantMaxHeight) * (0.2 + (0.01*_myLevel)); if (_myState == FOLLOW){ Vector3f myParentPosition = _myPlants[_myParentPlant]._myPlantStengel[9]; Vector3f myParentSecondPosition = _myPlants[_myParentPlant]._myPlantStengel[6];//3 stengel, because difference between 8 and 9 is too hevy Vector3f myPositionOffset = new Vector3f(); myPositionOffset.set(myParentPosition); myPositionOffset.sub(_myPosition); Vector3f myOrientation = new Vector3f(); myOrientation.set(_myPosition); myOrientation.sub(myParentPosition); Vector3f myBlossomOrientation = new Vector3f(); myBlossomOrientation.set(myParentPosition); myBlossomOrientation.sub(myParentSecondPosition); push(); translate(myParentPosition.x, myParentPosition.y); scale(_myBlossomScaler); float myFirstRotator = atan2(myBlossomOrientation.x, -myBlossomOrientation.y); rotate(myFirstRotator); translate(myPositionOffset.x,myPositionOffset.y); float mySecondRotator = atan2(-myOrientation.x, myOrientation.y); rotate(mySecondRotator); _myWholeRotation = myFirstRotator + mySecondRotator; /* draw stuff here */ for (int i = _myLevel; i >= 0; i--){ stroke(_myPlants[_myParentPlant]._myBasicStroke-(i*30)); strokeWeight(1); line(0, 0, 0, i*_mySeedLength); } /* -- */ pop(); } if(_myState == FALL){ if (_myWholeRotation !=0 && abs(_myWholeRotation) >= 0.1){ _myWholeRotation -= _myWholeRotation/10; } else { _myWholeRotation = 0; } push(); translate(_myPosition.x, _myPosition.y); scale(_myBlossomScaler); float myVelocityRotator = atan2(_myVelocity.x, _myLevel * 2); rotate(_myWholeRotation); rotate(myVelocityRotator); for (int i = _myLevel; i >= 0; i--){ stroke(_myPlants[_myParentPlant]._myBasicStroke-(i*20)); strokeWeight(1); line(0, 0, 0, i*_mySeedLength); } pop(); } } } ///*SEED END*//////////////////////////////////////////////////////////////////////////////////////////////////// ///*PLANT*//////////////////////////////////////////////////////////////////////////////////////////////////// class Plant { Vector3f[] _myPlantStengel; Vector3f _myPersonAttractor; float _myXPosition; int _myLevel; int _myID; int _myState; float _myPlantMaxHeight; float _myPlantHeightStage = height / 20; float _myPlantBasicHeight = random(-_myPlantHeightStage, -(_myPlantHeightStage + 5)); float _myPlantCurrentHeight = 0; //initial height float _myGrowthSpeed = (random (0.2,0.1) * (1+_myLevel));//determines the growth speed(steps) float _mySwingDistance = random(0.5,1) * (1+_myLevel); float _myDecayLevel = 0; Vector3f _myDecayDirection; int _mySeedCounter = NUMBER_OF_SEEDS; float _mySwingAngle = 0; float _mySwingSpeed = random(0.01,0.02); int _myAttractionRadius= ourAttractionRadius; float _myBasicStroke; //hier folgt der constructor Plant(float theXPosition, int theLevel, int theID) { _myXPosition=theXPosition; //downsteps the level to 0 per generation if(theLevel < 0){ theLevel = 0; } _myLevel=theLevel; _myPlantMaxHeight = _myPlantBasicHeight-(3*_myLevel); _myBasicStroke = 255-(10*(6-_myLevel))+(0.5*_myPlantBasicHeight); _myID=theID; _myState=GROWANDBOW; _myPlantStengel = new Vector3f[10]; _myPersonAttractor = new Vector3f(); for (int i=0; i<_myPlantStengel.length; i++){ _myPlantStengel[i] = new Vector3f(); } // here the first vector is defined because of fixed xpos _myPlantStengel[0].set(_myXPosition,height,0); _myDecayDirection = new Vector3f(); _myDecayDirection.set(random(-1,1),0,0); //here seeds are created****************************************************************************************** int myNumberOfSeeds = NUMBER_OF_SEEDS; for (int i = 0; i < _mySeeds.length; i++) { if (_mySeeds[i] == null) { _mySeeds[i] = new Seed(_myID, _myLevel, FOLLOW, i/*the Array ID*/); myNumberOfSeeds--; SeedCounter++; if (myNumberOfSeeds == 0) { break; } } } //******************************************************************************************************************* } void loop() { if (_myState == GROWANDBOW){ if (_mySwingAngle < TWO_PI){ _mySwingAngle+=_mySwingSpeed; }else{ _mySwingAngle = 0 ; } //the plant starts at currentHeight=0 an grows until it has reached its maxHeight-a Factor multipleid by the plants level if (_myPlantCurrentHeight > _myPlantMaxHeight){ _myPlantCurrentHeight -= _myGrowthSpeed; } //here the rest of the PlantS Segments are filled with values for (int i=1; i<_myPlantStengel.length; i++){ Vector3f myPersonPosition; myPersonPosition = _myPerson.getPosition(); float myPersonDistance = myPersonPosition.x -_myPlantStengel[i].x;//Distance can be negative or positive if (abs(myPersonDistance) < _myAttractionRadius) { float myAttractionStrength = myPersonDistance / _myAttractionRadius; myAttractionStrength = sin(PI * myAttractionStrength); _myPersonAttractor.set(myAttractionStrength * ourPlantAttractionFactor, 0, 0); } else { _myPersonAttractor.set(0,0,0); } float myDistanceScaler = 1 - (float)i/_myPlantStengel.length; // scaler to make segments smaller to the end float myDistance = _myPlantCurrentHeight * myDistanceScaler; // the distance for each segment, note it s 'distance' not 'height' Vector3f myOffset = new Vector3f(); // create an offset vector Vector3f mySwingVector = new Vector3f(); //create a swing vector mySwingVector.set(sin(_mySwingAngle) * _mySwingDistance ,0,0); myOffset.y += myDistance; //add height to offset myOffset.add(ourWind); //add wind to offset myOffset.add(mySwingVector); myOffset.add(_myPersonAttractor);//add Person Attractor to the offset vector myOffset.normalize(); //normalize the offset myOffset.multiply(-myDistance); // scale it to the desired distance _myPlantStengel[i].set(_myPlantStengel[i-1]); // copy the parent position _myPlantStengel[i].add(myOffset); // add offset to the position } //state is set do die when all seeds are gone if (_mySeedCounter <= 0 && _myLevel != 6){ _myState = DIE; } } //*STATE:DIE///////////////////////////////////////////////////////////////////////////////////////////////////////////// if (_myState == DIE){ _myPlantCurrentHeight += (_myGrowthSpeed / 2); for (int i=1; i<_myPlantStengel.length; i++){ float myDistanceScaler = 1 - (float)i/_myPlantStengel.length; // scaler to make segments smaller to the end float myDistance = _myPlantCurrentHeight * myDistanceScaler; // the distance for each segment, note it s 'distance' not 'height' Vector3f myOffset = new Vector3f(); // create an offset vector myOffset.y += myDistance; // add height to offset myOffset.add(ourWind); // add wind to offset //here the plant is dragged to the ground myOffset.y += _myDecayLevel; _myDecayLevel += _myGrowthSpeed / i / 2; myOffset.add(_myDecayDirection); myOffset.normalize(); // normalize the offset myOffset.multiply(-myDistance); // scale it to the desired distance _myPlantStengel[i].set(_myPlantStengel[i-1]); // copy the parent position _myPlantStengel[i].add(myOffset); // add offset to the position //set state to dead when second stengel is below "ground" if (_myPlantStengel[1].y > height){ _myState = DEAD; } } } //*STATE:DIE END///////////////////////////////////////////////////////////////////////////////////////////////////////////// } void draw() { for (int i=1; i<_myPlantStengel.length; i++){ stroke(_myBasicStroke-(i*(_myBasicStroke/15))); strokeWeight(1); line (_myPlantStengel[i-1].x, _myPlantStengel[i-1].y, _myPlantStengel[i].x, _myPlantStengel[i].y); } } } ///*PLANT END*//////////////////////////////////////////////////////////////////////////////////////////////////// ///*PERSON*////////////////////////////////////////////////////////////////////////////////////////////////////// class Person { Vector3f _myPosition; Vector3f _myPreviousPosition; boolean _myWaitingStarted = false; boolean _myJustCreatedPlant = false; int _myStartStandTime; int _myStandTime = ourPersonStandTime; int _myPersonwindCacheSize; float[] _myPersonwindCacheSteps; int _myCurrentCacheStepID; int _myTrackingCacheSize; float[] _myTrackingCacheSteps; int _myCurrentTrackingCacheStepID; Person(){ _myPosition = new Vector3f(); _myPreviousPosition = new Vector3f(); _myPersonwindCacheSize = 50; _myPersonwindCacheSteps = new float[_myPersonwindCacheSize]; _myCurrentCacheStepID = 0; _myTrackingCacheSize = 15; _myTrackingCacheSteps = new float[_myTrackingCacheSize]; _myCurrentTrackingCacheStepID = 0; } void setPosition(float theX, float theY, float theZ){ _myPosition.set(theX, theY, theZ); } Vector3f getPosition(){ return _myPosition; } void move(){ if(followMouse){ _myPosition.set(mouseX, mouseY, 0); } else { setTrackDeltaX(_myPersonX); _myPosition.set( (width/myScanWidth) * getAverageTrackingXpos(), 0, 0); } //sets wait time if (abs(_myPosition.x - _myPreviousPosition.x) <= myTrackingTolerance){ if (_myWaitingStarted == false && ourPersonHere){ _myStartStandTime = millis(); _myWaitingStarted = true; } if (millis() > _myStartStandTime + _myStandTime && _myJustCreatedPlant == false && ourPersonHere){ //create plant/// for (int i = 0; i < _myPlants.length; i++) { if (_myPlants[i] == null) { _myPlants[i] = new Plant( _myPosition.x, 6/*the Level*/, i/*the Plant ID*/); PlantCounter++; _myWaitingStarted = false; println("Person created plant " + i); _myJustCreatedPlant = true; break; } } //create plant end/// } } else { _myWaitingStarted=false; _myJustCreatedPlant=false; } } Vector3f _myPersonWind(){ float myDeltaX = _myPosition.x - _myPreviousPosition.x; setDeltaX(myDeltaX); Vector3f myWind = new Vector3f(); myWind.set(getAverageWind(),0,0); _myPreviousPosition.set(getPosition()); return myWind; } void setDeltaX(float theDeltaX) { _myPersonwindCacheSteps[_myCurrentCacheStepID] = theDeltaX; _myCurrentCacheStepID++; _myCurrentCacheStepID %= _myPersonwindCacheSteps.length; } float getAverageWind() { float myAverageWind = 0; for (int i = 0; i < _myPersonwindCacheSteps.length; i++) { myAverageWind += _myPersonwindCacheSteps[i]; } myAverageWind /= _myPersonwindCacheSteps.length; return myAverageWind; } void setTrackDeltaX(float theTrackDeltaX) { _myTrackingCacheSteps[_myCurrentTrackingCacheStepID] = theTrackDeltaX; _myCurrentTrackingCacheStepID++; _myCurrentTrackingCacheStepID %= _myTrackingCacheSteps.length; } float getAverageTrackingXpos() { float myAverageXpos = 0; for (int i = 0; i < _myTrackingCacheSteps.length; i++) { myAverageXpos += _myTrackingCacheSteps[i]; } myAverageXpos /= _myTrackingCacheSteps.length; return myAverageXpos; } void draw(){ stroke(255,0,0); strokeWeight(2); line(_myPosition.x, 0, _myPosition.x, height); stroke(100); line(_myPosition.x-ourAttractionRadius, 0, _myPosition.x-ourAttractionRadius, height); line(_myPosition.x+ourAttractionRadius, 0, _myPosition.x+ourAttractionRadius, height); } } ///*PERSON END*////////////////////////////////////////////////////////////////////////////////////////////////////// /*THE VECTORS*********************************************************/ class Vector3f { float x = 0; float y = 0; float z = 0; void set(float theX, float theY, float theZ) { x = theX; y = theY; z = theZ; } void set(Vector3f theVector) { x = theVector.x; y = theVector.y; z = theVector.z; } void add(Vector3f theVector) { x += theVector.x; y += theVector.y; z += theVector.z; } void sub(Vector3f theVector) { x -= theVector.x; y -= theVector.y; z -= theVector.z; } void multiply(float s) { x *= s; y *= s; z *= s; } float length() { float myLengthSquard = x*x + y*y + z*z; float myLength = sqrt(myLengthSquard); return myLength; } void normalize() { float d = length(); x /= d; y /= d; z /= d; } void cross(Vector3f a, Vector3f b) { x = a.y * b.z - a.z * b.y; y = b.x * a.z - b.z * a.x; z = a.x * b.y - a.y * b.x; } void print() { println("("+x+", "+y+", "+z+")"); } }