// splash.js// home page animation for sparkplug.ca// Javascript by Gordon Hicks, Gherkin Works <hicks@gherkin.com>, (C) copyright 2005, all rights reserved	// Global vars			// persona dramatis		var spritePlugA ;		var spritePlugB ;		var spriteSparks ;		var spriteExplosion ;		var spriteBigEyes ;		var buttonBoost ;		var staticNav ;		var staticLogo ;		var staticFooter ;				// animation:		var frameRate = 20; // target rate to update screen - time slice		var frameCount = 0;		var animationRunning = false; 		var gameCounter = 0;		// plug pixel position - measured from top of screen		var pxPositionDatum = 257; // px - datum position - when position = 0		var pxPosition = pxPositionDatum; // px - current position		// kinematic variables:		var positionZero = 0;       // px - above datum at beginning of time slice		var position = 0;			// px - above datum at end of time slice		var velocityZero = 0;		var positionMax = 0;		// px - maximum height		var velocity = 0;			// px/s		var acceleration = 0;		// px/s^2 - remains constant		var floorPosition = 0;		// initial position of the 'floor'		var floorElasticity = 0;	// floorElasticity of bounce - 1 = no speed loss		var boostSpeed = 0;			// px/s  boost adds this speed		var time = 0;				// elapsed time in seconds of the animation */		var timeDelta = 0;			// elapsed time in seconds from the last position calc */		// dates, timers, flags		var curDate = new Date();		var prevDate = curDate;		var navTimer = 0; // seconds - used to run nav reveal sequence		var jumpUpTimer = 0; // seconds - used to control floor level adjustment timing		var shutdownTimer = 0; // seconds - used to run shutdown sequence		var flag = new Array();		// IE kludge to prevent screen flicker:		var IEKludgeNeeded = 0;		IEKludgeNeeded = IEWinVersion();		if (IEKludgeNeeded > 6) { IEKludgeNeeded = 0 } ; // exempt version 7 and up	function init() {		// once the page elements are read the cast can be arranged					// persona dramatis - get a handle for each member of the cast:		if (document.layers){			spritePlugA = document.layers.plugA ;			spritePlugB = document.layers.plugB ;			spriteSparks = document.layers.sparks ;			spriteExplosion = document.layers.explosion ;			spriteBigEyes = document.layers.bigEyes ;			buttonBoost = document.layers.boost ;			staticNav = document.layers.gNav ;			staticLogo = document.layers.logo ;			staticFooter = document.layers.footer ;		}		else if (document.all) {			spritePlugA = document.all.plugA.style ;			spritePlugB = document.all.plugB.style ;			spriteSparks = document.all.sparks.style ;			spriteExplosion = document.all.explosion.style ;			spriteBigEyes = document.all.bigEyes.style ;			buttonBoost = document.all.boost.style ;			staticNav = document.all.gNav.style ;			staticLogo = document.all.logo.style ;			staticFooter = document.all.footer.style ;		}		else if (document.getElementById) {			spritePlugA = document.getElementById('plugA').style ;			spritePlugB = document.getElementById('plugB').style ;			spriteSparks = document.getElementById('sparks').style ;			spriteExplosion = document.getElementById('explosion').style ;			spriteBigEyes = document.getElementById('bigEyes').style ;			buttonBoost = document.getElementById('boost').style ;			staticNav = document.getElementById('gNav').style ;			staticLogo = document.getElementById('logo').style ;			staticFooter = document.getElementById('footer').style ;		}		// initial screen appearance:		staticNav.visibility = 'hidden' ;		staticLogo.visibility = 'hidden' ;		staticFooter.visibility = 'hidden' ;				spritePlugA.visibility = 'hidden' ;		spritePlugB.visibility = 'hidden' ;		spriteSparks.visibility = 'hidden' ;		spriteExplosion.visibility = 'hidden' ;		spriteBigEyes.visibility = 'hidden' ;				spritePlugA.top = '-900px' ; // off the screen, to the top		spritePlugB.top = '-900px' ;	}	function runAnimation() {		gameCounter++ ;				if (gameCounter == 1 ) {			// first time through (on load)			setTimeout("animation()",300); // ms delay before animation begins		} else {			// re-animate!					// re-initialize			time = 0;				// elapsed time in seconds of the animation */			timeDelta = 0;			// elapsed time in seconds from the last position calc */			curDate = new Date();			prevDate = curDate;			navTimer = 0; // seconds - used to run nav reveal sequence			jumpUpTimer = 0; // seconds - used to control floor level adjustment timing			shutdownTimer = 0; // seconds - used to run shutdown sequence			flag = new Array();			animation();		}	}	function boost() {		if ( animationRunning ) {			// boost the speed			if (velocityZero >= 0 ) {				velocityZero = velocityZero + boostSpeed;			} else {				velocityZero = velocityZero - boostSpeed;			} 		} else {			// let's play some more...			runAnimation() ;		}	}	function animation() {		animationRunning = true;		/*** Time Calcs ***/		// get time and timeDelta		prevDate = curDate;		curDate = new Date();		timeDelta = (curDate - prevDate)/1000;				// if timeDelta is too large, then set it to something realistic.		// this occurs if the animation is interrupted (to resize screen, for example)		if (timeDelta > 3/frameRate) timeDelta = 1/frameRate;		time = time + timeDelta;		var curSpeed = Math.abs(velocityZero);		// nav timer		if (( positionZero < 100 && curSpeed < 120 )  ||  flag['logo visible'] ) {			// increment			navTimer = navTimer + timeDelta ;		} else {			// reset 			navTimer = 0 ;		}			// jump up timer		if (( flag['nav visible']  && curSpeed < 100 )  ||  flag['jump up'] ) {			// increment			jumpUpTimer = jumpUpTimer + timeDelta ;		} else {			// reset 			jumpUpTimer = 0 ;		}			// shutdown timer		if (( flag['floor moved'] && curSpeed < 100 )  || flag['sparks off'] ) {			// increment			shutdownTimer = shutdownTimer + timeDelta ;		} else {			// reset 			shutdownTimer = 0 ;		}			/*** Events ***/		if ( !flag['go'] ) {					// make visible:			spriteSparks.visibility = 'visible' ;			buttonBoost.visibility = 'visible' ;			spritePlugA.visibility = 'visible' ;			if (IEKludgeNeeded) spritePlugB.visibility = 'visible' ;						flag['go'] = true;		}			if ( !flag['initialized'] && gameCounter == 1 ) {						// initial kinematics: 			positionZero = 450;			positionMax = 0;			velocityZero = -620;			acceleration = -900;			floorPosition = -55; // plug fits into head			floorElasticity = 0.55;			boostSpeed = 400;						flag['initialized'] = true;		}			if ( !flag['initialized'] && gameCounter > 1 ) {						// 'play again' kinematics: 			velocityZero = 400;			positionMax = 0;			floorPosition = -55; // plug fits into head						flag['initialized'] = true;		}			if ( !flag['logo visible'] && navTimer > 0.25 ) {			staticLogo.visibility = 'visible' ;			flag['logo visible'] = true;		}			if ( !flag['nav visible'] && navTimer > 0.75 ) {			staticNav.visibility = 'visible' ;			flag['nav visible'] = true;		}			if ( !flag['jump up'] && jumpUpTimer > 0.5 ) {			prevVelocity = 300;			flag['jump up'] = true;		}			if ( !flag['floor moved'] && jumpUpTimer > 0.6 ) {			floorPosition = 0;			spriteExplosion.visibility = 'visible' ;			flag['floor moved'] = true;		}			if ( !flag['big eyes'] && gameCounter > 1 && positionMax > 450 && jumpUpTimer > 0.8 ) {			spriteBigEyes.visibility = 'visible' ;			flag['big eyes'] = true;		}			if ( !flag['explosion done'] && jumpUpTimer > 0.8 ) {			spriteExplosion.visibility = 'hidden' ;			flag['explosion done'] = true;		}			if ( !flag['big eyes done'] && flag['big eyes'] && jumpUpTimer > 1.3 ) {			spriteBigEyes.visibility = 'hidden' ;			flag['big eyes done'] = true;		}		if ( !flag['sparks off'] && shutdownTimer > 2 ) {			spriteSparks.visibility = 'hidden' ;			// buttonBoost.visibility = 'hidden' ;			flag['sparks off'] = true;		}			if ( !flag['done'] && shutdownTimer > 2.5 ) {			spritePlugA.visibility = 'visible' ;			spritePlugB.visibility = 'hidden' ;			staticFooter.visibility = 'visible' ;			flag['done'] = true;			animationRunning = false;			return; // All done!		}			/*** Position ***/		// calculate new postion:		freeflight();		// emergency exit		if (position < -1000 || position > 5000) return;		// move the plug to the new position		movePlug();				/*** Continue ***/		// one more time!		positionZero = position;		positionMax = Math.max( position , positionMax );		velocityZero = velocity;		frameCount++;		setTimeout("animation()",1000/frameRate);	}		function freeflight() {		// calculate the position and velocity		position =  positionZero + ( velocityZero * timeDelta) + ( 0.5 * acceleration * timeDelta * timeDelta );		velocity = velocityZero + ( acceleration * timeDelta ) ;				// does that take us through the bounce floor?		if ( position <= floorPosition && velocity < 0 ) {			// yes			// at moment of impact			position = floorPosition;			var positionDelta = floorPosition-positionZero;						// there are two real solutions to this equation : only the negative square root is calculated			var timeDeltaBounce =  2*positionDelta / ( velocityZero - Math.sqrt( Math.abs( velocityZero*velocityZero + 2*acceleration*positionDelta ) ) );			velocity = velocityZero + ( acceleration * timeDeltaBounce ) ;					// post-bounce			var velocityRebound = -1 * velocity * floorElasticity;			timeDelta = timeDelta - timeDeltaBounce;			position =  positionZero + ( velocityRebound * timeDelta) + ( 0.5 * acceleration * timeDelta * timeDelta );			velocity = velocityRebound + ( acceleration * timeDelta ) ;					}		// check the floor		position = Math.max( position, floorPosition );	}	function movePlug() {		// move the plug on the screen		pxPosition = Math.round( pxPositionDatum - position );		if (IEKludgeNeeded) {			// kludge case - alternate moves to avoid flicker			if (frameCount%2) {						spritePlugA.top = pxPosition + 'px' ;			} else {					spritePlugB.top = pxPosition + 'px' ;			}			} else {			// ordinary case			spritePlugA.top = pxPosition + 'px' ;		}	}		function IEWinVersion() {		var ua = navigator.userAgent;		var MSIEOffset = ua.indexOf("MSIE ");		var isWin = ua.indexOf("Win");		if (MSIEOffset == -1 || isWin == -1) {			return 0;		} else {			return parseFloat(ua.substring(MSIEOffset + 5, ua.indexOf(";", MSIEOffset)));		}		}
