目前我正在进行一项任务,我必须制作一个具有不同子类的植绒系统。我正在使用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));
}
答案 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> >
。