> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.pBmdVwyoDiW/rev.5029
 * 
 * authors: 
 *   InSat
 *   

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



// Pressing Control-R will render this sketch.

float MaxX;
float MaxY;

int Action_Sleep  = 0;
int Action_Follow = 1;
int Action_Goto   = 2;
int StartingAction   = Action_Sleep;

double TargetReached = 4.0;

public class Runner
{
    private float _x,_y;        // current location
    private float _distTgt;     // distance de la cible (destination,_next)
    private float _dstX, _dstY; // destination x,y
    private Runner _next;       // next runner
    private int _r,_g,_b;       // color    
    private int _action;        // action
    
    Runner(float x,float y,int r,int g,int b){
        _action = StartingAction;            
        _x = MaxX/2;     // Position de départ
        _y = MaxY/2;     // Position de départ
        SetGoto (x, y);
        SetColor(r,g,b);
    }    
        
    public float X() {
        return _x;
    }
    public float Y() {
        return _y;
    }
    
    public void SetFollowing(Runner next) {
        _next = next;
    } 
    public void SetColor(int r,int g,int b) {
        _r = r;
        _g = g;
        _b = b;
    }     
    public void SetGoto (float x, float y) {
        _dstX = x;
        _dstY = y;  
    }
    public double GetDistanceTarget() {
        return _distTgt;
    }
    public void SetAction(int action) {
        _action = action;
    }
    public int GetAction() {
        return _action;
    }
                    
    public void Draw() {
        stroke(_r, _g, _b, 100);  
                
        if(_action==Action_Sleep)
            point(_x,_y);
        else if(_action==Action_Follow)
            line(_x,_y, _next.X(), _next.Y()); 
        else if(_action==Action_Goto)               
            point(_x,_y);

    }
    
    public void Move() {   
        if(_action==Action_Sleep)
            { /* do nothing */ }
        else if(_action==Action_Follow)
            Follow(); 
        else if(_action==Action_Goto)               
            Goto();                                         
    }   

    // Go to destination 
    private void Goto() {                
        GotoTgt( _dstX, _dstY);
    }      
    // Follow _next runner
    private void Follow() {                
        GotoTgt(
            _next.X(), 
            _next.Y());
    }    
    // go to point x,y
    private void GotoTgt(float x, float y) {
        float dx = x - _x;
        float dy = y - _y;
        _distTgt = sqrt( dx * dx + dy * dy);        
        _x  = Move(_x , dx / _distTgt , MaxX );
        _y  = Move(_y , dy / _distTgt , MaxY );
    }
    
    private float Move(float p, float dp, float max) {
        p += 2 * dp; 
        // on est sur un tor...       
        if(p>max) {
            p = 0;            
        }
        if(p<0) {
            p = max;            
        }
        return p;
    }                
}

public class Strategy {

    private int _currentAction = StartingAction;
    private ArrayList _runners = new ArrayList();
        
    public void InitializeRunners() {
        
        _runners.add(new Runner(100,100,   99,00,00));
        _runners.add(new Runner(100,500,   00,99,00));
        _runners.add(new Runner(500,500,   00,00,99));
        _runners.add(new Runner(500,100,   00,99,00));  

        int countRunners = _runners.size();
        for (int i = 0; i < countRunners ; i++) { 
            Runner runner1 = (Runner)_runners.get(i);
            Runner runner2;            
            if(i+1==countRunners) {
              runner2 = (Runner)_runners.get(0);                          
            } else {
              runner2 = (Runner)_runners.get(i+1); 
            }
            runner1.SetFollowing(runner2);
        };                       
    }
    

    
    public void  Action() {
        
        if(_currentAction==Action_Sleep) {
            //  Go to target (starting location )
            _currentAction= Action_Goto;
        }
        else if(_currentAction==Action_Follow && AllTargetsReached()) {
            //  Go to target
           _currentAction = Action_Goto;                
            for (int i = 0; i < _runners.size() ; i++) {
                Runner runner = (Runner)_runners.get(i);          
                runner.SetGoto( 100+random(400), 100+random(400) );
                runner.SetColor((int)random(255),(int)random(255),(int)random(255));
            }
        }
        else if (_currentAction == Action_Goto && AllTargetsReached()) {
            //  Follow _next runner
            _currentAction=Action_Follow; 
        }
        
        for (int i = 0; i < _runners.size() ; i++) { 
            Runner runner = (Runner)_runners.get(i);
            runner.SetAction(_currentAction); 
            runner.Move();             
        }                 
    }
    
    private boolean  AllTargetsReached() {
        boolean  allTargetsReached = true;
        for (int i = 0; i < _runners.size() ; i++) {
            Runner runner = (Runner)_runners.get(i);
            allTargetsReached &= (runner.GetDistanceTarget() < TargetReached );
        }
        return allTargetsReached;
    }

    public void Draw() {
        for (int i = 0; i < _runners.size() ; i++) { 
            Runner runner = (Runner)_runners.get(i);
            runner.Draw(); 
        }  
    }
}

Strategy strategy;

void setup() {  // this is run once.   
    
    // set the background color
    background(0);
    
    // canvas size (Variable aren't evaluated. Integers only, please.)
    size(600, 600); 
    MaxX = 600;
    MaxY = 600;
      
    // smooth edges
    smooth();
    
    // limit the number of frames per second
    frameRate(30);
    
    // set the width of the line. 
    strokeWeight(4);        

    strategy = new Strategy();
    strategy.InitializeRunners();
        
} 

void draw() {  // this is run repeatedly.  
    
    strategy.Action();
    strategy.Draw();
    
}