

//----------------------------------------------------------
// constants
//----------------------------------------------------------
var ONE_HALF			= 0.5;
var AREA_SIZE			= 400;
var WALL_THICKNESS		= 20;
var LEFT_WALL			= 30;
var RIGHT_WALL			= LEFT_WALL + AREA_SIZE;
var TOP_WALL			= 30;
var BOTTOM_WALL			= TOP_WALL + AREA_SIZE;
var SYMBOL_SIZE			= 40;
var MID_X				= LEFT_WALL + AREA_SIZE * ONE_HALF;
var MID_Y				= TOP_WALL 	+ AREA_SIZE * ONE_HALF;
var KNOB_WIDTH			= 15;
var KNOB_HEIGHT			= 30;
var KNOB_LEFT_LIMIT		= LEFT_WALL		+ 30;
var KNOB_RIGHT_LIMIT	= RIGHT_WALL	- 30;
var FORCE_NULL_RANGE	= 0.04;

//physics
var FRICTION			= 0.01;
var AIR_JITTER			= 0.7;
var WALL_JITTER			= 1.5;
var MAX_ATTRACTION		= 0.007;
var MAX_REPULSION		= 40.0;
var BOUNCE_APART		= 0.8;
var WALL_BOUNCE			= 0.5;

//-------------------------------------------------
// for things that animate, this is the frame rate
//-------------------------------------------------
var MILLISECONDS_PER_ANIMATION_STEP =  20;

//---------------------------------
// DOM Elements
//---------------------------------
var background		= null;
var mouseBackground	= null;
var male   			= null;
var female			= null;
var controls		= null;
var maleKnob		= null;
var femaleKnob		= null;

//--------------------------------------
// some variables
//--------------------------------------
var windowRight			= 0;
var windowBottom		= 0;
var browserWidth		= 0;
var browserHeight		= 0;
var centerX				= 0;
var timer				= 0;
var draggingMale		= false;
var draggingFemale		= false;
var draggingMaleKnob	= false;
var draggingFemaleKnob	= false;
var mouseX				= 0;
var mouseY				= 0;

var maleX			= MID_X - 100;
var maleY			= MID_Y;
var femaleX			= MID_X + 100;
var femaleY			= MID_Y;

var maleXv			= 0.0;
var maleYv			= 0.0;
var femaleXv		= 0.0;
var femaleYv		= 0.0;

var femaleForce	= 0.05;
var maleForce	= -0.45;

var maleKnobX	= 0;
var maleKnobY	= 0;
var femaleKnobX	= 0;
var femaleKnobY	= 0;

//----------------------------------------------------------------------
function InitializeMicroworld()
{
	var body = document.getElementsByTagName( "body" )[0];

	//-----------------------------------------------------------
	// mouse background
	//-----------------------------------------------------------
	mouseBackground = document.createElement( "div" );
	mouseBackground.style.position 		= "absolute";
	mouseBackground.style.left 			= 0;
	mouseBackground.style.top  			= 0;
	mouseBackground.style.width			= 1000 + 'px';
	mouseBackground.style.height 		= 900 + 'px';	
	mouseBackground.style.background	= 'url( mouse_background.jpg ) no-repeat';
	body.appendChild( mouseBackground );
	
   	mouseBackground.setAttribute( "onmouseup", 	"mouseUp();" );
	$( mouseBackground ).mousemove( function( event ) { setMouseMove( event ); 	} );

	//-----------------------------------------------------------
	// controls
	//-----------------------------------------------------------
	controls = document.createElement( "div" );
	controls.style.position = "absolute";
	controls.style.left 	= LEFT_WALL;
	controls.style.top  	= TOP_WALL + AREA_SIZE + 10;
	controls.style.width 	= AREA_SIZE + 'px';
	controls.style.height 	= 150 + 'px';	
	controls.style.background = 'url( controls.jpg ) no-repeat';
	body.appendChild( controls );
	
   	controls.setAttribute( "onmouseup", 	"mouseUp();" );
	//$( controls ).mouseover	( function( event ) { mouseOverControls();  	} );
	$( controls ).mousemove	( function( event ) { setMouseMove( event ); 	} );
	//$( controls ).mouseout	( function( event ) { mouseOutControls();		} );


	//-----------------------------------------------------------
	// maleKnob
	//-----------------------------------------------------------
	maleKnob = document.createElement( "div" );
	maleKnob.style.position = "absolute";	
	//maleKnobX = KNOB_LEFT_LIMIT;
	maleKnobX = KNOB_LEFT_LIMIT + ( KNOB_RIGHT_LIMIT - KNOB_LEFT_LIMIT ) * ( maleForce + ONE_HALF );

	maleKnob.style.left 	= maleKnobX;
	
	maleKnobY = TOP_WALL + AREA_SIZE + 26;
	maleKnob.style.top  	= maleKnobY;
	maleKnob.style.width 	= KNOB_WIDTH + 'px';
	maleKnob.style.height 	= KNOB_HEIGHT + 'px';	
	maleKnob.style.background = 'url( male_knob.jpg ) no-repeat';
	body.appendChild( maleKnob );
	$( maleKnob ).mousemove	( function( event ) { setMouseMove( event ); 	} );
   	maleKnob.setAttribute( "onmousedown", 	"mouseDownMaleKnob();" );
   	maleKnob.setAttribute( "onmouseup", 	"mouseUpMaleKnob();" );
   	
   	
	//-----------------------------------------------------------
	// femaleKnob
	//-----------------------------------------------------------
	femaleKnob = document.createElement( "div" );
	femaleKnob.style.position = "absolute";
	//femaleKnobX = KNOB_LEFT_LIMIT;
	femaleKnobX = KNOB_LEFT_LIMIT + ( KNOB_RIGHT_LIMIT - KNOB_LEFT_LIMIT ) * ( femaleForce + ONE_HALF );

	femaleKnob.style.left 	= femaleKnobX;
	
	femaleKnobY = TOP_WALL + AREA_SIZE + 65;
	femaleKnob.style.top  	= femaleKnobY;
	femaleKnob.style.width 	= KNOB_WIDTH + 'px';
	femaleKnob.style.height 	= KNOB_HEIGHT + 'px';	
	femaleKnob.style.background = 'url( female_knob.jpg ) no-repeat';
	body.appendChild( femaleKnob );

	$( femaleKnob ).mousemove( function( event ) { setMouseMove( event ); } );
   	femaleKnob.setAttribute	( "onmousedown", 	"mouseDownFemaleKnob();" );
   	maleKnob.setAttribute	( "onmouseup",		"mouseUpFemaleKnob();" );

	//-----------------------------------------------------------
	// male
	//-----------------------------------------------------------
	male = document.createElement( "div" );
	male.style.position = "absolute";
	male.style.left 	= maleX;
	male.style.top  	= maleY;
	male.style.width 	= SYMBOL_SIZE + 'px';
	male.style.height 	= SYMBOL_SIZE + 'px';	
	male.style.background = 'url( male.gif ) no-repeat';
	
	//male.innerHTML 	= "<img src = male.jpg>"
	body.appendChild( male );

   	male.setAttribute( "onmousedown", "mouseDownMale();" );
   	male.setAttribute( "onmouseup", "mouseUp();" );
	$( male ).mousemove	( function( event ) { setMouseMove( event ); 	} );

	//-----------------------------------------------------------
	// female
	//-----------------------------------------------------------
	female = document.createElement( "div" );
	female.style.position = "absolute";
	female.style.left 	= femaleX;
	female.style.top  	= femaleY;
	female.style.width 	= SYMBOL_SIZE + 'px';
	female.style.height 	= SYMBOL_SIZE + 'px';	
	female.style.background = 'url( female.gif ) no-repeat';
	body.appendChild( female );

   	female.setAttribute( "onmousedown", "mouseDownFemale();" );
   	female.setAttribute( "onmouseup",	"mouseUp();" );
	$( female ).mousemove	( function( event ) { setMouseMove( event ); 	} );

	//-----------------------------------------------------------
	// blurb
	//-----------------------------------------------------------
	blurb = document.createElement( "div" );
	blurb.style.position = "absolute";
	blurb.style.left 	= RIGHT_WALL + 20;
	blurb.style.top  	= TOP_WALL;
	blurb.innerHTML
	= "<font size = 4 face='arial' color = #555555 >Attractions and Repulsions<font>"
	+ "<font size = 2 face='arial' color = #555555 >"
	+ "<br>"
	+ "<br>"
	+ "Adjust the forces to cause the two symbols"
	+ "<br>"
	+ "to exhibit different interactive behaviors."
	+ "<br>"
	+ "<br>"
	+ "You can also move the symbols around."
	+ "<br>"
	+ "<br>"
	+ "This animation was created using JavaScript"
	+ "<br>"
	+ "by JJ Ventrella"
	+ "<br>"
	+ "<br>"
	+ "<a href = 'http://www.ventrella.com/' target = 'blank'>www.ventrella.com</a>"
	+ "<font>";
	
	body.appendChild( blurb );
	


	//-----------------------------------------------------------------------------------------------------
	// this is necessary to get things positioned right (this also gets invoked when the user resizes the window)
	//-----------------------------------------------------------------------------------------------------
	arrangeElementsAccordingToBrowserWidthAndHeight();

	//------------------------------------------------------------
	// start up the timer...
	//------------------------------------------------------------
	clearTimeout ( timer );
	timer = setTimeout( "updateAnimation()", MILLISECONDS_PER_ANIMATION_STEP );

}//----------------------------------------------------------------------




//-------------------------------------------------------------------------------------------
function setMouseMove( event )
{
	//----------------------------------------------------
	// save off these values
	//----------------------------------------------------
	mouseX = event.clientX;
	mouseY = event.clientY;

}//----------------------------------------------------------------------

//----------------------------------------------------------------------
function mouseDownMale()
{
	draggingMale = true;

}//----------------------------------------------------------------------

//----------------------------------------------------------------------
function mouseDownFemale()
{
	draggingFemale = true;

}//----------------------------------------------------------------------


//----------------------------------------------------------------------
function mouseDownMaleKnob()
{
	draggingMaleKnob = true;

}//----------------------------------------------------------------------

//----------------------------------------------------------------------
function mouseUpMaleKnob()
{
	draggingMaleKnob = false;

}//----------------------------------------------------------------------


//----------------------------------------------------------------------
function mouseUp()
{
	draggingMaleKnob	= false;
	draggingFemaleKnob	= false;
	draggingMale		= false;
	draggingFemale		= false;

}//----------------------------------------------------------------------

//----------------------------------------------------------------------
function jitterMale( j )
{
	maleXv	+= ( -j * ONE_HALF + j * Math.random() ) * Math.abs( maleForce );
	maleYv	+= ( -j * ONE_HALF + j * Math.random() ) * Math.abs( maleForce );

}//----------------------------------------------------------------------

//----------------------------------------------------------------------
function jitterFemale( j )
{
	femaleXv	+= ( -j * ONE_HALF + j * Math.random() ) * Math.abs( maleForce );
	femaleYv	+= ( -j * ONE_HALF + j * Math.random() ) * Math.abs( maleForce );

}//----------------------------------------------------------------------



//----------------------------------------------------------------------
function mouseDownFemaleKnob()
{
	draggingFemaleKnob = true;

}//----------------------------------------------------------------------

//----------------------------------------------------------------------
function mouseUpFemaleKnob()
{
	draggingFemaleKnob = false;

}//----------------------------------------------------------------------

//----------------------------------------------------------------------
function updateAnimation()
{
	//------------------------------------------------------------
	// reset the timer so it keeps on tickin'
	//------------------------------------------------------------
	timer = setTimeout( "updateAnimation()", MILLISECONDS_PER_ANIMATION_STEP );
	

	//-------------------------------------------------------------------------
	// update controls
	//-------------------------------------------------------------------------
	if ( draggingMaleKnob )
	{
		maleKnobX = mouseX - KNOB_WIDTH  / 2;
		
				if ( maleKnobX < KNOB_LEFT_LIMIT	) { maleKnobX = KNOB_LEFT_LIMIT;	}
		else 	if ( maleKnobX > KNOB_RIGHT_LIMIT	) { maleKnobX = KNOB_RIGHT_LIMIT;	}
		
		var v = ( maleKnobX - KNOB_LEFT_LIMIT ) / ( KNOB_RIGHT_LIMIT - KNOB_LEFT_LIMIT );
		
		maleForce = v - ONE_HALF;
		
		maleKnob.style.top  = maleKnobY;
		maleKnob.style.left = maleKnobX - KNOB_WIDTH  / 2;
	}
	

	if ( draggingFemaleKnob )
	{
		femaleKnobX = mouseX - KNOB_WIDTH  / 2;
		
				if ( femaleKnobX < KNOB_LEFT_LIMIT	) { femaleKnobX = KNOB_LEFT_LIMIT;	}
		else 	if ( femaleKnobX > KNOB_RIGHT_LIMIT	) { femaleKnobX = KNOB_RIGHT_LIMIT;	}
		
		var v = ( femaleKnobX - KNOB_LEFT_LIMIT ) / ( KNOB_RIGHT_LIMIT - KNOB_LEFT_LIMIT );
		
		femaleForce = v - ONE_HALF;
		
		femaleKnob.style.top  = femaleKnobY;
		femaleKnob.style.left = femaleKnobX - KNOB_WIDTH  / 2;
	}

	//------------------------------------------------------------
	// apply forces
	//------------------------------------------------------------
	var xx = femaleX - maleX;
	var yy = femaleY - maleY;
	var distance = Math.sqrt( xx*xx + yy*yy );
	
	if ( distance > 0.0 )
	{
		if ( maleForce > FORCE_NULL_RANGE )
		{
			maleXv += xx * maleForce * MAX_ATTRACTION;
			maleYv += yy * maleForce * MAX_ATTRACTION;
		}
		else if ( maleForce < -FORCE_NULL_RANGE )
		{
			var force = ( -maleForce * 2 * MAX_REPULSION ) / ( distance * distance );
			maleXv -= xx * force;
			maleYv -= yy * force;
		}
		
		if ( femaleForce > FORCE_NULL_RANGE )
		{
			femaleXv -= xx * femaleForce * MAX_ATTRACTION;
			femaleYv -= yy * femaleForce * MAX_ATTRACTION;
		}
		else if ( femaleForce < -FORCE_NULL_RANGE )
		{
			var force = ( -femaleForce * 2 * MAX_REPULSION ) / ( distance * distance );
			femaleXv += xx * force;
			femaleYv += yy * force;
		}
	}
			
	//------------------------------------------------------------
	// the jitters
	//------------------------------------------------------------
	jitterMale	( AIR_JITTER );
	jitterFemale( AIR_JITTER );
	
/*
maleXv 		+= ( -JITTER * ONE_HALF + JITTER * Math.random() ) * Math.abs( maleForce );
	maleYv		+= ( -JITTER * ONE_HALF + JITTER * Math.random() ) * Math.abs( maleForce );
	femaleXv	+= ( -JITTER * ONE_HALF + JITTER * Math.random() ) * Math.abs( femaleForce );
	femaleYv	+= ( -JITTER * ONE_HALF + JITTER * Math.random() ) * Math.abs( femaleForce );
*/

	//------------------------------------------------------------
	// friction
	//------------------------------------------------------------
	maleXv		*= ( 1.0 - FRICTION );
	maleYv		*= ( 1.0 - FRICTION );
	femaleXv	*= ( 1.0 - FRICTION );
	femaleYv	*= ( 1.0 - FRICTION );
	
	//------------------------------------------------------------
	// update position by velocity
	//------------------------------------------------------------
	maleX 	+= maleXv;
	maleY 	+= maleYv;
	femaleX	+= femaleXv;
	femaleY += femaleYv;
	
	//-------------------------------------------------------------------------
	// symbol-to-symbol collisions
	//-------------------------------------------------------------------------
	if (( distance < SYMBOL_SIZE )
	&&  ( distance > 0.0 ))
	{
		var force = ( 1.0 - ( distance / SYMBOL_SIZE ) ) * BOUNCE_APART;
		
		maleXv		-= force * ( xx / distance );
		maleYv		-= force * ( yy / distance );
		femaleXv	+= force * ( xx / distance );
		femaleYv	+= force * ( yy / distance );
	}
	
	
	
	// this is the orthogonal version...it keeps the images from overlapping in the corners
	/*
	if (( Math.abs(xx) < SYMBOL_SIZE )
	&&  ( Math.abs(yy) < SYMBOL_SIZE ))
	{
		var ax = Math.abs(xx);
		var ay = Math.abs(yy);
		if ( ax > ay )
		{
			var sx = SYMBOL_SIZE - ax;
			if ( xx > 0 )
			{
				//maleX 	-= sx;
				//femaleX += sx;
				maleXv 	-= sx * BOUNCE;
				femaleXv += sx * BOUNCE;
			}
			else 
			{
				//maleX 	+= sx;
				//femaleX -= sx;
				maleXv 	+= sx * BOUNCE;
				femaleXv -= sx * BOUNCE;
			}			
		}
		else
		{
			var sy = SYMBOL_SIZE - ay;
			if ( yy > 0 )
			{
				//maleY 	-= sy;
				//femaleY += sy;
				maleYv 	-= sy * BOUNCE;
				femaleYv += sy * BOUNCE;
			}
			else 
			{
				//maleY 	+= sy;
				//femaleY -= sy;
				maleYv 	+= sy * BOUNCE;
				femaleYv -= sy * BOUNCE;
			}
		}
	}
	*/
	
	
	if ( draggingMale )
	{
		maleX	= mouseX - SYMBOL_SIZE  / 2;
		maleY	= mouseY - SYMBOL_SIZE  / 2;
		maleXv	= 0.0;
		maleYv	= 0.0;
	}
	else if ( draggingFemale )
	{
		femaleX		= mouseX - SYMBOL_SIZE  / 2;
		femaleY		= mouseY - SYMBOL_SIZE  / 2;
		femaleXv	= 0.0;
		femaleYv	= 0.0;
	}
	


	
	//-------------------------------------------------------------------------
	// boundary collisions
	//-------------------------------------------------------------------------
	if ( maleX < LEFT_WALL 					) { maleX = LEFT_WALL; 					maleXv	= -maleXv * WALL_BOUNCE; jitterMale( WALL_JITTER );	}	
	if ( maleX > RIGHT_WALL	- SYMBOL_SIZE	) { maleX = RIGHT_WALL - SYMBOL_SIZE; 	maleXv	= -maleXv * WALL_BOUNCE; jitterMale( WALL_JITTER );	}
	if ( maleY < TOP_WALL					) { maleY = TOP_WALL; 					maleYv	= -maleYv * WALL_BOUNCE; jitterMale( WALL_JITTER );	}
	if ( maleY > BOTTOM_WALL - SYMBOL_SIZE	) { maleY = BOTTOM_WALL	- SYMBOL_SIZE;	maleYv	= -maleYv * WALL_BOUNCE; jitterMale( WALL_JITTER );	}

	if ( femaleX < LEFT_WALL				) { femaleX = LEFT_WALL; 				femaleXv = -femaleXv * WALL_BOUNCE; jitterFemale( WALL_JITTER );	}
	if ( femaleX > RIGHT_WALL - SYMBOL_SIZE	) { femaleX = RIGHT_WALL - SYMBOL_SIZE;	femaleXv = -femaleXv * WALL_BOUNCE; jitterFemale( WALL_JITTER );	}
	if ( femaleY < TOP_WALL					) { femaleY = TOP_WALL; 				femaleYv = -femaleYv * WALL_BOUNCE; jitterFemale( WALL_JITTER );	}
	if ( femaleY > BOTTOM_WALL - SYMBOL_SIZE) { femaleY = BOTTOM_WALL - SYMBOL_SIZE;femaleYv = -femaleYv * WALL_BOUNCE; jitterFemale( WALL_JITTER );	}
	
	//-------------------------------------------------------------------------
	// apply positions to div elements
	//-------------------------------------------------------------------------
	male.style.left 	= maleX;
	male.style.top		= maleY;
	female.style.left	= femaleX;
	female.style.top	= femaleY;

}//----------------------------------------------------------------------


//----------------------------------------------------------------------
function ResizeMicroworld()
{
	arrangeElementsAccordingToBrowserWidthAndHeight();

}//----------------------------------------------------------------------



//----------------------------------------------------------------------
function arrangeElementsAccordingToBrowserWidthAndHeight()
{
	browserWidth	= document.body.clientWidth;
	browserHeight	= document.body.clientHeight;

}//----------------------------------------------------------------------





