将继承与基于stdvector的flocking一起使用

时间:2012-11-06 14:28:17

标签: c++ subclass stdvector openframeworks flock

目前我正在进行一项任务,我必须制作一个具有不同子类的植绒系统。我正在使用OpenFrameworks和C ++。 我是Open Frameworks和C ++的新手。

作为基础我这个代码: https://sites.google.com/site/ofauckland/examples/ofxflocking-example

然而,事情是,这个代码的结构与我习惯的不同;用'new ...'创建新的类对象

我的问题是,如何使用两个植绒类?首先,例如,首先只使用不同的颜色。

到目前为止我添加的其中一个子类是:

class Team1 : public Boid {
public:

   Team1(): Boid() {};
   Team1(int x, int y): Boid(x,y) {};



   void draw()
    {

    }
};

我使用虚拟空隙绘制来获取超类Boid的虚空绘制,并使用了boids.push_back(* new Team1());在设置和mousedrag中。这会出现以下错误:

  • Team1
  • 之前的预期类型说明符
  • )
  • 之前预期Team1
  • 没有用于调用std::vector<Boid, std::allocator<Boid> >::push_back(int&)
  • 的匹配功能

整个代码:(所有代码都在一个testapp.cpp文件中以排除链接问题)

//number of boids
const int BoidAmount = 25;

Superclass Boid:

class Boid {
public:
Boid();
Boid(int x, int y);

void update(vector<Boid> &boids);
virtual void draw() {};

void seek(ofVec2f target);
void avoid(ofVec2f target);
void arrive(ofVec2f target);

void flock(vector<Boid> &boids);

ofVec2f steer(ofVec2f target, bool slowdown);   

ofVec2f separate(vector<Boid> &boids);
ofVec2f align(vector<Boid> &boids);
ofVec2f cohesion(vector<Boid> &boids);

ofVec2f location,direction

,acceleration;

float r;
float attraction;
float maxspeed;
};

构造

 //---Constructors(overload)-----------------------------------------
Boid::Boid() {
location.set(ofRandomWidth(),ofRandomHeight());
direction.set(0,0);
acceleration.set(0,0);
r = 3.0;
maxspeed = 4;
attraction = 0.05; 
}

Boid::Boid(int x, int y) {
location.set(x,y); //initial location
direction.set(0,0); //initial direction
acceleration.set(0,0); //initial acceleration   
r = 3.0;
maxspeed = 4; // initial max speed
attraction = 0.1; // initial max force
}

子类:

class Team1 : public Boid {
public:

Team1(): Boid() {};
Team1(int x, int y): Boid(x,y) {};



void draw()
{
    // Draw a triangle rotated in the direction of direction
    float angle = (float)atan2(-direction.y, direction.x);
    float theta =  -1.0*angle;
    float heading2D = ofRadToDeg(theta)+90;

    ofPushStyle();
    ofFill();


    ofPushMatrix();
    ofTranslate(location.x, location.y);

    ofRotateZ(heading2D);
    ofSetColor(255,255,255,80);

    ofEllipse(0, -r*2, 7, 12);
    ofBeginShape();
    ofVertex(0, -r*2);
    ofVertex(-r, r*2);
    ofVertex(r, r*2);
    ofEndShape(true);   
    ofPopMatrix();
    ofPopStyle();
}
};

class Team2 : public Boid {
public:

Team2(): Boid() {};
Team2(int x, int y): Boid(x,y) {};


void draw()
{


}

};

Methods:

// Method to update location
void Boid::update(vector<Boid> &boids) {

flock(boids);

direction += acceleration;   // Update direction
direction.x = ofClamp(direction.x, -maxspeed, maxspeed);  // Limit speed
direction.y = ofClamp(direction.y, -maxspeed, maxspeed);  // Limit speed
location += direction;
acceleration = 0;  // Reset accelertion to 0 each cycle

if (location.x < -r) location.x = ofGetWidth()+r;
if (location.y < -r) location.y = ofGetHeight()+r;

if (location.x > ofGetWidth()+r) location.x = -r;
if (location.y > ofGetHeight()+r) location.y = -r;
}

//SEEK
void Boid::seek(ofVec2f target) {
acceleration += steer(target, false);
}



// A method that calculates a steering vector towards a target
// Takes a second argument, if true, it slows down as it approaches the target
ofVec2f Boid::steer(ofVec2f target, bool slowdown) {
   ofVec2f steer;  // The steering vector
   ofVec2f desired = target - location;  // A vector pointing from the location to the target

float d = ofDist(target.x, target.y, location.x, location.y); // Distance from the target is the magnitude of the vector


// If the distance is greater than 0, calc steering (otherwise return zero vector)
if (d > 0) {

    desired /= d; // Normalize desired

    // Two options for desired vector magnitude (1 -- based on distance, 2 -- maxspeed)
    if ((slowdown) && (d < 100.0f)) {
        desired *= maxspeed * (d/100.0f); // This damping is somewhat arbitrary
    } else {
        desired *= maxspeed;
    }
    // Steering = Desired minus direction
    steer = desired - direction;
    steer.x = ofClamp(steer.x, -attraction, attraction); // Limit to maximum steering force
    steer.y = ofClamp(steer.y, -attraction, attraction); 

}
return steer;
}



//----------FLOCKING-BEHAVIOUR-------------------------------------------

void Boid::flock(vector<Boid> &boids) {
ofVec2f Seperation = separate(boids);
ofVec2f Alignment = align(boids);
ofVec2f Cohesion = cohesion(boids);

// Arbitrarily weight these forces
Seperation *= 1.5;
Alignment *= 1.0;
Cohesion *= 1.0;

acceleration += Seperation + Alignment + Cohesion;
}

//--SEPERATION--
// Method checks for nearby boids and steers away
ofVec2f Boid::separate(vector<Boid> &boids) {
float desiredseparation = 30.0;
ofVec2f steer;
int count = 0;

// For every boid in the system, check if it's too close
for (int i = 0 ; i < boids.size(); i++) {
    Boid &other = boids[i];

    float d = ofDist(location.x, location.y, other.location.x, other.location.y);

    // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
    if ((d > 0) && (d < desiredseparation)) {
        // Calculate vector pointing away from neighbor
        ofVec2f diff = location - other.location;
        diff /= d;          // normalize
        diff /= d;        // Weight by distance
        steer += diff;
        count++;            // Keep track of how many
    }
}
// Average -- divide by how many
if (count > 0) {
    steer /= (float)count;
}


// As long as the vector is greater than 0
//float mag = sqrt(steer.x*steer.x + steer.y*steer.y);

float mag = sqrt(steer.x*steer.x + steer.y*steer.y);
if (mag > 0) {
    // Steering = Desired - direction
    steer /= mag;
    steer *= maxspeed;
    steer -= direction;
    steer.x = ofClamp(steer.x, -attraction, attraction);
    steer.y = ofClamp(steer.y, -attraction, attraction);
}
return steer;
}

//--ALIGNMENT--
// For every nearby boid in the system, calculate the average direction
ofVec2f Boid::align(vector<Boid> &boids) {
float neighbordist = 60.0;
ofVec2f steer;
int count = 0;
for (int i = 0 ; i < boids.size(); i++) {
    Boid &other = boids[i];

    float d = ofDist(location.x, location.y, other.location.x, other.location.y);
    if ((d > 0) && (d < neighbordist)) {
        steer += (other.direction);
        count++;
    }
}
if (count > 0) {
    steer /= (float)count;
}

// As long as the vector is greater than 0
float mag = sqrt(steer.x*steer.x + steer.y*steer.y);
if (mag > 0) {
    // Implement Reynolds: Steering = Desired - direction
    steer /= mag;
    steer *= maxspeed;
    steer -= direction;
    steer.x = ofClamp(steer.x, -attraction, attraction);
    steer.y = ofClamp(steer.y, -attraction, attraction);
}
return steer;
}

//--COHESION--
// For the average location (i.e. center) of all nearby boids, calculate steering vector towards     that location
ofVec2f Boid::cohesion(vector<Boid> &boids) {
float neighbordist = 50.0;
ofVec2f sum;   // Start with empty vector to accumulate all locations
int count = 0;
for (int i = 0 ; i < boids.size(); i++) {
    Boid &other = boids[i];
    float d = ofDist(location.x, location.y, other.location.x, other.location.y);
    if ((d > 0) && (d < neighbordist)) {
        sum += other.location; // Add location
        count++;
    }
}
if (count > 0) {
    sum /= (float)count;
    return steer(sum, false);  // Steer towards the location
}
return sum;
}

//--------------------------------------------------------------
bool isMouseMoving() {
static ofPoint pmouse;
ofPoint mouse(ofGetMouseX(),ofGetMouseY());
bool mouseIsMoving = (mouse!=pmouse);
pmouse = mouse;
return mouseIsMoving;
}

vector initialize:

std::vector<Boid*> boids;

-

//--------------------------------------------------------------
void testApp::setup() {
ofSetBackgroundAuto(false);
ofBackground(0,0,0);
ofSetFrameRate(60);
ofEnableAlphaBlending();
for(int i=0; i<10; i++) 
{
    boids.push_back(new Team1());
    //boids.push_back(Boid());
}
}

//--------------------------------------------------------------
void testApp::update() {


    for(int i=0; i<boids.size(); i++) {            
        boids[i]->seek(ofPoint(mouseX,mouseY));
    }



    for(int i=0; i<boids.size(); i++) {
        boids[i]->update(boids);
    }

}

//--------------------------------------------------------------
void testApp::draw() {

ofSetColor(0,0,0,20);
ofRect(0,0,ofGetWidth(),ofGetHeight());

for(int i=0; i<boids.size(); i++) 
{
    boids[i]->draw();
}
}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button) {


boids.push_back(new Team1(x,y));
    ////boids.push_back(Boid());
    //boids.push_back(Boid(x,y));
}

2 个答案:

答案 0 :(得分:2)

从错误中,您似乎有std::vector<Boid>。您需要以多态方式保持Boids,因此您的向量应该保持(最好是智能)指针Boid

std::vector<Boid*> boids;

std::vector<std::unique_ptr<Boid>> boids;

然后你可以这样填写:

boids.push_back(new Team1());

boids.push_back(std::unique_ptr<Boid>(new Team1()));

分别

请注意std::unique_ptr需要C ++ 11支持。有关smart pointers here的更多信息。

答案 1 :(得分:1)

如果没有看到更多代码,很难确定,但我想调用boids.push_back(*new Team1());的代码无法看到Team1的定义。您需要#include在每个要使用它的.cpp文件中定义Team1的头文件。

另外,为了能够使用多态(虚函数),必须在矢量中存储指针,而不是实际的对象。因此,您必须将矢量键入std::vector<Boid*>。或者最好使用智能指针,例如std::vector<std::shared_ptr<Boid> >