DAN ZEN EXPO - CODE EXHIBIT - ZIM AVATAR
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Zim Avatar</title>

<link rel="shortcut icon" type="image/ico" href="favicon.ico" />

<!-- for Google -->
<meta name="description" content="ZIM Avatar - multiple avatars - multiuser with SocketIO and NodeJS - ZIM" />
<meta name="keywords" content="zimjs, socket, socketserver, socketio, nodejs, danzen, javascript, code, free, interactive media, modules, library, html5" />    
<meta name="author" content="Dan Zen" />
<meta name="copyright" content="Dan Zen" />

<!-- for Facebook -->          
<meta property="og:title" content="ZIM Avatar - multiple avatars - multiuser with SocketIO and NodeJS - ZIM" />
<meta property="og:type" content="website" />
<meta property="og:image" content="http://zimjs.com/images/zim_socket.jpg" />
<meta property="og:url" content="http://zimjs.com/avatar.html" />
<meta property="og:description" content="ZIM Avatar - multiple avatars - multiuser with SocketIO and NodeJS - ZIM" />

<!-- for Twitter -->          
<meta name="twitter:card" content="summary" /> <!-- do not edit this line (must say "summary") -->
<meta name="twitter:title" content="ZIM Avatar - multiple avatars - multiuser with SocketIO and NodeJS - ZIM" />
<meta name="twitter:description" content="ZIM Avatar - multiple avatars - multiuser with SocketIO and NodeJS - ZIM" />
<meta name="twitter:image" content="http://zimjs.com/images/zim_socket.jpg" />

<!-- for Apple -->
<meta name="viewport" content="width=device-width, maximum-scale=1, minimal-ui" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link rel="apple-touch-icon-precomposed" href="images/iconS_57.png" />

<!-- 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="http://d309knd7es5f10.cloudfront.net/zim_1.4.2_min.js"></script><!-- take off _min to see code -->
<script src="http://code.createjs.com/createjs-2014.12.12.min.js"></script> 
<script src="http://d309knd7es5f10.cloudfront.net/zimsocket_1.0.js"></script> 
<!-- or can go to zimjs.com and createjs.com for individual modules -->

<script src="https://cdn.socket.io/socket.io-1.3.4.js"></script>

<style>
	body {margin:0px; padding:0px; background-color:#FFF; background-image:url("images/avatarBacking3.jpg");}
	#myCanvas {position:absolute; background-color:#000;}
</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"; // full automatically sets width and height to window size
var width = 1000;
var height = 1000;
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;
	
	// ZIM Avatar - 2015 Dan Zen
	// uses zimsocket.js and zimserver.js at http://zimjs.com/socket.html
	
	// SUMMARY
	// client makes an avatar with two colors and joins other avatars
	// these all move around and the movement is shown on everyone's screen
	
	// STRATEGY
	// each client makes their own avatar object 
	// and sends the properties of the object to the server
	// the server keeps track of all the data
	// the client receives all the initial data from the server when it joins
	// the client then creates avatars for everyone else based on this data
	// and stores these avatars in an avatars object based on the other client ids
	// when another avatar joins the client stores this in avatars too and makes the avatar
	// when a client leaves, the client sends a disconnect to the server
	// the server sends this out to the remaining clients
	// the remaining clients remove the avatar and update their data
	
	// ZIM handles all the server functions for you and gives you events
	// join - when you join it passes all the other clients' data as an event object
	// otherjoin - when another joins it passes that client's data as an event object
	// otherleave - when another leaves it passes that client's data as an event object
	// data - when any client moves, it passes that client's movement data as an event object
	
	// here we show the Socket code first followed by the interface code
	// the begin function is called once the user selects the colors and presses the OKAY button
	
	var others = {};
	var colors = {grey:"#666",brown:"#d1a170",blue:"#50c4b7",purple:"#e472c4",green:"#acd241",orange:"#f58e25"}

	function begin() { // called from interface button at end of section below
		
		// set parameters for the zim.Socket object
		var server = "http://54.209.193.48:3000";
		var app = "zimavatar";
		var room = null; // just use the default room
		var maxPeople = null; // just use the default of 0 which means unlimited
		var fill = null; // just use the default of fill where clients leave
		// we can send an optional initial object to the server
		// this information will get sent to all the other clients in an otherjoin event
		var initObj = {outer:colorOuter.currentValue, inner:colorInner.currentValue, x:avatar.x, y:avatar.y};

		socket = new zim.Socket(server, app, room, maxPeople, fill, initObj);
		
		// the ready event is triggered when a client first joins
		// the event object holds all the data of the others in the room
		// in this case, we have one big room as the default maxPeople is unlimited (the second null above)
		socket.on("ready", function(avatars) {
			
			zog("connected");
			
			// populate the room using the data sent from the server - something like this:
			// {id:{property:value, p2:v2}, id2:{property:value, p2:v2}, etc.}
			// note, the data will also hold an id so data.id would give the id too
			var data;			
			for (var id in avatars) {
				data = avatars[id];
				if (data) createAvatar(id, data.outer, data.inner, data.x, data.y);		
			}
		});
		
		socket.on("otherjoin", function(data) {
			// create an avatar for the client who joined using the data sent from the server
			if (data) createAvatar(data.id, data.outer, data.inner, data.x, data.y);		
		});
		
		stage.on("stagemousedown", function() {
			// make our avatar move
			zim.animate(avatar, {x:stage.mouseX, y:stage.mouseY}, 1000, "backOut");
			// send x and y to other clients
			socket.setProperties({x:stage.mouseX, y:stage.mouseY});
		});	
		
		socket.on("data", function(data) {
			// receiving data from other clients
			// note: data will always hold an id
			// but not necessarily all the client data
			// for instance, in this case, we only sent x and y when moving
			// so we will not have a data property for the colors
			// to get a property for the colors we could use:
			// socket.getSenderProperty("inner");  
			// or to get some other client's inner color:
			// socket.getOtherProperty(clientId, "inner");
			zim.move(others[data.id], data.x, data.y, 700, "backOut");		
		});
		
		socket.on("otherleave", function(data) {
			zim.animate(others[data.id], {scaleX:0, scaleY:0}, 700, "backIn", gone);
			function gone() {
				delete others[data.id];
			}
		});
		
		socket.on("error", function() {
			error.label.text = "connection error";
			error.show();
			socket.disconnect();
		});

	}
	
	function createAvatar(id, outerColor, innerColor, x, y) {
		var other = others[id] = new createjs.Container();
		stage.addChildAt(other, 0);
		var outer = new zim.Circle(120, colors[outerColor]);
		other.addChild(outer);
		outer.shadow = new createjs.Shadow("rgba(0,0,0,.4)", 5, 5, 10);
		var inner = new zim.Circle(60, colors[innerColor]);
		other.addChild(inner);
		inner.alpha = .9;
		other.x = x;
		other.y = y;
		var b = other.getBounds();
		other.cache(-b.width/2,-b.height/2,b.width,b.height);
		zim.scale(other, 0);
		zim.animate(other, {scaleX:.4, scaleY:.4}, 700, "backOut");
	}
	
	// INTERFACE
	
	var pane = new zim.Pane(stage, 800, 900, null, "#ddd", null, null, false, 100);
	pane.show();
	pane.regY -= 10;
	
	var errorLabel = new zim.Label("please choose colors", null, null, "white");
	var error = new zim.Pane(stage, 400, 100, errorLabel, "red");
	zim.scale(error, 1.5);
	
	var avatar = new createjs.Container();
	avatar.x = stageW/2;
	avatar.y = stageH/2 - 240;
	stage.addChild(avatar);
	
	var outer = new zim.Circle(120, "#fff");
	avatar.addChild(outer);
	outer.shadow = new createjs.Shadow("rgba(0,0,0,.4)", 5, 5, 10);
	
	var inner = new zim.Circle(60, "#eee");
	avatar.addChild(inner);
	inner.alpha = .9;
	
	var colorOuter = new zim.Stepper(["outer", "orange","green","purple","blue","brown","grey"], 400);
	colorOuter.loop = true;
	pane.addChild(colorOuter);
	zim.scaleTo(colorOuter, pane, 70);
	zim.centerReg(colorOuter);
	var outerSwipe = new zim.Swipe(colorOuter);
	outerSwipe.on("swipe", function(e) {
		if (e.target.direction == "left") colorOuter.next();
		if (e.target.direction == "right") colorOuter.prev();
	});
	
	var colorInner = new zim.Stepper(["inner", "grey","brown","blue","purple","green","orange"], 400);
	colorInner.loop = true;
	pane.addChild(colorInner);
	zim.scaleTo(colorInner, pane, 70);
	zim.centerReg(colorInner);
	colorInner.y += 140;
	var innerSwipe = new zim.Swipe(colorInner);
	innerSwipe.on("swipe", function(e) {
		if (e.target.direction == "left") colorInner.next();
		if (e.target.direction == "right") colorInner.prev();
	});
	
	colorOuter.on("change", function(e) {
		if (e.target.currentValue == "outer") outer.setFill("white");
		else outer.setFill(colors[e.target.currentValue]);
		stage.update();
	});
	
	colorInner.on("change", function(e) {
		if (e.target.currentValue == "inner") inner.setFill("#ccc");
		else inner.setFill(colors[e.target.currentValue]);
		stage.update();
	});
	
	var label = new zim.Label("OKAY",null,null,"white","black");
	var button = new zim.Button(200,100,label,"black","white");
	pane.addChild(button);
	zim.centerReg(button);
	button.y = 300;
	button.on("click", function() {
		if (colorInner.currentValue == "inner" || colorOuter.currentValue == "outer") {
			// just in case a connection error changed it
			error.label.text = "please choose colors";
			error.show();
			return;
		}
		pane.hide();
		var b = avatar.getBounds();
		avatar.cache(-b.width/2,-b.height/2,b.width,b.height);
		zim.animate(avatar, {scaleX:.4, scaleY:.4}, 700, "backOut", begin);
	});
	
	stage.update();	
	
}); // end of ready
</script>


</head>

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