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)); }