/* General Structure notes. My classes tend to have a similar naming scheme and flow. I start with the 'exist' method. Exist is what an object needs to do every frame. Usually 'existing' consists of four main things. 1) Find the velocity. This involves determining what influences there are on the velocity. 2) Apply the velocity to the location. 3) Render the object. 4) Age the object. I also use the metaphor of aging and death. When first made, a particle's age will be zero. Every frame, the age will increment. If the age reaches the lifeSpan (which is a random number that I set in the constructor), then the boolean ISDEAD is set to true and the arraylist iterator removes the dead element from the list. */ class Particle{ int len; // number of elements in position array Vec3D[] loc; // array of position vectors Vec3D startLoc; // just used to make sure every loc[] is initialized to the same position Vec3D vel; // velocity vector Vec3D perlin; // perlin noise vector float radius; // particle's size float age; // current age of particle int lifeSpan; // max allowed age of particle float agePer; // range from 1.0 (birth) to 0.0 (death) float bounceAge; // amount to age particle when it bounces off floor boolean ISDEAD; // if age == lifeSpan, make particle die boolean ISBOUNCING; // if particle hits the floor... Particle( Vec3D _loc, Vec3D _vel ){ radius = random(50,400); len = (int)(radius); loc = new Vec3D[ len ]; // This confusing-looking line does three things at once. // First, you make a random vector. // new Vec3D().randomVector() // Next, you multiply that vector by a random number from 0.0 to 5.0. // scaleSelf( 5.0 ); // Finally, you add this new vector to the original sent vector. // _loc.add( ); // This is just a way to make sure all the particles made this frame // don't all start on the exact same pixel. This staggering will be useful // when we incorporate magnetic repulsion in a later tutorial. startLoc = new Vec3D( _loc.add( new Vec3D().randomVector().scaleSelf( random( 5.0 ) ) ) ); for( int i=0; i floorLevel ){ ISBOUNCING = true; } else { ISBOUNCING = false; }} if( ISBOUNCING ){ vel.scaleSelf( .75 ); vel.y *= -.5; }} void setPosition(){ // Every frame, the current location will be passed on to // the next element in the location array. Think 'cursor trail effect'. for( int i=len-1; i>0; i-- ){ loc[i].set( loc[i-1] ); } // Set the initial location. // loc[0] represents the current position of the particle. loc[0].addSelf( vel ); } void render(){ // As the particle ages, it will gain blue but will lose red and green. color c = color( agePer, agePer*50, 1.0 - agePer); renderImage( loc[0], radius * agePer, c, 1.0 ); } void renderTrails(){ float xp, yp, zp; float xOff, yOff, zOff; gl.glBegin( GL.GL_QUAD_STRIP ); for ( int i=0; i lifeSpan ){ ISDEAD = true; } else { // When spawned, the agePer is 1.0. // When death occurs, the agePer is 0.0. agePer = 1.0 - age/(float)lifeSpan; } } }