Use stdvector based stack inheritance

I am currently working on a task for which I must create a flocking system with different subclasses that behave differently. I work with OpenFrameworks and C ++. I am new to Open Frameworks and C ++.

As a basis, I use this code: https://sites.google.com/site/ofauckland/examples/ofxflocking-example

However, the fact is that the structure of this code is different from what I'm used to; creating new class objects using "new ..."

My question is: how can I use two stacking classes? For starters, first with just a different color, for example.

One of the subclasses I've added so far:

class Team1 : public Boid { public: Team1(): Boid() {}; Team1(int x, int y): Boid(x,y) {}; void draw() { } }; 

I used the draw virtual thread to draw in the void of the Boid superclass and used boids.push_back (* new Team1 ()); in the settings and and mousedrag. This gives the following errors:

  • expected specifier type before Team1
  • Expected ) to Team1
  • there is no corresponding function to call std::vector<Boid, std::allocator<Boid> >::push_back(int&)

WHOLE CODE: (all code is in a single testapp.cpp file to avoid binding problems)

 //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:

  //---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 } 

subclasses:

 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 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 (ie 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)); } 
+4
source share
2 answers

From the error, it seems that you have std::vector<Boid> . You must draw the Boids polymorphically, so your vector must hold (preferably smart) pointers to Boid :

 std::vector<Boid*> boids; 

or

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

which you can then fill out as follows:

 boids.push_back(new Team1()); 

or

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

respectively.

Note that std :: unique_ptr requires C ++ 11 support. More about smart pointers here .

+2
source

It's hard to be sure without seeing more code, but I think the code calling boids.push_back(*new Team1()); cannot see the definition of Team1 . You need the #include header file that defines Team1 in each .cpp file where you want to use it.

In addition, in order to be able to use polymorphism (virtual functions), you must store pointers in your vector, not in real objects. Therefore, you must enter your vector as std::vector<Boid*> . Or it is advisable to use a smart pointer, for example std::vector<std::shared_ptr<Boid> > .

+1
source

Source: https://habr.com/ru/post/1444379/


All Articles