Creating a trail of moving object in Processing Hints Solutions

From dftwiki3
Jump to: navigation, search

--D. Thiebaut 17:28, 25 June 2012 (EDT)


This page presents solutions and hints for the tutorial page on creating trails of moving objects in Processing]]


Exercise 1

Here's a possible way to do this, illustrated by the code below. The trickiest part of the code might be this line:


               // amount of red in color, varies between 0 and 255 and changes every frame.
               red = 128 + (int) ( sin( frameCount * 0.05f ) * 127 );

The red integer is set to a value that oscillates between 1 and 255, as the variable frameCount keeps on going up in value. The 0.05f value is a float that makes the changing of red smoother. If we were to use sin( frameCount ) directly, the variation would be too brusk. The Excel table below shows how 127 * sin( frameCount ) compares to 127 * sin( frameCount * 0.05 ): notice how the variation of the second quantity varies in a smoother way.


ExcelTableSinFrameCount.png



package tutorial2;
 
import processing.core.*;
 
public class Exercise1 extends PApplet {
	int red = 0; // amount of red in the circle's color
	
	public void setup() {
		// define the window size, make graphics softer, and make
		// the background white
		size(600, 600);
		smooth();
		background( 0xeeeeff );
	}
 
	public void draw() {
                // compute radius of circle, growing and shrinking between 20 and 80 pixels
		float radius = 50 + 30 * sin( frameCount * 0.05f );

                // amount of red in color, varies between 0 and 255 and changes every frame.
		red = 128 + (int) ( sin( frameCount * 0.05f ) * 127 );

		// change color of circle paint depending on mouse button
		if (mousePressed)  {
			stroke( red, 255-red, 0 );
			fill(0);
		}
		else { 
			stroke( 0 );
			fill( red, 255-red, 0 );
		}
 
                // draw a circle where the mouse is located
		ellipse(mouseX, mouseY, radius, radius );
	}
}


Exercise 8

This exercise is challenging. My approach is to create a class for the collection of 10 circles, and call it a TrailClass. The TrailClass contains the direction the trail moves in with two ints dirX and dirY. The CircleClass is simplified in the process.

Here's the code below. It maintains only 1 trail. It's easier to figure out what is going on with just one trail. Creating an applet with more than 1 trail is presented in the second listing.


package tutorial2;
 
import java.util.ArrayList;  // needed to 
import java.util.Iterator;
 
import processing.core.*;
 
/**
 *  CircleClass: a simple container to hold the location of 
 *  the center of the circle, and the frameCount when it 
 *  appears on the applet, as the frameCount is used to
 *  define the rate at which the circles "breathes".
 */
class CircleClass {

	public int 	x;
	public int 	y;
	public int  frameCount;
	int 		dirX;
	int 		dirY;
	
	CircleClass( PApplet p, int xx, int yy, int fc ) {
		
		x = xx;
		y = yy;
		frameCount = fc;
	}

	public void draw( PApplet p ) {
		float radius1 = 50 + 30 * p.sin( frameCount * 0.05f );
		float radius2 = 50 + 30 * p.sin( frameCount * 0.05f );
		p.ellipse( x, y, radius1, radius2 );		
	}
}
 
/**
 * TrailClass: this class is a collection of moving circles. In this example,
 * the trail maintains 10 circles or whatever the number in noCircles is.
 * The circles do not move.  Instead new circles are constantly added at dirX, dirY
 * away from the last circle drawn, and the oldest circle is removed, so that noCircles
 * remain on the applet.
 *
 */
class TrailClass {
	ArrayList circles;	// the collection of circles
	int dirX;			// direction of the trail in the X axis
	int dirY;			// direction of the trail in the Y axis
	final int noCircles = 10;
						// the number of circles in the trail
	
	TrailClass( PApplet p, int x, int y ) {
		// pick a random direction for the trail...
		dirX = (int) (5 - p.random( 10 ));
		dirY = (int) (3 - p.random( 6 ));
		
		// create a list of circles
		circles = new ArrayList();
		
		// add the first circle at (x,y)
		circles.add( new CircleClass( p, x, y, p.frameCount ) );
	}
	
	public void draw( PApplet p ) {
		// get the last circle we added to the tail
		CircleClass last = (CircleClass) circles.get( circles.size() - 1 );
		
		// get its center coordinates
		int x = last.x;
		int y = last.y;
		
		// find the center of the new circles
		x += dirX;
		y += dirY;
		
		// if that is outside the applet, change the direciton
		if ( x < 0 || x > p.width ) dirX = -dirX;
		if ( y < 0 || y > p.height) dirY = -dirY;
		
		// add a new circle at the new location
		circles.add( new CircleClass( p, x, y, p.frameCount ) );
		
		// if we have more than 10 circles remove oldest one
		if ( circles.size() > noCircles )
			circles.remove( 0 );

		// draw all the circles (we assumed they'll have been erased by the main draw() function
		for ( Iterator<CircleClass> it = circles.iterator(); it.hasNext(); ) {
			CircleClass c = it.next();
			c.draw( p );
		}
	}
}

/**
 * Exercise8: the main Processing applet.
 *
 */
public class Exercise8 extends PApplet {
	TrailClass trail;
 
	/**
	 * setup().  Sets the applet up.
	 */
	public void setup(){
	  size(800,600);           // Size of Background/panel
	  background( 0xeeeeff );   //Color of Background, Black
	  frameRate(30);    //Frame rate set at 30
 
	  // create a trail that starts in the center of the applet...
	  trail = new TrailClass( this, width/2, height/2 );
	}
 
 
	/**
	 * draw(): called to draw every frame.
	 * draws a circle where ever the mouse is.  
	 */
	public void draw() {        
	  // erase the applet
	  background( 0xeeeeff );
 
 
	  // display the trail 
	  //stroke( 0 );   // black outline
	  fill( 255 );   // white interior
	  trail.draw( this );
	}
}


Many Trails


package tutorial2;
 
import java.util.ArrayList;  // needed to 
import java.util.Iterator;
 
import processing.core.*;
 
/**
 *  CircleClass: a simple container to hold the location of 
 *  the center of the circle, and the frameCount when it 
 *  appears on the applet, as the frameCount is used to
 *  define the rate at which the circles "breathes".
 */
class CircleClass {

	public int 	x;
	public int 	y;
	public int  frameCount;
	int 		dirX;
	int 		dirY;
	
	CircleClass( PApplet p, int xx, int yy, int fc ) {
		
		x = xx;
		y = yy;
		frameCount = fc;
	}

	public void draw( PApplet p ) {
		float radius1 = 50 + 30 * p.sin( frameCount * 0.05f );
		float radius2 = 50 + 30 * p.sin( frameCount * 0.05f );
		p.ellipse( x, y, radius1, radius2 );		
	}
}
 
/**
 * TrailClass: this class is a collection of moving circles. In this example,
 * the trail maintains 10 circles or whatever the number in noCircles is.
 * The circles do not move.  Instead new circles are constantly added at dirX, dirY
 * away from the last circle drawn, and the oldest circle is removed, so that noCircles
 * remain on the applet.
 *
 */
class TrailClass {
	ArrayList circles;	// the collection of circles
	int dirX;			// direction of the trail in the X axis
	int dirY;			// direction of the trail in the Y axis
	final int noCircles = 10;
						// the number of circles in the trail
	
	TrailClass( PApplet p, int x, int y ) {
		// pick a random direction for the trail...
		dirX = (int) (5 - p.random( 10 ));
		dirY = (int) (5 - p.random( 10 ));
		
		// create a list of circles
		circles = new ArrayList();
		
		// add the first circle at (x,y)
		circles.add( new CircleClass( p, x, y, p.frameCount ) );
	}
	
	public void draw( PApplet p ) {
		// get the last circle we added to the tail
		CircleClass last = (CircleClass) circles.get( circles.size() - 1 );
		
		// get its center coordinates
		int x = last.x;
		int y = last.y;
		
		// find the center of the new circles
		x += dirX;
		y += dirY;
		
		// if that is outside the applet, change the direciton
		if ( x < 0 || x > p.width ) dirX = -dirX;
		if ( y < 0 || y > p.height) dirY = -dirY;
		
		// add a new circle at the new location
		circles.add( new CircleClass( p, x, y, p.frameCount ) );
		
		// if we have more than 10 circles remove oldest one
		if ( circles.size() > noCircles )
			circles.remove( 0 );

		// draw all the circles (we assumed they'll have been erased by the main draw() function
		for ( Iterator<CircleClass> it = circles.iterator(); it.hasNext(); ) {
			CircleClass c = it.next();
			c.draw( p );
		}
	}
}

/**
 * Exercise8: the main Processing applet.
 *
 */
public class Exercise8 extends PApplet {
	ArrayList<TrailClass> trails;
 
	/**
	 * setup().  Sets the applet up.
	 */
	public void setup(){
	  size(800,600);           // Size of Background/panel
	  background( 0xeeeeff );   //Color of Background, Black
	  frameRate(30);    //Frame rate set at 30
 
	  // create a trail that starts in the center of the applet...
	  trails = new ArrayList<TrailClass>();
	  for ( int i = 0; i < 20; i+= 1 ) 
		 trails.add( new TrailClass( this, width/2, height/2 ) );
	  
	}
 
 
	/**
	 * draw(): called to draw every frame.
	 * draws a circle where ever the mouse is.  
	 */
	public void draw() {        
	  // erase the applet
	  background( 0xeeeeff );
 
 
	  // display the trail 
	  //stroke( 0 );   // black outline
	  fill( 255 );   // white interior
	  
	  // draw each trail
	  for ( Iterator<TrailClass> it = trails.iterator(); it.hasNext(); ) 
		  it.next().draw( this );
	}
}