save loops

Dependencies:   mbed

blobConfig.cpp

Committer:
mbedalvaro
Date:
2014-12-02
Revision:
1:3be7b7d050f4
Parent:
0:df6fdd9b99f0

File content as of revision 1:3be7b7d050f4:


#include "blobConfig.h"

blobConfig::blobConfig(): numBlobs(0) {
    //blobArray.clear();// there is no need to do this, the vector does not contains anything here.
}

blobConfig::~blobConfig() {
    clearConfig();
}

// =========================================== STANDARD CONFIGURATIONS =============================================================================



void blobConfig::clearConfig() {
    for (int i=0; i<blobArray.size(); i++) delete blobArray[i]; // we must delete the pointer created with new, so the memory for the object is liberated (calls its destructor)
    blobArray.clear();
    numBlobs=0;// this is just equal to blobArray.size()
}

void blobConfig::initConfig(configType cfType,  int numblobs) {
    myConfigType=cfType;
    int i;
    switch(myConfigType) {
        case ONE_ELASTIC_FOLLOWING:
            // computeBoundingBox();
            clearConfig();
            addOneElasticContourFollowing();
        break;
        case ONE_ELASTIC_MOUTH:
            // computeBoundingBox();
            clearConfig();
            addOneElasticLoopContractCentral();
        break;
        case ONE_ELASTIC_MOUTH_SMALL:
            // computeBoundingBox();
            clearConfig();
            addOneElasticLoopContractCentralFast();
        break;
        case BOUNCING_SPOTS:
            // computeBoundingBox();
           clearConfig();
           for (i=0; i<numblobs ; i++) addOneRigidLoopBouncing();
           randomizeAllColors();
        break;
        case LORENTZ_SPOTS:
         // computeBoundingBox();
            clearConfig();
            for (i=0; i<numblobs ; i++) addOneRigidLoopLorentz();
            randomizeAllColors();
        break;
        case FOLLOWING_SPOTS:
         // computeBoundingBox();
            clearConfig();
            for (i=0; i<numblobs ; i++) {
                addOneRigidLoopFollowing(vector2Df(CENTER_AD_MIRROR_X+i*200, CENTER_AD_MIRROR_Y+i*200), vector2Df(11,0));
                }
            // randomize colors:
            randomizeAllColors();
        break;
        case ONE_TRACKING_SPOT:
           clearConfig();
           addOneRigidTrackingSpot();
        break;
         case ONE_TRACKING_SPOT_DOT:
           clearConfig();
           addOneRigidTrackingSpotDot();
        break;
        case AIR_HOCKEY_GAME: 
            // computeBoundingBox();
            clearConfig();
            for (i=0; i<numblobs ; i++) addOneRigidLoopAirHockey();
        break;
        case CIRCULAR_PONG_GAME:
            // computeBoundingBox();
            clearConfig();
            // (1) One SPOT_TRACK to track the background. It will be the number 0 in the config. 
            addOneRigidTrackingSpotDot();
            // (2) Add bouncing spots:
            for (i=0; i<numblobs ; i++) {
                float anglaux=1.0*i/numblobs*2*PI;
                addOneRigidLoopBouncing(vector2Df(CENTER_AD_MIRROR_X+200*cos(anglaux), CENTER_AD_MIRROR_Y+200*sin(anglaux)), 
                                        vector2Df(5*cos(anglaux),sin(anglaux))*10);
            }
        break;
        case VERTICAL_PINBALL_GAME:
         clearConfig();
         // (1) one (or two) SPOT_TRACK or SPOT_TRACK_DOT to track the background - It will be the number 0 (and 1) in the config. 
          addOneRigidTrackingSpotDot(vector2Df(CENTER_AD_MIRROR_X, CENTER_AD_MIRROR_Y+600), 
                                     vector2Df(0,0));
         // addOneRigidTrackingSpot(vector2Df(CENTER_AD_MIRROR_X, CENTER_AD_MIRROR_Y+600), 
          //                           vector2Df(0,0));
         // (2) one or more bouncing spots with gravity:
         for (i=0; i<numblobs ; i++) {
            addOneRigidLoopBouncingGravity(vector2Df(CENTER_AD_MIRROR_X, CENTER_AD_MIRROR_Y-600), 
                                           vector2Df(i*10-5,0));   
         }                   

        break; 
        case RAIN_MODE:
        clearConfig();
         // Add bouncing spot with gravity:
          for (i=0; i<numblobs ; i++) {
          addOneRigidLoopBouncingGravity(vector2Df(CENTER_AD_MIRROR_X, 10), vector2Df(0,0));   
         }       
          randomizeAllColors();
        break;
        case FISH_NET_GAME:
        clearConfig();
         // (1) one SPOT_TRACK_DOT to track the background - It will be the number 0  
          addOneRigidTrackingSpotDot(vector2Df(CENTER_AD_MIRROR_X, CENTER_AD_MIRROR_Y),  // CENTERED
                                     vector2Df(0,0));
        // (2) Add bouncing spots without gravity:
            for (i=0; i<numblobs ; i++) {
                float anglaux=1.0*i/numblobs*2*PI;
                addOneRigidLoopBouncing(vector2Df(CENTER_AD_MIRROR_X+400*cos(anglaux), CENTER_AD_MIRROR_Y+400*sin(anglaux)), 
                                        vector2Df(cos(anglaux),sin(anglaux))*10);
            }                      
        break;
        case PAC_MAN_GAME:
            clearConfig();
            //(1) add one very slowly slidind-bouncing spot, the PACMAN (number 0 in the config):
           // addOneRigidLoopPacman(vector2Df(CENTER_AD_MIRROR_X, CENTER_AD_MIRROR_Y), vector2Df(20,0));
           
           // note: the pacman behaviour is not so good... for the time being, let's just use a following spot:
            addOneRigidLoopFollowing(vector2Df(CENTER_AD_MIRROR_X, CENTER_AD_MIRROR_Y), vector2Df(10,0));
            // set the color to red+green:
            blobArray.back()->setColor(0x06);
          
          
            // (2) Add some initial SPOT_FOLLOWING or SPOT_GHOST spots (the ghosts):
            addOneRigidLoopGhost(vector2Df(CENTER_AD_MIRROR_X+500, CENTER_AD_MIRROR_Y-500), vector2Df(-5,0));
            addOneRigidLoopGhost(vector2Df(CENTER_AD_MIRROR_X-500, CENTER_AD_MIRROR_Y-500), vector2Df(5,0));
            
        break;
        default:
        break;
    }
    
    // make sure lockin red is ON (could be off if using blue for checking mirror delay...):
    IO.setLaserLockinPower(1);
}

void blobConfig::printParameters() {
    for (int i=0; i<blobArray.size(); i++) { 
     pc.printf("Blob n.%d\n", i);
     blobArray[i]->printParameters(); // a blob that is in stand-by mode may send data (good for testing with a fixed loop)
    }
    }

 // ==================== Template spots from which to create multi-spot configurations: =====================

void blobConfig::addOneElasticLoopRelax(vector2Df initpos, vector2Df initspeed) {
    elasticLoop* pBlob= new elasticLoop();
    pBlob->createBlob(blobArray.size(), RELAX, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();

}


void blobConfig::addOneElasticLoopContract(vector2Df initpos, vector2Df initspeed) {
    elasticLoop* pBlob= new elasticLoop();
    pBlob->createBlob(blobArray.size(), CONTRACT, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneElasticLoopContractCentral(vector2Df initpos, vector2Df initspeed) {
    elasticLoop* pBlob= new elasticLoop();
    pBlob->createBlob(blobArray.size(), CONTRACT_CENTRAL, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneElasticLoopContractCentralFast(vector2Df initpos, vector2Df initspeed) {
    elasticLoop* pBlob= new elasticLoop();
    pBlob->createBlob(blobArray.size(), CONTRACT_CENTRAL_FAST, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneElasticContourFollowing(vector2Df initpos, vector2Df initspeed) {

    elasticLoop* pBlob= new elasticLoop();
    pBlob->createBlob(blobArray.size(), CONTOUR_FOLLOWING, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}


void blobConfig:: addOneElasticContourFollowingFAST(vector2Df initpos, vector2Df initspeed) {
    elasticLoop* pBlob= new elasticLoop();
    pBlob->createBlob(blobArray.size(), CONTOUR_FOLLOWING_FAST,  initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneElasticBouncing(vector2Df initpos, vector2Df initspeed) {
    elasticLoop* pBlob= new elasticLoop();
    pBlob->createBlob(blobArray.size(), BOUNCING,  initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}
void blobConfig::addOneRigidLoopBouncingGravity(vector2Df initpos, vector2Df initspeed) {
    rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_BOUNCING_FACTOR,  initpos, initspeed);
    // (We can use here methods of the child class, even if these are not declared virtual on the base class, because we are doing this BEFORE
    // adding this to the blobArray as a pointer). This is good to set parameters...
    pBlob->gravity.set(0,3.5);  
    pBlob->centerMass.dampMotion = 0.002;
    pBlob->factorBouncingForce=0;//0.003; // this is because we will use a force on the central mass (not used in SPOT_BOUNCING_FACTOR)
    pBlob->factorAbsorptionShock=0.9; // coef elastic bouncing
   
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}
void blobConfig::addOneRigidLoopBouncing(vector2Df initpos, vector2Df initspeed) {
    rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_BOUNCING_FACTOR, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);
 
    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneRigidLoopPacman(vector2Df initpos, vector2Df initspeed) {
    rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_PACMAN, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}
void blobConfig::addOneRigidLoopGhost(vector2Df initpos, vector2Df initspeed) {
    rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_GHOST, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}


void blobConfig::addOneRigidLoopLorentz(vector2Df initpos, vector2Df initspeed) {
    rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_LORENTZ_FORCE, initpos, initspeed);
    // add this loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneRigidLoopAirHockey(vector2Df initpos, vector2Df initspeed) {
    rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_AIR_HOCKEY,  initpos, initspeed);
    // add this loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneRigidLoopFollowing(vector2Df initpos, vector2Df initspeed) {
    rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_FOLLOWING, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);
    
    // random color for Tokyo Designer Week:
    //randomizeAllColors();

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneRigidLoopTest(vector2Df initpos, vector2Df initspeed) {
    rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_TEST, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneRigidTrackingSpot(vector2Df initpos, vector2Df initspeed) {
   rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_TRACK, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}

void blobConfig::addOneRigidTrackingSpotDot(vector2Df initpos, vector2Df initspeed) {
   rigidLoop* pBlob= new rigidLoop();
    pBlob->createBlob(blobArray.size(), SPOT_TRACK_DOT, initpos, initspeed);
    // add this relaxing loop to the present config:
    blobArray.push_back(pBlob);

    // update auxiliary variable numBlobs (just for easy reference):
    numBlobs=blobArray.size();
}
// ==================================================================================================================================================
void blobConfig::processSensedData() {
     for (int i=0; i<blobArray.size(); i++) blobArray[i]->displaySensingBuffer.processSensedData(); // note: region with light is -1, and without is 2 (TO CHANGE!!! then we don't need to do "if" in the moment computation, but just a product)
}

void blobConfig::allKill() { // this put all the blobs in "dead" mode, meaning that neither rendering nor update is done (but they are not deleted).
    for (int i=0; i<blobArray.size(); i++) {
        blobArray[i]->render = false;
        blobArray[i]->standByMode = true;
    }
}
void blobConfig::allAlive() {
    for (int i=0; i<blobArray.size(); i++) {
        blobArray[i]->render = true;
        blobArray[i]->standByMode = false;
    }
}

void blobConfig::allStandBy() {
    for (int i=0; i<blobArray.size(); i++) blobArray[i]->standByMode = true;
}

void blobConfig::allResume() {
    for (int i=0; i<blobArray.size(); i++) blobArray[i]->standByMode = false;
}

void blobConfig::allVisible() {
    for (int i=0; i<blobArray.size(); i++) blobArray[i]->render = true;
}

void blobConfig::allInvisible() { // note that they may continue to evolve
    for (int i=0; i<blobArray.size(); i++) blobArray[i]->render = false;
}

void blobConfig::allSetColor(unsigned char c) {
    for (int i=0; i<blobArray.size(); i++) blobArray[i]->setColor(c);
 }
 
 void blobConfig::allSetGreen(unsigned char c) {
    for (int i=0; i<blobArray.size(); i++) blobArray[i]->setGreenColor(c);
 }
 
  void blobConfig::allSetBlue(unsigned char c) {
    for (int i=0; i<blobArray.size(); i++) blobArray[i]->setBlueColor(c);
 }
 
  void blobConfig::randomizeAllColors() {   
    int c;
    for (int i=0; i<blobArray.size(); i++) {
     c= rand() % 2;  
     blobArray[i]->setBlueColor(c);
     c= rand() % 2;  
     blobArray[i]->setGreenColor(c);
 }
 }

void blobConfig::update() { // update dynamics of the blob configuration:
int i;
float minDist=5000, dist;
bool win;
    // Depending on the config type, perform some special test and updates: 
   switch(myConfigType) {
        // simple behaviours:
        case ONE_ELASTIC_FOLLOWING:
        case ONE_ELASTIC_MOUTH:
        case ONE_ELASTIC_MOUTH_SMALL:
        case BOUNCING_SPOTS:
        case LORENTZ_SPOTS:
        case FOLLOWING_SPOTS:
        case ONE_TRACKING_SPOT:
        case AIR_HOCKEY_GAME:
            // In all these simple cases, update dynamics of each blob independently:
            for (i=0; i<blobArray.size(); i++) {
                 if (blobArray[i]->standByMode==false) blobArray[i]->update();
            }
        break; 
        // more game-like:
        case CIRCULAR_PONG_GAME:
          // spot index 0 is a tracking spot, the background "anchor":
         if (blobArray[0]->standByMode==false) blobArray[0]->update();
         // all the other spots are bouncing spots:
        for (i=1; i<blobArray.size(); i++) {
            if (blobArray[i]->standByMode==false) blobArray[i]->update();
        }
        // GAME CHECK: is some bouncing spot too far from the anchor? if so, make it "explode" (and then dissapear, but leave this for now):
        for (i=1; i<blobArray.size(); i++) {
            dist=(blobArray[0]->getCenter()).distance(blobArray[i]->getCenter());
            if (dist>1000) {
                blobArray[i]->explosion();
                float anglaux=1.0*(i-1)/(blobArray.size()-1)*2*PI;
                 blobArray[i]->setPositionSpeed(vector2Df(CENTER_AD_MIRROR_X+200*cos(anglaux), CENTER_AD_MIRROR_Y+200*sin(anglaux)), 
                                                vector2Df(cos(anglaux),sin(anglaux))*10);
            }
        }
        break;
        case RAIN_MODE: // this is just spots with gravity that reapears in the top position when reaching the bottom:
          // others are bouncing with gravity:
        for (i=0; i<blobArray.size(); i++) {
            if (blobArray[i]->standByMode==false) blobArray[i]->update();
        }
        // GAME CHECKS:
         for (i=0; i<blobArray.size(); i++) {
           if (blobArray[i]->getCenter().y>MAX_AD_MIRRORS-20) {
           // Replace position of spot to the initial position:
                blobArray[i]->explosion();
                blobArray[i]->resetPositionSpeed();
            }
      }
        break;
        case VERTICAL_PINBALL_GAME:
          // spot index 0 is a tracking spot, the background "anchor":
         if (blobArray[0]->standByMode==false) blobArray[0]->update();
         // others are bouncing with gravity:
        for (i=1; i<blobArray.size(); i++) {
            if (blobArray[i]->standByMode==false) blobArray[i]->update();
        }
        // GAME CHECKS:
         for (i=1; i<blobArray.size(); i++) {
            dist=(blobArray[0]->getCenter()).distance(blobArray[i]->getCenter());
            //(1) win (meaning bouncing spot very close to anchor):
            if (dist<60) {
                blobArray[i]->explosion();
                blobArray[i]->setPositionSpeed(vector2Df(blobArray[0]->getCenter().x-400+rand()%800, blobArray[0]->getCenter().y-1200), 
                                                        vector2Df(0, 0));
            }
            //(2) loose (meaning spot went outside range):
            if (blobArray[i]->getCenter().y>blobArray[0]->getCenter().y) {
                blobArray[i]->setPositionSpeed(vector2Df(blobArray[0]->getCenter().x-400+rand()%800, blobArray[0]->getCenter().y-1200), 
                                                        vector2Df(i*10-5, 0));
                }
            }
        break; 
        case FISH_NET_GAME:
         // spot index 0 is a tracking spot, the background "anchor":
         if (blobArray[0]->standByMode==false) blobArray[0]->update();
         // all the other spots are bouncing spots:
        for (i=1; i<blobArray.size(); i++) {
            if (blobArray[i]->standByMode==false) blobArray[i]->update();
        }
        // GAME CHECKS: a win only, when all the spots are very close to the mother spot:
         win=true;
         for (i=1; i<blobArray.size(); i++) {
            dist=(blobArray[0]->getCenter()).distance(blobArray[i]->getCenter());
            win&=(dist<80);
        }
        if (win) {
            for (i=1; i<blobArray.size(); i++) {
            blobArray[i]->explosion();
             float anglaux=1.0*(i-1)/(blobArray.size()-1)*2*PI;
                 blobArray[i]->setPositionSpeed(vector2Df(CENTER_AD_MIRROR_X+400*cos(anglaux), CENTER_AD_MIRROR_Y+400*sin(anglaux)), 
                                                vector2Df(cos(anglaux),sin(anglaux))*10);
        }
        }
        break;
        case PAC_MAN_GAME:
        // spot index 0 is the pacman:
        if (blobArray[0]->standByMode==false) blobArray[0]->update();
        // spot 1 and 2 are ghosts:
        if (blobArray[1]->standByMode==false) blobArray[1]->update(blobArray[0]->getCenter());
        if (blobArray[2]->standByMode==false) blobArray[2]->update(blobArray[0]->getCenter()); // pass the position of the PACMAN!
        
        // GAME CHECK: are any ghost too close to the pacman?
        for (i=1; i<blobArray.size(); i++) {
            dist=(blobArray[0]->getCenter()).distance(blobArray[i]->getCenter());
            if (minDist>dist) minDist=dist;
        }
        if (minDist<50) {
             blobArray[0]->explosion();
             // then restart the game: 
            // initConfig(PAC_MAN_GAME);
        }
        
        break;
        default:
        break;
    }
     
    
}

void blobConfig::computeBoundingBox() {
    for (int i=0; i<blobArray.size(); i++) {
        blobArray[i]->computeBoundingBox();
    }
}

void blobConfig::draw() { // draw uses the opengl like renderer (if any), and save projected trajectory in the LaserSensingTrajectory object of each blob
    for (int i=0; i<blobArray.size(); i++) {
        if (blobArray[i]->render==true) blobArray[i]->draw();
    }
}

void blobConfig::sendConfData() {
// For the time being, only "per blob" data sending:
// (b) Per-spot sending of data (note: both are NOT exclusive; so if we want just packaged data, 
// we need to make all the spot STOP sending data.
    for (int i=0; i<blobArray.size(); i++) { 
        if (blobArray[i]->render==true) blobArray[i]->sendData(); // a blob that is in stand-by mode may send data (good for testing with a fixed loop)
    }
}