DAN ZEN EXPO - CODE EXHIBIT - POMP (SMALL)
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>ZIM Small Game</title> 

<!-- for CreateJS and ZIMjs http://zimjs.com - free to modify - Dan Zen 2015 -->
<!-- see http://zimjs.com/templates for more templates and meta tags -->

<script>var zon = true; // true for comments from zim code</script>
<script src="libraries/zim_1.4.3.js"></script>
<script src="libraries/createjs-2015.05.21.min.js"></script> 
<!-- or can go to zimjs.com and createjs.com for individual modules -->

<style>
	body {margin:0px; padding:0px; background-color:#000;}
	#myCanvas {position:absolute; background-color:#333;}
</style>

<script>

// SCALING OPTIONS
// "none"		sets canvas and stage to dimensions and does not scale if window changes
// "fit"		sets canvas and stage to dimensions and scales to fit inside window size
// "outside"		sets canvas and stage to dimensions and scales to fit outside window size
// "full"		sets canvas and stage to window size (canvas is actually set to screen size)

var scaling = "fit"; // fit scales to fit the browser window while keeping the aspect ratio
var width = 960;
var height = 640;
var frame = new zim.Frame(scaling, width, height); 
frame.on("ready", function() {	
	zog("ready from ZIM Frame");
	
	var stage = frame.stage;
	var stageW = frame.width;
	var stageH = frame.height;
	
	// LOAD SOUND
	// handle asset loading and call main app function when complete
	// we only have sounds to load for this game and they are in the game folder
	var contentPath = "game/";
	var manifest = [
		{src:"backing.mp3", id:"backing"},
		{src:"end.mp3", id:"end"},
		{src:"grow.mp3", id:"grow"},
		{src:"hit.mp3", id:"hit"},
		{src:"blip.mp3", id:"blip"}
	]; // array of objects
	var preload = new createjs.LoadQueue(true, contentPath);
	preload.installPlugin(createjs.Sound);
	preload.on("complete", app);	 // call the main code when ready	
	preload.loadManifest(manifest);
	
	// a little animated waiting component
	var waiter = new zim.Waiter(stage);
	waiter.show();

	// when the sounds load we can begin!
	function app() {
		
		// generally, the game is to keep a bunch of circles from hitting one another
		// the circles grow bigger and you press them to make them smaller
		// the longer you keep them apart, the more points you get (seconds playing game)
				
		waiter.hide(); // now that the sound has loaded, hide the waiter component
		createjs.Sound.play("backing",{loop:-1, volume:.5}); // loop forever
		
		// INITIAL SETUP
		var startTime = new Date(); // used to calculate the score based on time played
		var endCheck = false;		// has the game ended?
		
		// make a list of colors to cycle through and then randomize the order
		var colors = ["#f58e25", "#acd241", "#e472c4", "#50c4b7", "#d1a170"];
		zim.shuffle(colors);
		
		// game settings
		var spacing = 140;	// spacing between circles
		var minSize = 30; 	// minimum starting size
		var maxSize = 50; 	// maximum starting size
		var odds = .97; 	// if our random number is greater than this, we grow
		var bigger = 1.3; 	// make circle bigger by this much each time
		var smaller = .9; 	// when we press, make circle smaller by this much
		
		// for centering the circles
		var totalSpacing = spacing * (colors.length-1);
		var padding = (stageW - totalSpacing) / 2; 
		
		// MAKE CIRCLES
		// create a container to hold all our circles
		var circles = new createjs.Container();
		stage.addChild(circles);
				
		var c;				// temporarily stores each circle in loop
		var radius;			// the radius of the circle we are making
		var color;			// the color of the cicle we are making
		for (var i=0; i<colors.length; i++) { // loop to make circles
			radius = zim.rand(minSize, maxSize); // get a radius in the range
			color = colors[i]; 
			c = new zim.Circle(radius, color);
			c.cursor = "pointer"; // indicate that it can be pressed
			c.size = 1; // used to keep track of scale
			circles.addChild(c); // add the circle to the container

			c.x = i * spacing + padding; 
			c.y = stageH/2;		
		}
		
		// CLICKING CIRCLES
		// here is where we do code for when any of the circles get clicked
		// e.target will tell us which circle gets clicked and we store that in c
		// if c has hit another circle then its end property will be set to true
		// and we leave the function using the keyword, return
		circles.on("click", function(e) {
			var c = e.target;
			if (c.end) return; // do not allow clicks on circles that have touched		
			createjs.Sound.play("blip");
			// reducing scale while it is tweening causes a jump
			// check to see if it is animating and if so, remove the tween
			if (c.pause) {
				createjs.Tween.removeTweens(c);
				c.pause = false;  // mark the circle as not animating
				c.size /= bigger; // set the circle back to size before animation
			} else {
				c.size *= smaller; // was not animating so just make smaller
			}
			if (c.size < .1) { // make sure it is not too small
				c.size = .1;	
			}
			zim.scale(c, c.size); 	// set the scale
			circles.addChild(c);  	// bring clicked circle to top of circles
			stage.update();	
		});
		
		
		// GAME ANIMATION
		// here is the code that handles the circles getting bigger
		// and checking if any circles are hitting and if the game should end
		// this ticker goes at 60 frames per second so quite fast
		var timer = createjs.Ticker.on("tick", function() {		
			var c; 	// a temporary reference to a circle that is being made bigger
			for (var i=0; i<circles.numChildren; i++) { // loop through all the circles
				if (Math.random() > odds) { // have we rolled higher than the odds?
					c = circles.getChildAt(i); // if so, get a reference to the circle
					if (c.end || c.pause) continue; // if it is already hitting or currently animating go to next i
					c.size *= bigger; 	// set the new scale
					c.pause = true; 	// set the circle as animating
					createjs.Sound.play("grow");
					// animate the circle to the new scale
					// call the done function when done and pass to it which circle is animating
					zim.animate(c, {scaleX:c.size, scaleY:c.size}, 1700, "elasticOut", done, c);					
				}			
			}
			stage.update();		
		});	
		createjs.Ticker.setFPS(60);
		
		
		// HIT TESTS
		// here is the function that runs when a circle is finished growing
		// we collect the circle in the parameter c
		function done(c) {
			c.pause = false; // set it to be done animating
			var c2; // a temporary variable to hold a second circle
			// loop through all the circles to see if it is hitting any now that it is bigger
			for (var i=0; i<circles.numChildren; i++) {
				c2 = circles.getChildAt(i); // get the second circle
				if (c == c2) continue;		// if it is the same as the first, go to the next i
				if (zim.hitTestCircle(c, c2, 4)) { // if the first circle is hitting any of 4 points on the second circle
					createjs.Sound.play("hit");
					c2.end = true;			// mark circles as ended (hitting)
					c.end = true;
					c2.cursor = "default";	// take off the pointer indicator
					c.cursor = "default";
					odds -= .05;			// decrease the odds to make circles more likely to grow
				}								
			}
			
			// find out if there is zero or one circle left
			// we need to count how many circles have the end property set to true
			var ends = 0;
			var last; // this will reference the last circle alive
			for (i=0; i<circles.numChildren; i++) {
				c2 = circles.getChildAt(i);
				if (c2.end) {
					ends++;	 	// increase our counter
				} else {
					last = c2;	// this could be the last circle as it has not ended
				}
			}	
			// when two circles end together there is a possibility of ending twice
			// so only use one of them to end by setting an end check
			// if we have already ended then do not end again!
			if (ends >= circles.numChildren - 1 && !endCheck) {
				endCheck = true; // mark that we have ended
				if (last) {
					last.end = true;
					last.cursor = "default";
				}
				final();				
			}
		}
		

		// GAME END
		// turn off ticker, show score and reset button
		function final() {
			createjs.Sound.play("end");
			createjs.Ticker.off("tick", timer); // stop the ticker from running
			var currentTime = new Date(); // get the current time and subtract from the start time
			var time = Math.round((currentTime.getTime() - startTime.getTime()) / 1000);
			var label = new zim.Label(String(time),60,null,"white",null,"#666");
			zim.centerReg(label);
			stage.addChild(label);
			label.x = stageW/2; 
			label.y = 100;	
			
			// wait a bit while the ending sound plays and they view their score
			setTimeout(function() {		
				// darken the game		
				var rect = new zim.Rectangle(stageW,stageH);
				rect.alpha = .7;
				stage.addChild(rect);
				// add a restart button
				var button = new zim.Button(300, 100, new zim.Label("RESTART", null, null, "white"), "#666", "#777");
				stage.addChild(button);
				zim.centerReg(button);
				button.x = stageW/2;
				button.y = 400;
				button.on("click", function() {
					zgo("gameSmall.html"); // load the page again (poor man's restart)
				});				
				stage.update();				
			}, 4000);
			
			stage.update();
		}
		
		
		// SOUND MUTE
		// this code handles the mute button (just a label)	or M key press	
		var mute = new zim.Label("MUTE", 20, null, "white", "violet");
		mute.cursor = "pointer";
		mute.x = stageW - mute.width - 30;
		mute.y = stageH - mute.height - 10;
		stage.addChild(mute);
		mute.on("click", doSound);
		function doSound() {
			createjs.Sound.muted = !createjs.Sound.muted; 
			if (createjs.Sound.muted) {
				mute.text = "SOUND";
			} else {
				mute.text = "MUTE";
			}
		}
		window.addEventListener("keydown", function(e) {
			// zog(e.keyCode);
			if (e.keyCode == 77) { // M key
				doSound();
			}
		});
		
		stage.update();	
	}
	
}); // end of ready
</script>
</head>

<body>
<!-- canvas with id="myCanvas" is made by zim Frame -->
</body>
</html>