Hi,
I’m trying to create simple “fireworks” using particles. I’d like the particles to form circular shapes, and spread out, almost like a ripple, then fall to the bottom of the screen.
Right now, it’s creating the circular shapes at the point of the mouse, but the particles are not “falling” as they should… Once the code gets to “particles[i].draw()”, I assumed that it would make every particle “fall” to the ground with varying velocity… I’m really at a loss with what I’m doing wrong, and your help is greatly appreciated.
testApp.cpp:
#include "testApp.h"
//--------------------------------------------------------------
void testApp::setup(){
ofSetVerticalSync(true);
ofSetFrameRate(60);
ofBackground(0, 0, 0);
for (int i = 0; i < 100; i++){
particle myParticle;
//myParticle.setInitialCondition(fireX_orig, fireY_orig, 0, ofRandom(-4,4), ofRandom(-4,4),ofRandom(-4,4));
// more interesting with diversity :)
//myParticle.damping = ofRandom(0.001, 0.05);
particles.push_back(myParticle);
}
}
//--------------------------------------------------------------
void testApp::update(){
angle = .02f;
//for(int i = 0.001; i < 1; i++){
fireX_orig = mouseX;
fireY_orig = mouseY;
fireRadius = ofRandom(50, 300);
for(int i = 0; i < particles.size(); i++){ //this doesn't work with whole numbers, why?
fireX = fireX_orig + (fireRadius * sin(i+angle));
fireY = fireY_orig + (fireRadius * cos(i+angle));
particles[i].setInitialCondition(fireX, fireY, 0, ofRandom(-2, 2), ofRandom(-2, 2), ofRandom(-2,2));
}
//}
// on every frame
// we reset the forces
// add in any forces on the particle
// perfom damping and
// then update
for (int i = 0; i < particles.size(); i++){
particles[i].resetForce();
particles[i].addDampingForce();
particles[i].update();
}
}
//--------------------------------------------------------------
void testApp::draw(){
for (int i = 0; i < particles.size(); i++){
//ofSetColor(R, G, B, ofRandom(0, 255));
particles[i].draw();
}
}
//--------------------------------------------------------------
void testApp::keyPressed (int key){
}
//--------------------------------------------------------------
void testApp::keyReleased (int key){
}
//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){
}
//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::mouseReleased(){
}
testApp.h
#include "ofMain.h"
#include "particle.h"
class testApp : public ofSimpleApp{
public:
void setup();
void update();
void draw();
void keyPressed (int key);
void keyReleased (int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased();
// let's make a vector of them
vector <particle> particles;
float angle;
float R;
float G;
float B;
float fireX_orig;
float fireY_orig;
float fireX;
float fireY;
float fireRadius;
};
#endif
particle.cpp
#include "particle.h"
#include "ofMain.h"
#define OF_ADDON_USING_OFXVECTORMATH
#include "ofAddons.h"
//------------------------------------------------------------
particle::particle(){
setInitialCondition(0,0,0,0);
damping = 0.01f;
gravity = 0.04f;
}
//------------------------------------------------------------
void particle::resetForce(){
// we reset the forces every frame
frc.set(0,0,0);
}
//------------------------------------------------------------
void particle::addForce(float x, float y){
// add in a force in X and Y for this frame.
frc.x = frc.x + x;
frc.y = frc.y + y;
}
//------------------------------------------------------------
void particle::addDampingForce(){
// the usual way to write this is vel *= 0.99
// basically, subtract some part of the velocity
// damping is a force operating in the oposite direction of the
// velocity vector
frc.x = frc.x - vel.x * damping;
frc.y = frc.y - vel.y * damping + gravity;
frc.z = frc.z - vel.z * damping;
}
//------------------------------------------------------------
void particle::setInitialCondition(float px, float py, float vx, float vy){
pos.set(px,py,0);
vel.set(vx,vy,0);
}
//------------------------------------------------------------
void particle::setInitialCondition(float px, float py, float pz, float vx, float vy, float vz){
pos.set(px,py,pz);
vel.set(vx,vy,vz);
}
//------------------------------------------------------------
void particle::update(){
vel = vel + frc;
pos = pos + vel;
}
//------------------------------------------------------------
void particle::draw(){
glPushMatrix();
glTranslatef(pos.x, pos.y,pos.z);
ofEnableAlphaBlending();
R = ofRandom(0, 255);
G = ofRandom(0, 255);
B = ofRandom(0, 255);
ofSetColor(R, G, B);
ofCircle(0,0, 3.0f);
ofDisableAlphaBlending(); //why do you have to do this? It looks the same without it....
glPopMatrix();
}
particle.h
#ifndef PARTICLE_H
#define PARTICLE_H
#include "ofMain.h"
#define OF_ADDON_USING_OFXVECTORMATH
#include "ofAddons.h"
class particle
{
public:
ofxVec3f pos;
ofxVec3f vel;
ofxVec3f frc; // frc is also know as acceleration (newton says "f=ma")
particle();
virtual ~particle(){};
void resetForce();
void addForce(float x, float y);
void addDampingForce();
void setInitialCondition(float px, float py, float vx, float vy);
void setInitialCondition(float px, float py, float pz, float vx, float vy, float vz);
void update();
void draw();
float damping;
float gravity;
float R;
float G;
float B;
protected:
private:
};
#endif // PARTICLE_H
main.cpp
#include "ofMain.h"
#include "testApp.h"
//========================================================================
int main( ){
ofSetupOpenGL(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());
}