OpenFrameworks boid demo
I made a small boids demo in openframeworks. It is more or less a port of the boids demo i made in processing a while ago.
It's bin a while since i wrote c++ the last time, so i'm pretty sure i have forgotten to free some memory or have done something very unc++y :-)
The main class is just the standard openframeworks main from the emptyExample
main.cpp:
#include "ofMain.h"
#include "testApp.h"
#include "ofAppGlutWindow.h"
//========================================================================
int main( ){
ofAppGlutWindow window;
ofSetupOpenGL(&window, 1024,768, OF_WINDOW); // <-------- setup the GL context
// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp( new testApp());
}
in testApp.h i have defined an array of Boids
testApp.h:
#ifndef _TEST_APP
#define _TEST_APP
#include "ofMain.h"
#include "boid.h"
#define BOIDS 100
class testApp : public ofBaseApp{
private:
boid *boids[BOIDS];
public:
void setup();
void update();
void draw();
void keyPressed (int key);
};
#endif
in testApp.cpp i iterate over the array and update, and call the draw function of the individual boids
testApp.cpp:
#include "testApp.h"
//--------------------------------------------------------------
void testApp::setup(){
for( int i=0; i < BOIDS; i++) {
boids[i] = new boid( ofRandom(0,ofGetWidth()), ofRandom(0,ofGetHeight()), ofRandom(-10,10), ofRandom(-10,10), boids, BOIDS );
}
ofSetFrameRate(25);
}
//--------------------------------------------------------------
void testApp::update(){
for( int i=0; i < BOIDS; i++) {
boids[i]->update();
}
}
//--------------------------------------------------------------
void testApp::draw(){
ofBackground(255,255,255);
for( int i=0; i < BOIDS; i++) {
boids[i]->draw();
}
}
//--------------------------------------------------------------
void testApp::keyPressed(int key){
for( int i=0; i < BOIDS; i++) {
boids[i]->boo();
}
}
In boids.h i define a class for the individual boids
boids.h:
#ifndef _BOID
#define _BOID
class boid {
private:
float r1;
float r2;
float r3;
float x,y;
float vx,vy;
boid** others;
int num_others;
public:
boid( float x, float y, float vx, float vy, boid* others[], int num_others );
void boo();
void update();
void draw();
void sep();
void align();
void coh();
};
#endif
and finally boids.cpp, this is where all the calculations happen
boids.cpp:
#include "boid.h"
#include "ofMain.h"
float sq( float a ) {
return a * a;
}
boid::boid( float x, float y, float vx, float vy, boid* others[], int num_others ) {
this->r1 = 40;
this->r2 = 80;
this->r3 = 160;
this->x = x;
this->y = y;
this->vx = vx;
this->vy = vy;
this->others = others;
this->num_others = num_others;
}
void boid::boo() {
vx = ofRandom( -25, 25 );
vy = ofRandom( -25, 25 );
}
void boid::update() {
sep();
align();
coh();
float l = sqrt( sq( vx ) + sq ( vy ));
if (l > 4 ) {
vx = 0.9 * vx;
vy = 0.9 * vy;
}
x += vx;
y += vy;
if (x > ofGetWidth() - 30 ) { vx -= 2; }
if (x < 30 ) { vx += 2; }
if (y > ofGetHeight() -30 ) {vy -= 2; }
if (y < 30) { vy += 2; }
}
void boid::sep() {
int count = 0;
float sx = 0;
float sy = 0;
for ( int i = 0; i < num_others; i ++ ) {
float d = sqrt( sq( x - others[i]->x ) + sq( y - others[i]->y ));
if (d < r1 && this != others[i] ) {
count++;
sx += others[i]->x;
sy += others[i]->y;
}
}
if ( count > 0 ){
sx = x - sx / count;
sy = y - sy / count;
float l = sqrt( sq( sx ) + sq ( sy ));
sx = 1.2 * sx / l;
sy = 1.2 * sy / l;
}
vx += sx;
vy += sy;
}
void boid::align() {
int count = 0;
float dx = 0;
float dy = 0;
for ( int i = 0; i < num_others; i ++ ) {
float d = sqrt( sq( x - others[i]->x ) + sq( y - others[i]->y ));
if (d < r2 && this != others[i] ) {
count++;
dx += others[i]->vx;
dy += others[i]->vy;
}
}
if ( count > 0 ){
dx = dx / count;
dy = dy / count;
float l = sqrt( sq( dx ) + sq ( dy ));
dx = dx / l;
dy = dy / l;
}
vx += dx;
vy += dy;
}
void boid::coh() {
int count = 0;
float sx = 0;
float sy = 0;
for ( int i = 0; i < num_others; i ++ ) {
float d = sqrt( sq( x - others[i]->x ) + sq( y - others[i]->y ));
if (d < r3 && d > r1 && this != others[i] ) {
count++;
sx += others[i]->x;
sy += others[i]->y;
}
}
if ( count > 0 ){
sx = x - sx / count;
sy = y - sy / count;
float l = sqrt( sq( sx ) + sq ( sy ));
sx = sx / l;
sy = sy / l;
}
vx -= sx;
vy -= sy;
}
void boid::draw() {
ofSetLineWidth(2);
glPushMatrix();
glTranslatef( x, y, 0 );
float alpha = atan( vy/vx ) + ( vx < 0 ? PI : 0 );
glRotatef( alpha * 180 / PI , 0,0,1);
ofSetColor(228,228,228);
ofFill();
ofBeginShape();
ofVertex( -15, -5 );
ofVertex( -15, 5 );
ofVertex( 15, 5 );
ofVertex( 15, -5 );
ofEndShape(true);
ofSetColor(128,128,128);
ofNoFill();
ofBeginShape();
ofVertex( -15, -5 );
ofVertex( -15, 5 );
ofVertex( 15, 5 );
ofVertex( 15, -5 );
ofEndShape(true);
glPopMatrix();
}
See also:
Ronin experiment 17 - boids
feeling watched in openframeworks
osc app using openframeworks
rotating box in openframeworks
Hi Nikolaus! Really nice projects! I had a go with your boid code and added some interactive capabilities for a course on openFrameworks. Please have a look! http://www.fromtimetoti.me/emergenes/
Hi Nikolaus!
really cool;
thanks for sharing!