Использовать наследование с флокированием на основе stdvector

В данный момент я работаю над заданием, для которого мне нужно создать систему флокирования с разными подклассами, которые ведут себя по-разному. Я работаю с 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 ()); в настройках и и музедраг. Это дает следующие ошибки:

  • ожидаемый тип-спецификатор перед Team1
  • ожидаемый ) до Team1
  • нет соответствующей функции для вызова std::vector<Boid, std::allocator<Boid> >::push_back(int&)

ВЕСЬ КОД: (весь код находится в одном файле testapp.cpp, чтобы исключить проблемы со связыванием)

//number of boids
const int BoidAmount = 25;

Суперкласс 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;
}

вектор инициализировать:

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

Решение

От ошибки кажется, что у вас есть 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()));

соответственно.

Обратите внимание, что станд :: unique_ptr требует поддержки C ++ 11. Еще умные указатели здесь.

2

Другие решения

Трудно быть уверенным, не видя больше кода, но я предполагаю, что код, вызывающий boids.push_back(*new Team1()); не может видеть определение Team1, Вам нужно #include заголовочный файл, определяющий Team1 в каждом файле .cpp, где вы хотите его использовать.

Кроме того, чтобы иметь возможность использовать полиморфизм (виртуальные функции), вы должны хранить указатели в вашем векторе, а не фактические объекты. Таким образом, вы должны ввести свой вектор как std::vector<Boid*>, Или желательно использовать умный указатель, такой как std::vector<std::shared_ptr<Boid> >,

1

По вопросам рекламы [email protected]