//------------------------------------------------------------------
void seraParticle::update(){
    ofPoint attractPt(mahoPos[1].x, mahoPos[1].y);
    frc = attractPt-pos;
    frc.normalize();
    vel *= drag;
    vel += frc * seraParticleKasokuAmt;
	pos += vel;
}
 void demoParticle::choca( )
 {

     ofPoint attractPt(ofGetMouseX(), ofGetMouseY());
     frc = attractPt-pos;

     //obtiene la distancia
	 float dist = frc.length();
     frc.normalize();

     // se repelen los puntos serca del mouse
	 if( dist < 90 ){
         pos += -frc * 0.1;
      }
  }
//------------------------------------------------------------------
void demoParticle::update(){
    
	// 1 - APPLY THE FORCES BASED ON WHICH MODE WE ARE IN
	// 1 - 加载的力取决于我们选择何种模式
	if( mode == PARTICLE_MODE_ATTRACT ){
		ofPoint attractPt(ofGetMouseX(), ofGetMouseY());
		frc = attractPt-pos;		// we get the attraction force/vector by looking at the mouse pos relative to our pos
        // 粒子获得的引力是通过计算鼠标位置和粒子位置的关系得到的
        
		frc.normalize();			// by normalizing we disregard how close the particle is to the attraction point
                                    // 通过初始化力,我们忽略了粒子和吸引点之间的距离。
        
		vel *= drag;				// apply drag
                                    // 用拖拽
        
		vel += frc * 0.6;			// apply force
                                    // 用力
	}
	else if( mode == PARTICLE_MODE_REPEL ){
		ofPoint attractPt(ofGetMouseX(), ofGetMouseY());
		frc = attractPt-pos;
		
		// let get the distance and only repel points close to the mouse
        // 击退离鼠标够近的粒子
		float dist = frc.length();
		frc.normalize();
		
		vel *= drag;
		if( dist < 150 ){
			vel += -frc * 0.6;		// notice the frc is negative
                                    // 注意,力是相反的
		}else{
            
			//if the particles are not close to us, lets add a little bit of random movement using noise. this is where uniqueVal comes in handy.
            //如果粒子不够靠近,我们可以用噪点制造一些随机移动。这就是为什么我们前面创建了一个随机数字,它让每个粒子的移动略微不同。
			frc.x = ofSignedNoise(uniqueVal, pos.y * 0.01, ofGetElapsedTimef()*0.2);
			frc.y = ofSignedNoise(uniqueVal, pos.x * 0.01, ofGetElapsedTimef()*0.2);
			vel += frc * 0.04;
		}
	}
	else if( mode == PARTICLE_MODE_NOISE ){
        
		/* lets simulate falling snow
         the fake wind is meant to add a shift to the particles based on where in x they are
         we add pos.y as an arg so to prevent obvious vertical banding around x values - try removing the pos.y * 0.006 to see the banding
         
         下面,我们会用粒子模拟下雪的效果
         为了模拟风对雪的影响,我们会在x轴上加入一个移动效果
         提供y坐标为了不给x坐标过多的影响力
         */
		float fakeWindX = ofSignedNoise(pos.x * 0.003, pos.y * 0.006, ofGetElapsedTimef() * 0.6);
		
		frc.x = fakeWindX * 0.25 + ofSignedNoise(uniqueVal, pos.y * 0.04) * 0.6;
		frc.y = ofSignedNoise(uniqueVal, pos.x * 0.006, ofGetElapsedTimef()*0.2) * 0.09 + 0.18;
        
		vel *= drag;
		vel += frc * 0.4;
		
		// we do this so as to skip the bounds check for the bottom and make the particles go back to the top of the screen
		// 如果往下移动时发现跨过边界,就屏幕下消失然后从上面出现
		if( pos.y + vel.y > ofGetHeight() ){
			pos.y -= ofGetHeight();
		}
	}
	else if( mode == PARTICLE_MODE_NEAREST_POINTS ){
		
		if( attractPoints ){
            
			// 1 - find closest attractPoint
			// 1 - 寻找周围最接近的粒子
			ofPoint closestPt;
			int closest = -1;
			float closestDist = 9999999;
			
			for(unsigned int i = 0; i < attractPoints->size(); i++){
				float lenSq = ( attractPoints->at(i)-pos ).lengthSquared();
				if( lenSq < closestDist ){
					closestDist = lenSq;
					closest = i;
				}
			}
			
			// 2 - if we have a closest point - lets calcuate the force towards it
			// 2 - 计算力对closetPt产生的力量
			if( closest != -1 ){
				closestPt = attractPoints->at(closest);
				float dist = sqrt(closestDist);
				
				// in this case we don't normalize as we want to have the force proportional to distance
				// 不要规范为0至1,力量必须相对一距离
				frc = closestPt - pos;
                
				// 别忘了乘以拖拽
				vel *= drag;
                
				// lets also limit our attraction to a certain distance and don't apply if 'f' key is pressed
				// 设置吸引力的底线,如果按下'f'就放弃
				if( dist < 300 && dist > 40 && !ofGetKeyPressed('f') ){
					vel += frc * 0.003;
				}else{
					// if the particles are not close to us, lets add a little bit of random movement using noise. this is where uniqueVal comes in handy.
					// 距离够远的话可以考虑添加一点随机行为
					frc.x = ofSignedNoise(uniqueVal, pos.y * 0.01, ofGetElapsedTimef()*0.2);
					frc.y = ofSignedNoise(uniqueVal, pos.x * 0.01, ofGetElapsedTimef()*0.2);
					vel += frc * 0.4;
				}
			}
		}
	}
	
	
	// 2 - UPDATE OUR POSITION
	// 2 - 更新位置
	pos += vel;
	
	
	// 3 - (optional) LIMIT THE PARTICLES TO STAY ON SCREEN
	// we could also pass in bounds to check - or alternatively do this at the ofApp level
	// 防止粒子走出屏幕,碰到边界时就立刻改变方向
	if( pos.x > ofGetWidth() ){
		pos.x = ofGetWidth();
		vel.x *= -1.0;
	}else if( pos.x < 0 ){
		pos.x = 0;
		vel.x *= -1.0;
	}
	if( pos.y > ofGetHeight() ){
		pos.y = ofGetHeight();
		vel.y *= -1.0;
	}
	else if( pos.y < 0 ){
		pos.y = 0;
		vel.y *= -1.0;
	}
}
//------------------------------------------------------------------
void demoParticle::update(ofPoint extraAttractor){

	//1 - APPLY THE FORCES BASED ON WHICH MODE WE ARE IN 
	
	if( mode == PARTICLE_MODE_ATTRACT ){
		/*
		ofVec2f attractPt(ofGetMouseX(), ofGetMouseY());
		frc = attractPt-pos; // we get the attraction force/vector by looking at the mouse pos relative to our pos
		frc.normalize(); //by normalizing we disregard how close the particle is to the attraction point 
		
		vel *= drag; //apply drag
		vel += frc * 0.6; //apply force
		 
		 */
		

		ofPoint attractPt = extraAttractor;
		frc = attractPt-pos; // we get the attraction force/vector by looking at the mouse pos relative to our pos
		frc.normalize(); //by normalizing we disregard how close the particle is to the attraction point
		
		vel *= drag; //apply drag
		vel += frc * 0.6; //apply force
		
		
	}
	else if( mode == PARTICLE_MODE_REPEL ){
		ofVec2f attractPt(ofGetMouseX(), ofGetMouseY());
		frc = attractPt-pos; 
		
		//let get the distance and only repel points close to the mouse
		float dist = frc.length();
		frc.normalize(); 
		
		vel *= drag; 
		if( dist < 150 ){
			vel += -frc * 0.6; //notice the frc is negative 
		}else{
			//if the particles are not close to us, lets add a little bit of random movement using noise. this is where uniqueVal comes in handy. 			
			frc.x = ofSignedNoise(uniqueVal, pos.y * 0.01, ofGetElapsedTimef()*0.2);
			frc.y = ofSignedNoise(uniqueVal, pos.x * 0.01, ofGetElapsedTimef()*0.2);
			vel += frc * 0.04;
		}
	}
	else if( mode == PARTICLE_MODE_NOISE ){
		//lets simulate falling snow 
		//the fake wind is meant to add a shift to the particles based on where in x they are
		//we add pos.y as an arg so to prevent obvious vertical banding around x values - try removing the pos.y * 0.006 to see the banding
		float fakeWindX = ofSignedNoise(pos.x * 0.003, pos.y * 0.006, ofGetElapsedTimef() * 0.6);
		
		frc.x = fakeWindX * 0.25 + ofSignedNoise(uniqueVal, pos.y * 0.04) * 0.6;
		frc.y = ofSignedNoise(uniqueVal, pos.x * 0.006, ofGetElapsedTimef()*0.2) * 0.09 + 0.18;

		vel *= drag; 
		vel += frc * 0.4;
		
		//we do this so as to skip the bounds check for the bottom and make the particles go back to the top of the screen
		if( pos.y + vel.y > ofGetHeight() ){
			pos.y -= ofGetHeight();
		}
	}
	else if( mode == PARTICLE_MODE_NEAREST_POINTS ){
		
		
		if( attractPoints ){ 
			

			//1 - find closest attractPoint
			ofVec2f closestPt;
			int closest = -1; 
			float closestDist = 9999999;
			
			for(unsigned int i = 0; i < attractPoints->size(); i++){
				float lenSq = ( attractPoints->at(i)-pos ).lengthSquared();
				if( lenSq < closestDist ){
					closestDist = lenSq;
					closest = i;
				}
			}
			
			//2 - if we have a closest point - lets calcuate the force towards it
			if( closest != -1 ){
				closestPt = attractPoints->at(closest);				
				float dist = sqrt(closestDist);
				
				//in this case we don't normalize as we want to have the force proportional to distance 
				frc = closestPt - pos;
		
				vel *= drag;
				 
				//lets also limit our attraction to a certain distance and don't apply if 'f' key is pressed
				if( dist < 300 && dist > 40 && !ofGetKeyPressed('f') ){
					vel += frc * 0.003;
				}else{
					//if the particles are not close to us, lets add a little bit of random movement using noise. this is where uniqueVal comes in handy. 			
					frc.x = ofSignedNoise(uniqueVal, pos.y * 0.01, ofGetElapsedTimef()*0.2);
					frc.y = ofSignedNoise(uniqueVal, pos.x * 0.01, ofGetElapsedTimef()*0.2);
					vel += frc * 0.4;
				}
				
			}
		 
		}
		
		
		
		
	}
	
	
	//2 - UPDATE OUR POSITION
	
	pos += vel; 
	
	
	//3 - (optional) LIMIT THE PARTICLES TO STAY ON SCREEN 
	//we could also pass in bounds to check - or alternatively do this at the ofApp level
	if( pos.x > ofGetWidth() ){
		pos.x = ofGetWidth();
		vel.x *= -1.0;
	}else if( pos.x < 0 ){
		pos.x = 0;
		vel.x *= -1.0;
	}
	if( pos.y > ofGetHeight() ){
		pos.y = ofGetHeight();
		vel.y *= -1.0;
	}
	else if( pos.y < 0 ){
		pos.y = 0;
		vel.y *= -1.0;
	}	
		
}