В данный момент я работаю над заданием, для которого мне нужно создать систему флокирования с разными подклассами, которые ведут себя по-разному. Я работаю с 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));
}
От ошибки кажется, что у вас есть 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. Еще умные указатели здесь.
Трудно быть уверенным, не видя больше кода, но я предполагаю, что код, вызывающий boids.push_back(*new Team1());
не может видеть определение Team1
, Вам нужно #include
заголовочный файл, определяющий Team1
в каждом файле .cpp, где вы хотите его использовать.
Кроме того, чтобы иметь возможность использовать полиморфизм (виртуальные функции), вы должны хранить указатели в вашем векторе, а не фактические объекты. Таким образом, вы должны ввести свой вектор как std::vector<Boid*>
, Или желательно использовать умный указатель, такой как std::vector<std::shared_ptr<Boid> >
,