So you may have been thinking that its way too fiddly and complicated to get graphics into a game as the engine uses it’s own custom bitmaps.
Your right. The point was that by default you would just draw some simple shapes. However if you really want more complex graphics you can always use this. Its a simple sprite editing app.

I wrote a simple rough and ready app to do this as one of the first GameEngine apps. It was quite fiddly but it did the job. I have now re-written it to be a little more user friendly.

Hope this helps you in your creations. Of course, as always, if you don’t like something or want to add more functionality then go ahead.

<html>
<head>
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=0">
	
	<title>GE Sprite Editor</title>
	<style>
Body
{
	background-color: #181818;
	color: #ffffff;
	margin: 0px;
}
	
Canvas
{
	position:fixed;
}

#counter
{
	position:absolute;
	bottom:0;
	right:0;
	color:#ffffff;
	display:inline;
}

#CodeWindow
{
	position:absolute;
	top:10;
	left:20;
	width:400px;
	height:340px;
	border: 1px solid #ffffff;
	background: rgba(0,0,0,.8);
	color: rgb(255,255,255);
}

#CodePanel
{
	margin:20px;
	width:400px;
	height:250px;
	overflow:none;
}

#CodeOut
{
 white-space: pre;
 width:360px;
 height:260px;
 font-size:10px;

}


#ImportCodeWindow
{
	position:absolute;
	top:10;
	left:20;
	width:400px;
	height:340px;
	border: 1px solid #ffffff;
	background: rgba(0,0,0,.8);
	color: rgb(255,255,255);
}

#ImportCodePanel
{
	margin:20px;
	width:400px;
	height:250px;
	overflow:none;
}

#ImportCode
{
	white-space: pre;
	width:360px;
	height:260px;
	font-size:10px;
}

.hide
{
	display:none;
	background-color:#ff0000; 	
}
	</style>
</head>
<body>
	<canvas id="myCanvas">Sorry... your browser does not support the canvas element.</canvas>
	<p id="counter">counter</p>
	<div id="CodeWindow" class="hide"  title="Press Ctrl-C to copy to clipboard">
		<div id="CodePanel">
			<textarea id="CodeOut">output</textarea>
		</div>
		<div class="buttonPanel">
			<input type=button value="Close" onClick="ExportClose();"/>
		</div>
	</div>
	<div id="ImportCodeWindow" class="hide" >
		<div id="ImportCodePanel">
			<textarea id="ImportCode"></textarea>
		</div>
		<div class="buttonPanel">
			<input type=button value="Close" onClick="ImportClose();"/>
			<input type=button value="Import Code" onClick="ImportBtn();"/>
		</div>
	</div>
</body>
<script>

// Global variables
// used for calculating and showing the frames per second
var dwFrames=0;
var dwCurrentTime=0;
var dwLastUpdateTime=0;
var dwElapsedTime=0;
var fpsText;
// The game engine needs to persist
var GE;


var spriteSize = 16;
var canvasSize = Math.floor(240/spriteSize)*spriteSize;
var canvasOffset = Math.floor((240 - canvasSize)/2);
var pixelSize = Math.floor(canvasSize / spriteSize);
var selectedColour = 15;

var canvasBitmap;

var bitmaps = new Array();
var currentFrame = 0;
var selectedColour = 5;

var clipboard;

var colourPalette;
var mainToolbar;
var preview;
var canvas;
var animationControls;

var animationType = 0; // 0 = stop, 1 = loop, 2 = bounce
var refreshPreview = false;
var animationSpeed = .5;

init = function()
{
	var pageCanvas = document.getElementById('myCanvas');
	if (pageCanvas.getContext)
	{
		// got to have the game engine 
		GE = GameEngine16Colour(pageCanvas,Update,Draw);

		// when the window resizes we want to resize the canvas
		window.onresize = function() { doResize(); };
		doResize();

		// screen background
		GE.DrawRect(0,0,GE.CanvasWidth, GE.CanvasHeight,8);

		InitBitmaps();
		colourPalette = ColourPalette();
		animationControls = AnimationControls();
		mainToolbar = MainToolbar();
		preview = Preview();
		canvas = Canvas();
	}
}

function InitBitmaps()
{
	bitmaps = new Array();
	bitmaps.push(Bitmap(spriteSize,spriteSize));
	canvasBitmap = Bitmap(canvasSize,canvasSize);
	GE.SpriteAdd("canvasBitmap",Sprite(canvasOffset,canvasOffset,canvasBitmap),1);
}

// This gets called every time the engine redraws the canvas
// For slow machines this may be less that the actual fps 
Draw = function()
{
	colourPalette.Draw();
	mainToolbar.Draw();
	preview.Draw();
	canvas.Draw();
	animationControls.Draw();

	// calculate and show the fps
	dwFrames++;
	dwCurrentTime = (new Date).getTime();	
	dwElapsedTime = dwCurrentTime - dwLastUpdateTime;
	if(dwElapsedTime >= 1000)
	{        
		fpsText = "FPS " + dwFrames;
		dwLastUpdateTime = dwCurrentTime;
		dwFrames = 0;
	}
	var l = document.getElementById('counter');
	l.textContent = fpsText;
}

// This gets called every game update frame 
Update = function()
{
	colourPalette.Update();
	mainToolbar.Update();
	preview.Update();
	canvas.Update();
	animationControls.Update();
}

// This just makes sure the canvas is as big as possible
// given the window size.
function doResize()
{
	var pageCanvas = document.getElementById('myCanvas');
	var screenHeight = window.innerHeight;
	var screenWidth = window.innerWidth;
	if ( GE.CanvasWidth > GE.CanvasHeight)
	{
		if (screenWidth*3/4 < screenHeight)
		{
			screenHeight = Math.floor(screenWidth*3/4);
		}
		else
		{
			screenWidth = Math.floor(screenHeight*4/3);
		}
	}
	else
	{
		if (screenHeight*3/4 < screenWidth)
		{
			screenWidth = Math.floor(screenHeight*3/4);
		}
		else
		{
			screenHeight = Math.floor(screenWidth*4/3);
		}
	}
	pageCanvas.style.height = screenHeight+"px";
	pageCanvas.style.width = screenWidth+"px";
	pageCanvas.style.marginLeft = (window.innerWidth-screenWidth)/2;
	pageCanvas.style.marginTop = Math.floor((window.innerHeight-screenHeight)/2)+1;
}

function ColourPalette()
{
	var obj = {};
	
	obj.Init = function ()
	{
		// draw background area for colour palette
		GE.DrawRect(GE.CanvasWidth-76,84,32,17*9+1,6+8);
		GE.DrawRect(GE.CanvasWidth-75,85,31,17*9+1,6);

		// Draw colours
		for ( var c = 0; c<16; c++ )
		{
			GE.DrawRect(GE.CanvasWidth-75,94+c*9,30,9,c);
		}
		// and the clear button
		GE.DrawRect(GE.CanvasWidth-75,85,30,9,0);
		GE.DrawLine(GE.CanvasWidth-75,85,GE.CanvasWidth-75+8,85+8,7);
		GE.DrawLine(GE.CanvasWidth-75+16,85,GE.CanvasWidth-75+8+16,85+8,7);
		
		// create a sprite to show selected colour
		var bm = Bitmap(30,9);
		bm.DrawRect(0,0,30,9,15);
		bm.DrawRect(1,1,28,7,-1);
		GE.SpriteAdd("SelectedColour",Sprite(GE.CanvasWidth-75,94+selectedColour*9,bm));
	}

	obj.Update = function()
	{
		if ( GE.mouseClicked)
		{
			if ( GE.mousePos.x >= GE.CanvasWidth-75 && GE.mousePos.x <= GE.CanvasWidth-75+30)
			{
				var newColour = Math.floor((GE.mousePos.y - 94) / 9);
				if ( newColour >= -1 && newColour <= 15 )
				{
					selectedColour = newColour;
					GE.SpriteGet("SelectedColour").pos.y = 94+selectedColour*9;
				}
			}
		}
	}

	obj.Draw = function()
	{
	}

	obj.Init();
	
	return obj;
}

function baseButtonControl ()
{
	var obj = {};

	DrawButton = function(bm,x,y,costumeNum,buttonList,code)
	{
		var buttons = ButtonsCostume();
		bm.DrawRect(x,y,18,18,6+8);
		bm.DrawRect(x+1,y+1,17,17,6);
		bm.Paste(x+1,y+1,buttons.GetItem(costumeNum));
		buttonList.push([x,y,code]);
	}

	DrawButtonSelected = function(bm,x,y,costumeNum,buttonList,code)
	{
		var buttons = ButtonsCostume();
		bm.DrawRect(x,y,18,18,6);
		bm.DrawRect(x+1,y+1,17,17,6+8);
		bm.Paste(x+1,y+1,buttons.GetItem(costumeNum));
		buttonList.push([x,y,code]);
	}

	FindButtonAt = function(x,y,buttonList)
	{
		for(var button in buttonList)
		{
			if ( x >= buttonList[button][0] && x <= buttonList[button][0]+20 && y >= buttonList[button][1] && y <= buttonList[button][1]+20 )
			{
				buttonList[button][2]();
				return true;
			}
		}
		return false;
	}

	return obj;
}

function MainToolbar()
{
	var obj = baseButtonControl();
	
	var buttonList = Array();

	obj.Init = function()
	{
		buttonList = new Array();
		var bm = Bitmap(40,144);
		
		// Draw buttons
		var buttons = ButtonsCostume();
		var left = 0; //GE.CanvasWidth-40;
		var ypos = 0; //94;

		// left/right image
		DrawButton(bm,left,ypos,0,buttonList,PreviousFrame);
		DrawButton(bm,left+20,ypos,1,buttonList,NextFrame);
		
		ypos += 20
		// insert frame / delete frame
		DrawButton(bm,left,ypos,10,buttonList,InsertFrame);
		DrawButton(bm,left+20,ypos,11,buttonList,DeleteFrame);

		ypos += 28
		// copy/paste
		DrawButton(bm,left,ypos,4,buttonList,Copy);
		DrawButton(bm,left+20,ypos,5,buttonList,Paste);

		ypos += 28
		// rotate left/right
		DrawButton(bm,left,ypos,6,buttonList,RotateLeft);
		DrawButton(bm,left+20,ypos,7,buttonList,RotateRight);

		ypos += 20
		// mirror horizontal/vertical
		DrawButton(bm,left,ypos,8,buttonList,FlipHorizontal);
		DrawButton(bm,left+20,ypos,9,buttonList,FlipVertical);

		ypos += 30
		// import/export
		DrawButton(bm,left,ypos,2,buttonList,Export);
		DrawButton(bm,left+20,ypos,3,buttonList,Import);

		GE.Paste(GE.CanvasWidth-40,94,bm);
	}

	obj.Draw = function()
	{
	}

	obj.Update = function()
	{
		var keyPressed = "";
		if ( GE.mouseClicked)
		{
			if ( GE.mousePos.x >= GE.CanvasWidth-40 && GE.mousePos.y >= 94 )
			{
				keyPressed = FindButtonAt(GE.mousePos.x-(GE.CanvasWidth-40), GE.mousePos.y-94,buttonList);
			}
		}
	}

	function NextFrame()
	{
		if ( currentFrame < bitmaps.length-1 )
			currentFrame++;
		GE.SpriteGet("SpritePreview").costume.SetItem(currentFrame,bitmaps[currentFrame]);
	}
	function PreviousFrame()
	{
		if ( currentFrame > 0 )
			currentFrame--;
		GE.SpriteGet("SpritePreview").costume.SetItem(currentFrame,bitmaps[currentFrame]);
	}
	function InsertFrame()
	{
		var bm = Bitmap(spriteSize, spriteSize);
		var newbitmaps = new Array();
		var f = 0;
		for ( f = 0; f <= currentFrame; f++)
		{
			newbitmaps[f] = bitmaps[f];
		}
		newbitmaps[currentFrame+1] = bm;
		for ( f = currentFrame+1; f < bitmaps.length; f++)
		{
			newbitmaps[f+1] = bitmaps[f];
		}

		bitmaps = newbitmaps;
		currentFrame += 1;
		refreshPreview = true;
	}
	function DeleteFrame()
	{
		var newbitmaps = new Array();
		var f = 0;
		for ( f = 0; f < currentFrame; f++)
		{
			newbitmaps.push(bitmaps[f]);
		}

		for ( f = currentFrame+1; f < bitmaps.length; f++)
		{
			newbitmaps.push(bitmaps[f]);
		}

		if ( newbitmaps.length == 0 )
			newbitmaps.push(Bitmap(spriteSize,spriteSize));

		bitmaps = newbitmaps;
		if ( currentFrame + 1 >= bitmaps.length )
			currentFrame = bitmaps.length-1;
		refreshPreview = true;
	}
	function Copy()
	{
		clipboard = bitmaps[currentFrame].Clone();
	}
	function Paste()
	{
		bitmaps[currentFrame] = clipboard.Clone();
		GE.SpriteGet("SpritePreview").costume.SetItem(currentFrame,bitmaps[currentFrame]);
	}
	function FlipHorizontal()
	{
		var newBitmap = bitmaps[currentFrame].FlipX();
		bitmaps[currentFrame] = newBitmap;
		GE.SpriteGet("SpritePreview").costume.SetItem(currentFrame,bitmaps[currentFrame]);
	}
	function FlipVertical()
	{
		var newBitmap = bitmaps[currentFrame].FlipY();
		bitmaps[currentFrame] = newBitmap;
		GE.SpriteGet("SpritePreview").costume.SetItem(currentFrame,bitmaps[currentFrame]);
	}
	function RotateLeft()
	{
		var newBitmap = bitmaps[currentFrame].RotateLeft();
		bitmaps[currentFrame] = newBitmap;
		GE.SpriteGet("SpritePreview").costume.SetItem(currentFrame,bitmaps[currentFrame]);
	}
	function RotateRight()
	{
		var newBitmap = bitmaps[currentFrame].RotateRight();
		bitmaps[currentFrame] = newBitmap;
		GE.SpriteGet("SpritePreview").costume.SetItem(currentFrame,bitmaps[currentFrame]);
	}
	function Export()
	{
		var output = document.getElementById('CodeOut');
		var code = "var cs=Costume();\n"
		var addcomma = "";
		for (var b in bitmaps)
		{
			var bm = bitmaps[b];
			code+="cs.SetItem("+b+",\n"
			addcomma = ",";
			code += "Bitmap("+spriteSize+","+spriteSize+").PixelsFromArray(["
			for ( var y = 0; y < spriteSize; y++ )
			{
				for ( var x = 0; x < spriteSize; x++ )
				{
					if (x+y > 0 )
						code += "," 
						
					code += bm.GetPixel(x,y);
				}
				code += "\n";
			}
			code += "]));\n";
		}
		var exportWindow = document.getElementById('CodeWindow');
		exportWindow.className = "";
		output.textContent = code;
		output.focus();
		output.select();
	}
	function Import()
	{
		var importWindow = document.getElementById('ImportCodeWindow');
		importWindow.className = "";
	}

	obj.Init();

	return obj;
}

function AnimationControls()
{
	var obj = baseButtonControl();

	var buttonList = Array();

	obj.Init = function()
	{
		buttonList = new Array();
		// Draw buttons
		var bm = Bitmap(60,20);
		var buttons = ButtonsCostume();
		var left = 0; //GE.CanvasWidth-40;
		var ypos = 0; //64;
		// animate bounce, loop, stop
		DrawButton(bm,left,ypos,12,buttonList,SelectLoop);
		DrawButton(bm,left+20,ypos,13,buttonList,SelectBounce);
		DrawButton(bm,left+40,ypos,14,buttonList,SelectStop);
		DrawButtonSelected(bm,left+40,ypos,14,buttonList,{});
		// Frame n of n text
		GE.DrawRect(GE.CanvasWidth-42,84,8*5,8,8);
		GE.WriteString(StrNumberPad(currentFrame+1, 2)+"/"+StrNumberPad(bitmaps.length, 2),GE.CanvasWidth-42,84,15);
	
		// animate speed slider
		// speed is scale of .1 to 1
		var offset = 60 * animationSpeed;
		GE.DrawRect(GE.CanvasWidth-70,1,2,61,7);
		GE.DrawRect(GE.CanvasWidth-70-5,offset,12,4,8);
		GE.DrawRect(GE.CanvasWidth-70-4,1+offset,10,2,7);
		
		GE.Paste(GE.CanvasWidth-60,64,bm);
	}

	obj.Update = function()
	{
		if ( GE.mouseDown)
		{
			if ( GE.mousePos.x >= GE.CanvasWidth-75 && GE.mousePos.x <= GE.CanvasWidth-65 && GE.mousePos.y >= 1 && GE.mousePos.y <= 60 )
			{
				animationSpeed = 1 - (GE.mousePos.y -1) / 60; 
				var offset = 60 * (1-animationSpeed);
				GE.DrawRect(GE.CanvasWidth-70-5,1,12,61,8);
				GE.DrawRect(GE.CanvasWidth-70,1,2,61,7);
				GE.DrawRect(GE.CanvasWidth-70-5,offset,12,4,8);
				GE.DrawRect(GE.CanvasWidth-70-4,1+offset,10,2,7);
				refreshPreview = true;
			}
		}
		if ( GE.mouseClicked)
		{
			if ( GE.mousePos.x >= GE.CanvasWidth-60 && GE.mousePos.y <= 84 )
			{
				keyPressed = FindButtonAt(GE.mousePos.x-(GE.CanvasWidth-60), GE.mousePos.y-64,buttonList);
				if ( keyPressed )
				{
					// Draw buttons
					var bm = Bitmap(60,20);
					var buttons = ButtonsCostume();
					var left = 0; //GE.CanvasWidth-40;
					var ypos = 0; //64;
					// animate bounce, loop, stop
					DrawButton(bm,left,ypos,12,buttonList,SelectLoop);
					DrawButton(bm,left+20,ypos,13,buttonList,SelectBounce);
					DrawButton(bm,left+40,ypos,14,buttonList,SelectStop);
					switch (animationType)
					{
						case 0:
							DrawButtonSelected(bm,left+40,ypos,14,buttonList,{});
							break;
						case 1:
							DrawButtonSelected(bm,left,ypos,12,buttonList,{});
							break;
						case 2:
							DrawButtonSelected(bm,left+20,ypos,13,buttonList,{});
							break;
					}
					GE.Paste(GE.CanvasWidth-60,64,bm);
					refreshPreview = true;
				}
			}
		}
		// Frame n of n text
		GE.DrawRect(GE.CanvasWidth-42,84,8*5,8,8);
		GE.WriteString(StrNumberPad(currentFrame+1, 2)+"/"+StrNumberPad(bitmaps.length, 2),GE.CanvasWidth-42,84,15);
	}

	obj.Draw = function()
	{
	}

	obj.Init();

	function SelectLoop()
	{
		animationType = 1;
		refreshPreview = true;
	}
	function SelectBounce()
	{
		animationType = 2;
		refreshPreview = true;
	}
	function SelectStop()
	{
		animationType = 0;
		refreshPreview = true;
	}

	return obj;
}

function Preview()
{
	var obj={};
	
	obj.Init = function()
	{
		// draw background area for preview box
		GE.DrawRect(GE.CanvasWidth-62,0,62,62,6+8);
		GE.DrawRect(GE.CanvasWidth-61,1,61,61,6);

		// preview box .. max size 60
		GE.DrawRect(GE.CanvasWidth-61,1,60,60,7);

		var offset = Math.floor((60-spriteSize)/2);
		GE.DrawRect(GE.CanvasWidth-61+offset,1+offset,spriteSize,spriteSize,0);
		GE.SpriteAdd("SpritePreview",Sprite(GE.CanvasWidth-61+offset,1+offset,bitmaps[0]),1);
		refreshPreview = true;
	}

	obj.Update = function()
	{
		if ( GE.mouseDown)
		{
			var offset = Math.floor((60-spriteSize)/2);
			if ( GE.mousePos.x >= GE.CanvasWidth-61+offset && GE.mousePos.x <= GE.CanvasWidth-61+offset+spriteSize 
				&& GE.mousePos.y >= offset && GE.mousePos.y <= offset+spriteSize )
			{
				if ( selectedColour >=0 )
					GE.DrawRect(GE.CanvasWidth-61+offset,1+offset,spriteSize,spriteSize,selectedColour);
			}
		}
		if ( refreshPreview )
		{
			var cs = Costume();
			cs.SetItems(bitmaps,0);
			GE.SpriteGet("SpritePreview").SetCostume(cs);
			if ( animationType == 1 )
				GE.SpriteGet("SpritePreview").SetAnimatorLoop();
			else
				GE.SpriteGet("SpritePreview").SetAnimatorBounce();
			GE.SpriteGet("SpritePreview").SetAnimatorUpdateRate(animationSpeed);
			GE.SpriteGet("SpritePreview").costumeAnimator.repeat = true;
			refreshPreview = false;
		}
		if ( animationType == 0 )
			GE.SpriteGet("SpritePreview").costumeAnimator.Set(currentFrame);
	}

	obj.Draw = function()
	{
	}

	obj.Init();

	return obj;
}

function StrNumberPad(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
}

function Canvas()
{
	var obj = {};
	
	obj.Init = function()
	{
		// Draw Area ... multiple of 60
		var cs = Costume();

		for ( var pixelShift = 0; pixelShift < pixelSize; pixelShift++ )
		{
			var bm = Bitmap(canvasSize,canvasSize);
			bm.DrawRect(0,0,canvasSize,canvasSize,0);
			for ( pixel=0; pixel <= spriteSize; pixel++)
			{
				bm.DrawLine(0,pixelShift+pixel*pixelSize, canvasSize, canvasSize+pixelShift+pixel*pixelSize,8);
				bm.DrawLine(-pixelShift+pixel*pixelSize,0, canvasSize-pixelShift+pixel*pixelSize,canvasSize,8);
			}
			cs.SetItem(pixelShift,bm);
		}

		var sp = Sprite(canvasOffset,canvasOffset,cs);
		sp.SetAnimatorLoop();
		sp.costumeAnimator.repeat = true;
		sp.SetAnimatorUpdateRate(.1);
		GE.SpriteAdd("CanvasBackground",sp,0);

		var bm = Bitmap(canvasSize,canvasSize);
		for ( var x = 0; x <= spriteSize; x++ )
		{
			bm.DrawLine(x*pixelSize,0,x*pixelSize,spriteSize*pixelSize,7);
			bm.DrawLine(0,x*pixelSize,spriteSize*pixelSize,x*pixelSize,7);
		}
		var sp = Sprite(canvasOffset,canvasOffset,bm);
		GE.SpriteAdd("CanvasGrid",sp,2);
	}

	obj.Update = function()
	{
		if ( GE.mouseDown)
		{
			// Has the user clicked in the canvas
			var xpix = Math.floor((GE.mousePos.x-canvasOffset) / pixelSize);
			var ypix = Math.floor((GE.mousePos.y-canvasOffset) / pixelSize);
			
			if ( xpix >= 0 && xpix < spriteSize && ypix >=0 && ypix < spriteSize)
			{
				bitmaps[currentFrame].SetPixel(xpix,ypix,selectedColour);
			}
		}
	}

	obj.Draw = function()
	{
		// Rebuild the canvas bitmap
		for (var y = 0; y < spriteSize; y++)
		{
			for(var x = 0; x < spriteSize; x++)
			{
				var col = bitmaps[currentFrame].GetPixel(x,y);
				canvasBitmap.DrawRect(x*pixelSize+canvasOffset, y*pixelSize+canvasOffset,pixelSize,pixelSize,col);
			}
		}
	}

	obj.Init();

	return obj;
}

ButtonsCostume = function()
{
	var cs=Costume();
	cs.SetItem(0,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,15,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,15,7,7,15,-1,15,15,15,15,15,15,15,15,-1,-1,-1
	,7,7,7,15,-1,7,7,7,7,7,7,7,7,-1,-1,-1
	,-1,7,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(1,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,7,15,-1
	,-1,-1,-1,15,15,15,15,15,15,15,15,-1,7,7,7,15
	,-1,-1,-1,7,7,7,7,7,7,7,7,-1,7,7,7,7
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,7,7,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(2,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,15,7,7,15,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,15,7,7,7,7,15,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,15,7,7,7,7,7,7,15,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,7,-1,15,15,15,15,15,15,15,15,15,15,15,15,-1,7
	,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7
	,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7
	,-1,15,15,15,15,15,15,15,15,15,15,15,15,15,15,-1
	]));
	cs.SetItem(3,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,15,15,15,15,15,15,15,15,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,7,7,7,7,7,7,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,7,7,7,7,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,7,-1,15,15,15,15,15,15,15,15,15,15,15,15,-1,7
	,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7
	,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7
	,-1,15,15,15,15,15,15,15,15,15,15,15,15,15,15,-1
	]));
	cs.SetItem(4,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,15,15,15,15,15,15,15,15,15,15,15,-1
	,-1,-1,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1
	,-1,15,15,15,15,15,15,15,15,15,15,15,-1,-1,15,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,15,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,15,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,15,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,15,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,15,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,15,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,7,7,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1
	,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1
	,-1,7,7,7,7,7,7,7,7,7,7,7,-1,-1,-1,-1
	]));
	cs.SetItem(5,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,15,15,15,15,15,15,15,15,15,-1,-1,-1
	,-1,-1,-1,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1
	,-1,-1,15,-1,-1,15,15,15,15,15,15,15,-1,-1,15,-1
	,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,-1
	,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,7,-1,-1,15,15,15,15,15,15,15,15,15,15,15
	,-1,-1,7,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,7,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,7,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,7,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,7,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,7,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,7,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,7,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,7,7,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,15
	,-1,-1,-1,-1,-1,7,7,7,7,7,7,7,7,7,7,7
	]));
	cs.SetItem(6,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,15,15,15,15,15,15,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,15,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,-1,15,7,7,-1,-1,-1,-1,7,7,15,-1,-1
	,-1,-1,-1,7,7,7,-1,-1,-1,-1,-1,-1,7,7,15,-1
	,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1,-2,7,15,-1
	,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1,-2,7,15,-1
	,15,15,15,7,7,15,15,15,-1,-1,-1,-1,-2,7,15,-1
	,-1,7,7,7,7,7,7,-1,-1,-1,-1,-1,-2,7,15,-1
	,-1,-1,7,7,7,7,-1,-1,-1,-1,-1,-1,-2,7,15,-1
	,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1,15,7,7,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,7,7,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,15,15,15,7,7,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,7,7,7,7,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(7,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,15,15,15,15,15,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,15,15,7,7,7,7,7,15,-1,-1,-1,-1,-1
	,-1,-1,15,7,7,-1,-1,-1,-1,7,7,15,-1,-1,-1,-1
	,-1,15,7,7,-1,-1,-1,-1,-1,-1,7,7,15,-1,-1,-1
	,-1,7,7,-1,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1
	,-1,7,15,-1,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1
	,-1,7,15,-1,-1,-1,-1,-1,15,15,15,7,7,15,15,15
	,-1,7,15,-1,-1,-1,-1,-1,-1,7,7,7,7,7,7,-1
	,-1,7,15,-1,-1,-1,-1,-1,-1,-1,7,7,7,7,-1,-1
	,-1,7,7,15,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1
	,-1,-1,7,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,7,7,15,15,15,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,7,7,7,7,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(8,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,15,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1
	,-1,-1,15,15,-1,-1,-1,7,7,-1,-1,-1,7,15,-1,-1
	,-1,15,7,15,-1,-1,-1,-1,-1,-1,-1,-1,7,7,15,-1
	,15,7,7,15,-1,15,15,15,15,15,15,-1,7,7,7,15
	,7,7,7,15,-1,7,7,7,7,7,15,-1,7,7,7,7
	,-1,7,7,15,-1,-1,-1,-1,-1,-1,-1,-1,7,7,7,-1
	,-1,-1,7,15,-1,-1,-1,7,7,-1,-1,-1,7,7,-1,-1
	,-1,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,7,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(9,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,15,7,7,15,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,15,7,7,7,7,15,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,15,7,7,7,7,7,7,15,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,7,-1,7,-1,7,-1,7,15,-1,7,-1,7,-1,7,-1
	,-1,7,-1,7,-1,7,-1,7,15,-1,7,-1,7,-1,7,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,15,15,15,15,15,15,15,15,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,7,7,7,7,7,7,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,7,7,7,7,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(10,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,15,15,15,15,7,7,15,15,15,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,7,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,15,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(11,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,15,15,15,15,15,15,15,15,15,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,7,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(12,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-2,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,15,15,15,15,15,15,15,15,15,15,15,15,15,15,-1
	,15,7,7,7,7,7,7,7,7,7,7,7,7,7,7,15
	,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,15
	,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,15
	,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,15
	,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,15
	,7,15,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1,-1,7,15
	,7,15,-1,-1,7,7,15,15,-1,-1,-1,-1,-1,-1,7,15
	,7,7,15,-1,7,7,7,7,15,15,-1,15,15,15,7,7
	,-1,7,7,-1,7,7,7,7,7,7,-1,7,7,7,7,-1
	,-1,-1,-1,-1,7,7,7,7,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(13,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1
	,-1,-1,-1,-2,-2,-2,-1,-1,15,15,7,7,-1,-1,-1,-1
	,-1,15,15,15,15,-1,15,15,7,7,7,7,-1,15,15,-1
	,15,7,7,7,7,-1,7,7,7,7,7,7,-1,7,7,15
	,7,15,-1,-1,-1,-1,-1,-1,7,7,7,7,-1,-1,7,15
	,7,15,-1,-1,-1,-1,-1,-1,-1,-1,7,7,-1,-1,7,15
	,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,15
	,7,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,15
	,7,15,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1,-1,7,15
	,7,15,-1,-1,7,7,15,15,-1,-1,-1,-1,-1,-1,7,15
	,7,7,15,-1,7,7,7,7,15,15,-1,15,15,15,7,7
	,-1,7,7,-1,7,7,7,7,7,7,-1,7,7,7,7,-1
	,-1,-1,-1,-1,7,7,7,7,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,7,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));
	cs.SetItem(14,
	Bitmap(16,16).PixelsFromArray([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,15,15,15,15,15,15,15,15,15,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,15,-1,-1,-1
	,-1,-1,-1,7,7,7,7,7,7,7,7,7,7,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
	]));

	return cs;
}

ImportBtn = function()
{
	bitmaps = new Array();
	var size =0;
	var incode = document.getElementById('ImportCode');
	var code = incode.value;
	var pos = seekPattern(code,'SetItem',0);
	var frame = 0;
	if (pos != -1 )
	{
		pos = seekPattern(code,'(',pos+7);
		frame = seekNumber(code,pos+1);
	}
	pos = seekPattern(code,'Bitmap',pos);
	pos = seekPattern(code,'(',pos+6);
	
	var nextbitmappos = seekPattern(code,'Bitmap',pos+1);
	var finished = false;
	while (!finished)
	{
		if(frame == 0)
		{
			size = seekNumber(code,pos+1);
			if ( size < 1 ) size = 1;
			if ( size > 60 ) size = 60;
		}
		else
			seekNumber(code,pos+1);
		pos = seekPattern(code,',',pos+1);
		seekNumber(code,pos+1);

		pos = seekPattern(code,'PixelsFromArray',pos+1);
		pos = seekPattern(code,'(',pos+1);
		pos = seekPattern(code,'[',pos+1);
		
		
		// now read in all the pixel data 
		var pixels = new Array();
		if ( pos != -1 )
		{
			var n = 0;
			for ( n = 0; n < size*size; n++)
			{
				var num = seekNumber(code,pos+1);
				if(pos == -1) break;
				if(nextbitmappos != -1 && pos > nextbitmappos ) break;
				
				pixels[n] = num;
				pos = seekPattern(code,',',pos+1);
			}

			// if there are any pixels not created then create them now
			if ( n < size*size)
			{
				for ( n=n; n < size*size; n++ )
				{
					pixels[n] = -1;
				}
			}
		}
		bm = Bitmap(size,size);
		bm.SetPixelArray(pixels);
		bitmaps[frame] = bm;
		
		pos = nextbitmappos;
		if (pos == -1)
			finished = true;
		else
		{
			pos = seekPattern(code,'(',pos+6);
			nextbitmappos = seekPattern(code,'Bitmap',pos+1);
			frame++;
		}
	}

	currentFrame = 0;
	spriteSize = size;

	canvasSize = Math.floor(240/spriteSize)*spriteSize;
	canvasOffset = Math.floor((240 - canvasSize)/2);
	pixelSize = Math.floor(canvasSize / spriteSize);

	preview = Preview();
	canvas = Canvas();
}

seekPattern = function(source,match,startPos)
{
	return source.indexOf(match,startPos);
}

seekNumber = function(source,startPos)
{
	return parseInt(source.substring(startPos).match(/^\s*(\+|-)?\d+/));
}

ExportClose = function()
{
	var exportWindow = document.getElementById('CodeWindow');
	exportWindow.className = "hide";
}

ImportClose = function()
{
	var importWindow = document.getElementById('ImportCodeWindow');
	importWindow.className = "hide";
}
GameEngine16Colour = function(canvasIn,updateFunction,drawFunction)
{
	"use strict";
	var obj = {};

	if ( typeof(updateFunction) != "function" ) 
		updateFunction = function(){};

	if ( typeof(drawFunction) != "function" ) 
		drawFunction = function(){};
	
	var CANVAS_WIDTH = 320; //320;
	var CANVAS_HEIGHT = 240; // 240;

	var FPS = 30;
	var updateRate = Math.floor(1000 / FPS);

	var canvas = canvasIn;
	
	var colours = new Array();

	var charSet = {};
		
	obj.mousePos = new Vector();
	obj.mouseClicked = false;
	obj.mouseTouchFire = false;
	obj.mouseUnclicked = false;
	obj.mouseDown = false;
	
	obj.CanvasWidth = CANVAS_WIDTH;
	obj.CanvasHeight = CANVAS_HEIGHT;
	
	canvas.width = CANVAS_WIDTH;
	canvas.height = CANVAS_HEIGHT;

	obj.sprites = new Array(); 	// key = spritename, value = layer
	obj.layers = new Array();	// key = spritename, value = sprite
	
	obj.collisionRules = new Array();

	var ctx = null;
	if(canvas.getContext )
	{
		ctx = canvas.getContext('2d');
	}

	if (ctx === null )
	{
		return null;
	}
	
	var screenImageData = ctx.getImageData(0,0,CANVAS_WIDTH,CANVAS_HEIGHT);

	for ( var pixel = 0; pixel < CANVAS_WIDTH*CANVAS_HEIGHT; pixel+=1)
	{
		screenImageData.data[pixel*4+3] = 255;
	}

	var screenBitmap = Bitmap(CANVAS_WIDTH,CANVAS_HEIGHT);
	screenBitmap.DrawRect(0,0,CANVAS_WIDTH,CANVAS_HEIGHT,0);
	
	var tempScreenBitmap= Bitmap(CANVAS_WIDTH,CANVAS_HEIGHT);
	var prevScreenBitmap= Bitmap(CANVAS_WIDTH,CANVAS_HEIGHT);

	function InitColours() 
	{
		colours[0] = Colour(0,0,0);
		colours[1] = Colour(128,0,0);
		colours[2] = Colour(0,128,0);
		colours[3] = Colour(0,0,128);
		colours[4] = Colour(128,128,0);
		colours[5] = Colour(128,0,128);
		colours[6] = Colour(0,128,128);
		colours[7] = Colour(128,128,128);

		colours[8] = Colour(64,64,64);
		colours[9] = Colour(255,0,0);
		colours[10] = Colour(0,255,0);
		colours[11] = Colour(0,0,255);
		colours[12] = Colour(255,255,0);
		colours[13] = Colour(255,0,255);
		colours[14] = Colour(0,255,255);
		colours[15] = Colour(255,255,255);
		
		// experimental colours
		// mid black and dark primary
		colours[16] = TertiaryMix(colours[7],colours[7],32);
		colours[17] = TertiaryMix(colours[1],colours[1],64);
		colours[18] = TertiaryMix(colours[2],colours[2],64);
		colours[19] = TertiaryMix(colours[3],colours[3],64);
		// secondary
		colours[20] = TertiaryMix(colours[4],colours[4],64);
		colours[21] = TertiaryMix(colours[5],colours[5],64);
		colours[22] = TertiaryMix(colours[6],colours[6],64);

		// tertiary colours
		colours[23] = TertiaryMix(colours[1],colours[4],128);
		colours[24] = TertiaryMix(colours[1],colours[5],128);
//		colours[18] = TertiaryMix(colours[1],colours[6],128);

		colours[25] = TertiaryMix(colours[2],colours[4],128);
//		colours[20] = TertiaryMix(colours[2],colours[5],128);
		colours[26] = TertiaryMix(colours[2],colours[6],128);

//		colours[22] = TertiaryMix(colours[3],colours[4],128);
		colours[27] = TertiaryMix(colours[3],colours[5],128);
		colours[28] = TertiaryMix(colours[3],colours[6],128);

		colours[29] = TertiaryMix(colours[4],colours[5],128);
		colours[30] = TertiaryMix(colours[4],colours[6],128);

//		colours[28] = TertiaryMix(colours[5],colours[4],128);
//		colours[29] = TertiaryMix(colours[5],colours[6],128);

//		colours[30] = TertiaryMix(colours[6],colours[4],128);
		colours[31] = TertiaryMix(colours[6],colours[5],128);

		// bright
		colours[32] = TertiaryMix(colours[15],colours[15],192);
		colours[33] = TertiaryMix(colours[9],colours[9],192);
		colours[34] = TertiaryMix(colours[10],colours[10],192);
		colours[35] = TertiaryMix(colours[11],colours[11],192);
		// secondary
		colours[36] = TertiaryMix(colours[12],colours[12],192);
		colours[37] = TertiaryMix(colours[13],colours[13],192);
		colours[38] = TertiaryMix(colours[14],colours[14],192);

//		colours[31] = TertiaryMix(colours[7],colours[7],96);

		colours[39] = TertiaryMix(colours[9],colours[12],255);
		colours[40] = TertiaryMix(colours[9],colours[13],255);
//		colours[34] = TertiaryMix(colours[9],colours[14],255);

		colours[41] = TertiaryMix(colours[10],colours[12],255);
//		colours[36] = TertiaryMix(colours[10],colours[13],255);
		colours[42] = TertiaryMix(colours[10],colours[14],255);

//		colours[38] = TertiaryMix(colours[11],colours[12],255);
		colours[43] = TertiaryMix(colours[11],colours[13],255);
		colours[44] = TertiaryMix(colours[11],colours[14],255);

		colours[45] = TertiaryMix(colours[12],colours[13],255);
		colours[46] = TertiaryMix(colours[12],colours[14],255);

//		colours[44] = TertiaryMix(colours[13],colours[12],255);
//		colours[45] = TertiaryMix(colours[13],colours[14],255);

//		colours[46] = TertiaryMix(colours[14],colours[12],255);
		colours[47] = TertiaryMix(colours[14],colours[13],255);

//		colours[47] = TertiaryMix(colours[15],colours[15],192);

		function TertiaryMix (col1,col2,maxValue)
		{
			var red = col1.red + col2.red;
			var green = col1.green + col2.green;
			var blue = col1.blue + col2.blue;
			
			var br = red;
			if(green > br) br = green;
			if(blue > br) br = blue;
			
			red = Math.floor(red / br * maxValue);
			green = Math.floor(green / br * maxValue);
			blue = Math.floor(blue / br * maxValue);
			
			return Colour(red,green,blue);
		}
	}	

	InitColours();
	
	function InitCharSet()
	{
		charSet = CharSet(8,8);

		charSet.SetChar("\\",[
			"*       ",
			" *      ", 
			"  *     ", 
			"   *    ", 
			"    *   ", 
			"     *  ", 
			"      * ", 
			"        "]);
			
		charSet.SetChar("\"",[
			"  * *   ",
			"  * *   ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        "]);
			
		charSet.SetChar("#",[
			" *   *  ",
			"******* ", 
			" *   *  ", 
			" *   *  ", 
			" *   *  ", 
			"******* ", 
			" *   *  ", 
			"        "]);
			
		charSet.SetChar("$",[
			"   *    ",
			" *****  ", 
			"*  *    ", 
			" *****  ", 
			"   *  * ", 
			" *****  ", 
			"   *    ", 
			"        "]);

		charSet.SetChar("%",[
			" *    * ",
			"* *  *  ", 
			" *  *   ", 
			"   *    ", 
			"  *  *  ", 
			" *  * * ", 
			"*    *  ", 
			"        "]);

		charSet.SetChar("&",[
			"  ***   ",
			" *   *  ", 
			"  * *   ", 
			"  **    ", 
			" *  *   ", 
			"*    *  ", 
			" **** * ", 
			"        "]);

		charSet.SetChar("'",[
			"   *    ",
			"   *    ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        "]);
			
		charSet.SetChar("(",[
			"   *    ",
			"  *     ", 
			" *      ", 
			" *      ", 
			" *      ", 
			"  *     ", 
			"   *    ", 
			"        "]);
			
		charSet.SetChar(")",[
			"   *    ",
			"    *   ", 
			"     *  ", 
			"     *  ", 
			"     *  ", 
			"    *   ", 
			"   *    ", 
			"        "]);
			
		charSet.SetChar("*",[
			"        ",
			"*   *   ", 
			" * *    ", 
			"  *     ", 
			" * *    ", 
			"*   *   ", 
			"        ", 
			"        "]);
			
		charSet.SetChar("+",[
			"        ",
			"   *    ", 
			"   *    ", 
			" *****  ", 
			"   *    ", 
			"   *    ", 
			"        ", 
			"        "]);
			
		charSet.SetChar(",",[
			"        ",
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"   *    ", 
			"   *    ", 
			"  *     "]);
			
		charSet.SetChar("-",[
			"        ",
			"        ", 
			"        ", 
			" *****  ", 
			"        ", 
			"        ", 
			"        ", 
			"        "]);
			
		charSet.SetChar(".",[
			"        ",
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"   *    ", 
			"        "]);
			
		charSet.SetChar("/",[
			"      * ",
			"     *  ", 
			"    *   ", 
			"   *    ", 
			"  *     ", 
			" *      ", 
			"*       ", 
			"        "]);
			
		charSet.SetChar("0",[
			" *****  ",
			"*     * ", 
			"*   * * ", 
			"*  *  *", 
			"* *   * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("1",[
			"   *    ",
			"  **    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"  ***   ", 
			"        "]);

		charSet.SetChar("2",[
			" *****  ",
			"*     * ", 
			"     *  ", 
			"    *   ", 
			"  **    ", 
			" *      ", 
			"******* ", 
			"        "]);

		charSet.SetChar("3",[
			" *****  ",
			"*     * ", 
			"      * ", 
			"  ****  ", 
			"      * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("4",[
			" *      ",
			" *      ", 
			" *      ", 
			" *  *   ", 
			" ****** ", 
			"    *   ", 
			"    *   ", 
			"        "]);

		charSet.SetChar("5",[
			"******* ",
			"*       ", 
			"*       ", 
			"******  ", 
			"      * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("6",[
			" *****  ",
			"*     * ", 
			"*       ", 
			"******  ", 
			"*     * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("7",[
			"******* ",
			"      * ", 
			"     *  ", 
			"     *  ", 
			"    *   ", 
			"    *   ", 
			"    *   ", 
			"        "]);

		charSet.SetChar("8",[
			" *****  ",
			"*     * ", 
			"*     * ", 
			" *****  ", 
			"*     * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("9",[
			" *****  ",
			"*     * ", 
			"*     * ", 
			" ****** ", 
			"      * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar(":",[
			"        ",
			"        ", 
			"   *    ", 
			"        ", 
			"   *    ", 
			"        ", 
			"        ", 
			"        "]);

		charSet.SetChar(";",[
			"        ",
			"        ", 
			"   *    ", 
			"        ", 
			"   *    ", 
			"  *     ", 
			"        ", 
			"        "]);

		charSet.SetChar("<",[
			"        ",
			"    **  ", 
			"  **    ", 
			" *      ", 
			"  **    ", 
			"    **  ", 
			"        ", 
			"        "]);

		charSet.SetChar("=",[
			"        ",
			"        ", 
			" *****  ", 
			"        ", 
			" *****  ", 
			"        ", 
			"        ", 
			"        "]);

		charSet.SetChar(">",[
			"        ",
			" **     ", 
			"   **   ", 
			"     *  ", 
			"   **   ", 
			" **     ", 
			"        ", 
			"        "]);
			
		charSet.SetChar("A",[
			" *****  ",
			"*     * ", 
			"*     * ", 
			"******* ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"        "]);

		charSet.SetChar("B",[
			"******  ",
			"*     * ", 
			"*     * ", 
			"******* ", 
			"*     * ", 
			"*     * ", 
			"******  ", 
			"        "]);

		charSet.SetChar("C",[
			" *****  ",
			"*     * ", 
			"*       ", 
			"*       ", 
			"*       ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("D",[
			"******  ",
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"******  ", 
			"        "]);

		charSet.SetChar("E",[
			"******* ",
			"*       ", 
			"*       ", 
			"*****   ", 
			"*       ", 
			"*       ", 
			"******* ", 
			"        "]);

		charSet.SetChar("F",[
			"******* ",
			"*       ", 
			"*       ", 
			"*****   ", 
			"*       ", 
			"*       ", 
			"*       ", 
			"        "]);

		charSet.SetChar("G",[
			" *****  ",
			"*     * ", 
			"*       ", 
			"*  **** ", 
			"*     * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("H",[
			"*     * ",
			"*     * ", 
			"*     * ", 
			"******* ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"        "]);

		charSet.SetChar("I",[
			"  ***   ",
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"  ***   ", 
			"        "]);

		charSet.SetChar("J",[
			"******* ",
			"      * ", 
			"      * ", 
			"      * ", 
			"*     * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("K",[
			"*     * ",
			"*   **  ", 
			"* **    ", 
			"**      ", 
			"* **    ", 
			"*   **  ", 
			"*     * ", 
			"        "]);

		charSet.SetChar("L",[
			"*       ",
			"*       ", 
			"*       ", 
			"*       ", 
			"*       ", 
			"*       ", 
			"******* ", 
			"        "]);

		charSet.SetChar("M",[
			"*     * ",
			"**   ** ", 
			"* * * * ", 
			"*  *  * ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"        "]);

		charSet.SetChar("N",[
			"*     * ",
			"**    * ", 
			"* *   * ", 
			"*  *  * ", 
			"*   * * ", 
			"*    ** ", 
			"*     * ", 
			"        "]);

		charSet.SetChar("O",[
			" *****  ",
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("P",[
			" *****  ",
			"*     * ", 
			"*     * ", 
			"******  ", 
			"*       ", 
			"*       ", 
			"*       ", 
			"        "]);

		charSet.SetChar("Q",[
			" *****  ",
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*   * * ", 
			"**   *  ", 
			" **** * ", 
			"        "]);

		charSet.SetChar("R",[
			"******  ",
			"*     * ", 
			"*     * ", 
			"******  ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"        "]);

		charSet.SetChar("S",[
			" *****  ",
			"*     * ", 
			"*       ", 
			" *****  ", 
			"      * ", 
			"*     * ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("T",[
			"******* ",
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"        "]);

		charSet.SetChar("U",[
			"*     * ",
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*     * ", 
			" ****** "]);

		charSet.SetChar("V",[
			"*     * ",
			"*     * ", 
			" *   *  ", 
			" *   *  ", 
			"  * *   ", 
			"  * *   ", 
			"   *    ", 
			"        "]);

		charSet.SetChar("W",[
			"*     * ",
			"*     * ", 
			"*     * ", 
			"*     * ", 
			"*  *  * ", 
			"* * * * ", 
			"**   ** ", 
			"        "]);

		charSet.SetChar("X",[
			"*     * ",
			" *   *  ", 
			"  * *   ", 
			"   *    ", 
			"  * *   ", 
			" *   *  ", 
			"*     * ", 
			"        "]);

		charSet.SetChar("Y",[
			"*     * ",
			" *   *  ", 
			"  * *   ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"        "]);

		charSet.SetChar("Z",[
			"******* ",
			"     *  ", 
			"    *   ", 
			"   *    ", 
			"  *     ", 
			" *      ", 
			"******* ", 
			"        "]);

	// [\]^_`abcdefg.....z{|}~	
		charSet.SetChar("[",[
			"  ***   ",
			"  *     ", 
			"  *     ", 
			"  *     ", 
			"  *     ", 
			"  *     ", 
			"  ***   ", 
			"        "]);

		charSet.SetChar("\\",[
			"*       ",
			" *      ", 
			"  *     ", 
			"   *    ", 
			"    *   ", 
			"     *  ", 
			"      * ", 
			"        "]);

		charSet.SetChar("]",[
			"  ***   ",
			"    *   ", 
			"    *   ", 
			"    *   ", 
			"    *   ", 
			"    *   ", 
			"  ***   ", 
			"        "]);

		charSet.SetChar("^",[
			"   *    ",
			"  * *   ", 
			" *   *  ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        "]);

		charSet.SetChar("_",[
			"        ",
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"********"]);

		charSet.SetChar("`",[
			"  *     ",
			"   *    ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        ", 
			"        "]);

		charSet.SetChar("a",[
			"        ",
			"        ", 
			" ****   ", 
			"     *  ", 
			" *****  ", 
			"*    *  ", 
			" **** * ", 
			"        "]);

		charSet.SetChar("b",[
			"*       ",
			"*       ", 
			"*****   ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			"*****   ", 
			"        "]);

		charSet.SetChar("c",[
			"        ",
			"        ", 
			" ****   ", 
			"*       ", 
			"*       ", 
			"*       ", 
			" ****   ", 
			"        "]);

		charSet.SetChar("d",[
			"     *  ",
			"     *  ", 
			" *****  ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("e",[
			"        ",
			"        ", 
			" ****   ", 
			"*    *  ", 
			"******  ", 
			"*       ", 
			" ****   ", 
			"        "]);

		charSet.SetChar("f",[
			"  ***   ",
			" *      ", 
			" *      ", 
			"****    ", 
			" *      ", 
			" *      ", 
			" *      ", 
			"        "]);

		charSet.SetChar("g",[
			"        ",
			"        ", 
			" ****   ", 
			"*    *  ", 
			"*    *  ", 
			" *****  ", 
			"     *  ", 
			" ****   "]);

		charSet.SetChar("h",[
			"*       ",
			"*       ", 
			"*       ", 
			"*****   ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			"        "]);

		charSet.SetChar("i",[
			"        ",
			"  *     ", 
			"        ", 
			"  *     ", 
			"  *     ", 
			"  *     ", 
			"  *     ", 
			"        "]);

		charSet.SetChar("j",[
			"        ",
			"     *  ", 
			"        ", 
			"    **  ", 
			"     *  ", 
			"     *  ", 
			"     *  ", 
			" ****   "]);

		charSet.SetChar("k",[
			"*       ",
			"*       ", 
			"*  *    ", 
			"* *     ", 
			"***     ", 
			"*  *    ", 
			"*   *   ", 
			"        "]);

		charSet.SetChar("l",[
			"*       ",
			"*       ", 
			"*       ", 
			"*       ", 
			"*       ", 
			"*       ", 
			" ***    ", 
			"        "]);

		charSet.SetChar("m",[
			"        ",
			"        ", 
			"*** **  ", 
			"*  *  * ", 
			"*  *  * ", 
			"*  *  * ", 
			"*  *  * ", 
			"        "]);

		charSet.SetChar("n",[
			"        ",
			"        ", 
			"*****   ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			"        "]);

		charSet.SetChar("o",[
			"        ",
			"        ", 
			" ****   ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			" ****   ", 
			"        "]);

		charSet.SetChar("p",[
			"        ",
			"        ", 
			"*****   ", 
			"*    *  ", 
			"*    *  ", 
			"*****   ", 
			"*       ", 
			"*       "]);

		charSet.SetChar("q",[
			"        ",
			"        ", 
			" *****  ", 
			"*    *  ", 
			"*    *  ", 
			" *****  ", 
			"     *  ", 
			"     *  "]);

		charSet.SetChar("r",[
			"        ",
			"        ", 
			" ****   ", 
			"*       ", 
			"*       ", 
			"*       ", 
			"*       ", 
			"        "]);

		charSet.SetChar("s",[
			"        ",
			"        ", 
			" ****   ", 
			"*       ", 
			" ****   ", 
			"*    *  ", 
			" ****   ", 
			"        "]);

		charSet.SetChar("t",[
			"        ",
			" *      ", 
			"***     ", 
			" *      ", 
			" *      ", 
			" *      ", 
			"  ***   ", 
			"        "]);

		charSet.SetChar("u",[
			"        ",
			"        ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			" *****  ", 
			"        "]);

		charSet.SetChar("v",[
			"        ",
			"        ", 
			"*    *  ", 
			"*    *  ", 
			" *  *   ", 
			" *  *   ", 
			"  **    ", 
			"        "]);

		charSet.SetChar("w",[
			"        ",
			"        ", 
			"*  *  * ", 
			"*  *  * ", 
			"*  *  * ", 
			"*  *  * ", 
			" ** **  ", 
			"        "]);

		charSet.SetChar("x",[
			"        ",
			"        ", 
			"*    *  ", 
			" *  *   ", 
			"  **    ", 
			" *  *   ", 
			"*    *  ", 
			"        "]);

		charSet.SetChar("y",[
			"        ",
			"        ", 
			"*    *  ", 
			"*    *  ", 
			"*    *  ", 
			" *****  ", 
			"     *  ", 
			" ****   "]);

		charSet.SetChar("z",[
			"        ", 
			"        ", 
			"*****   ", 
			"   *    ", 
			"  *     ", 
			" *      ", 
			"*****   ",
			"        "]);

		charSet.SetChar("{",[
			"    *   ",
			"   *    ", 
			"   *    ", 
			"  *     ", 
			"   *    ", 
			"   *    ", 
			"    *   ", 
			"        "]);

		charSet.SetChar("|",[
			"   *    ",
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"   *    ", 
			"        "]);

		charSet.SetChar("}",[
			"  *     ",
			"   *    ", 
			"   *    ", 
			"    *   ", 
			"   *    ", 
			"   *    ", 
			"  *     ", 
			"        "]);

		charSet.SetChar("~",[
			"        ",
			"        ", 
			"      * ", 
			" *****  ", 
			"*       ", 
			"        ", 
			"        ", 
			"        "]);
	}

	obj.CharSet = function()
	{
		return charSet;
	}
	
	InitCharSet();

	var dwCurrentTime=0;
	var dwLastUpdateTime=(new Date).getTime();
	var dwTimeCarriedOver = 0;
	var dwElapsedTime=0;

	obj.Main = function()
	{
		dwCurrentTime = (new Date).getTime();	
		dwElapsedTime = dwCurrentTime - dwLastUpdateTime + dwTimeCarriedOver;
		if(dwElapsedTime >= updateRate)
		{
			var frames = Math.floor(dwElapsedTime / updateRate );
			dwTimeCarriedOver = dwElapsedTime % updateRate;
			dwLastUpdateTime = dwCurrentTime;
			for ( var f = 0; f < frames; f++)
			{
				updateFunction();
				obj.Update();
				obj.mouseClicked = false;
				obj.mouseUnclicked = false;
				obj.mouseTouchFire = false;
				obj.CheckCollisions();
			}
			drawFunction();
			obj.Draw();
		}
	}

	var timer = Timer(FPS, obj.Main);
	
	obj.Stop = function()
	{
		timer.Stop();
	}
	
	obj.writeToCanvas = function(bitmap)
	{
		var sourceArray = bitmap.GetPixelArray();
		var prevArray = prevScreenBitmap.GetPixelArray();
		var offset = 0;
	
		for ( var p = 0; p < sourceArray.length; p++ )
		{
			if ( sourceArray[p] != prevArray[p])
			{
				prevArray[p] = sourceArray[p];
				var colour = colours[sourceArray[p]];
				screenImageData.data[offset] = colour.red;
				screenImageData.data[offset+1] = colour.green;
				screenImageData.data[offset+2] = colour.blue;
			}
//			else
//			{
//				screenImageData.data[offset] = 0;
//				screenImageData.data[offset+1] = 0;
//				screenImageData.data[offset+2] = 0;
//			}
			offset+=4;
		}
		ctx.putImageData(screenImageData,0,0);
	}

	obj.Update = function()
	{
		for ( var l in obj.layers )
		{
			var currentLayer = obj.layers[l];
			for ( var i in currentLayer )
			{
				var s = currentLayer[i];
				if ( s )
				{
					s.Update(tempScreenBitmap.width, tempScreenBitmap.height);
					if( s.died )
						SpriteDeleteForReal(s.name);
				}
			}
		}
	}

	obj.PortraitMode = function()
	{
		if (CANVAS_WIDTH > CANVAS_HEIGHT )
		{
			var tmp = CANVAS_WIDTH;
			CANVAS_WIDTH = CANVAS_HEIGHT;
			CANVAS_HEIGHT = tmp;

			obj.CanvasWidth = CANVAS_WIDTH;
			obj.CanvasHeight = CANVAS_HEIGHT;
	
			canvas.width = CANVAS_WIDTH;
			canvas.height = CANVAS_HEIGHT;

			screenImageData = ctx.getImageData(0,0,CANVAS_WIDTH,CANVAS_HEIGHT);

			for ( var pixel = 0; pixel < CANVAS_WIDTH*CANVAS_HEIGHT; pixel+=1)
			{
				screenImageData.data[pixel*4+3] = 255;
			}

			screenBitmap = Bitmap(CANVAS_WIDTH,CANVAS_HEIGHT);
			screenBitmap.DrawRect(0,0,CANVAS_WIDTH,CANVAS_HEIGHT,0);
			
			tempScreenBitmap= Bitmap(CANVAS_WIDTH,CANVAS_HEIGHT);
			prevScreenBitmap= Bitmap(CANVAS_WIDTH,CANVAS_HEIGHT);

		}
	}
	
	obj.CheckCollisions = function()
	{
		for ( var r in obj.collisionRules )
		{
			var currentLayer = obj.layers[r];
			CheckCollisionsForLayer(currentLayer, obj.collisionRules[r]);
		}
	}
	
	function CheckCollisionsForLayer(layer, collisionRule)
	{
		for ( var spritePos in layer )
		{
			var sprite = layer[spritePos];
			if ( sprite )
			{
				sprite.collided = false;
				for ( var targetLayer in collisionRule)
				{
					CheckSpriteCollisionWithLayer(sprite, obj.layers[targetLayer]);
				}
			}
		}
	}

	function CheckSpriteCollisionWithLayer(sprite, layer)
	{
		if ( layer )
		{
			for ( var spritePos in layer )
			{
				var targetSprite = layer[spritePos];
				if( sprite.IsCollidedWith(targetSprite.name))
				{
					sprite.collided = true;
					targetSprite.collided = true;
				}
			}
		}
	}

	obj.CountSpritesInLayer=function(layerName)
	{
		var count = 0;

		var layer = obj.layers[layerName];
		
		for ( var spritePos in layer )
		{
			var sprite = layer[spritePos];
			if ( sprite )
			{
				count++;
			}
		}
		return count;
	}

	obj.Draw = function()
	{
		// copy the screenBitmap and place all the sprites on it
		
		// Cloning has been replaced with a permanent temp bitmap and
		// contents just copied over. This seems to yield significant
		// speed improvement in chrome. 
//		var bitmap = screenBitmap.Clone();
		var size = screenBitmap.width * screenBitmap.height;
		var targetArray = tempScreenBitmap.GetPixelArray();
		var sourceArray = screenBitmap.GetPixelArray();
		for (  var p = 0; p < size; p++)
		{
			targetArray[p] = sourceArray[p];
		}

		for ( var l in obj.layers )
		{
			var currentLayer = obj.layers[l];
			for ( var i in currentLayer )
			{
				var spr = currentLayer[i];
				if ( spr )
					tempScreenBitmap.Paste(spr.pos.x,spr.pos.y, spr.bitmap )
//				bitmap.Paste(s.pos.x,s.pos.y, s.bitmap )
			}
		}
		obj.writeToCanvas(tempScreenBitmap);
//		obj.writeToCanvas(bitmap);
	}
		
	obj.DrawPixel = function(pixelX, pixelY,colour)
	{
		screenBitmap.SetPixel(Math.floor(pixelX),Math.floor(pixelY),colour);
	}

	obj.Clear = function(colour)
	{
		screenBitmap.Clear(colour);
	}
	
	obj.DrawLine = function(startX, startY, endX, endY, colour)
	{
		screenBitmap.DrawLine(startX, startY, endX, endY, colour)
	}
	
	obj.DrawRect = function(xPos,yPos,width,height,colour)
	{
		screenBitmap.DrawRect(xPos, yPos, width, height, colour)
	}
	
	obj.DrawCircle = function(xPos,yPos,radius,colour)
	{
		screenBitmap.DrawCircle(xPos,yPos,radius,colour)
	}

	obj.Scroll = function(xMovement,yMovement)
	{
		screenBitmap.Scroll(xMovement,yMovement);
	}
	
	obj.FlipX = function()
	{
		screenBitmap = screenBitmap.FlipX();
	}

	obj.FlipY = function()
	{
		screenBitmap = screenBitmap.FlipY();
	}

	obj.Paste = function(xPos,yPos,bitmap)
	{
		screenBitmap.Paste(xPos,yPos,bitmap);
	}
	
	obj.DefineColour = function(colour,r,g,b)
	{
		colours[colour] = Colour(r,g,b);
	}

	function CleanUpArray(arrayObj)
	{
		var returnArray = new Array();
		
		for ( var i in arrayObj)
		{
			if ( arrayObj[i] != null )
			{
				returnArray[i] = arrayObj[i];
			}
		}
		return returnArray;
	}
	
	function CountItemsInArray(arrayObj)
	{
		var count = 0;
		for ( var i in arrayObj )
		{
			count++;
		}
		
		return count;
	}
	
	obj.SpriteAdd = function(name,sprite, layer)
	{
		obj.SpriteDelete(name);

		obj.sprites[name] = layer;

		if (obj.layers[layer] == null )
		{
			obj.layers[layer] = new Array();
		}

		var newLayer = obj.layers[layer];
		newLayer[name] = sprite;
		sprite.name = name;
	}

	function SpriteDeleteForReal(name)
	{
		var spriteLayer = obj.sprites[name];
		if ( spriteLayer )
		{
			obj.layers[spriteLayer][name] = null;
			obj.layers[spriteLayer] = CleanUpArray(obj.layers[spriteLayer]);
			if ( CountItemsInArray(obj.layers[spriteLayer]) == 0 )
			{
				obj.layers[spriteLayer] = null;
				obj.layers = CleanUpArray(obj.layers);
			}
			obj.sprites[name] = null;
			obj.sprites = CleanUpArray(obj.sprites);
		}
	}

	obj.SpriteDelete=function(name)
	{
		var spriteLayer = obj.sprites[name];
		if ( spriteLayer )
		{
			if ( obj.layers[spriteLayer] )
				obj.layers[spriteLayer][name].died = true;
		}
	}

	obj.DeleteSpritesInLayer=function(spriteLayer)
	{
		if ( spriteLayer )
		{
			if ( obj.layers[spriteLayer] )
			{
				for ( var i in obj.layers[spriteLayer] )
				{
					obj.layers[spriteLayer][i].died = true;
				}
			}
		}
	}

	obj.GetSpritesInLayer = function(spriteLayer)
	{
		if ( spriteLayer )
		{
			if ( obj.layers[spriteLayer] )
			{
				return obj.layers[spriteLayer] 
			}
		}
		return null;
	}

	
/*
	obj.WriteChar = function(char, charset, xPos,yPos,colour)
	{
		screenBitmap.WriteChar(char, charset, xPos,yPos,colour);
	}

	obj.WriteString = function(text,charset, xPos,yPos,colour)
	{
		screenBitmap.WriteString(text,charset, xPos,yPos,colour);
	}
*/
	obj.SpriteGet = function(name)
	{
		var spriteLayer = obj.layers[obj.sprites[name]];
		if ( spriteLayer )
			return spriteLayer[name];
		return null;
	}

	obj.CollisionRuleAdd = function(sourceLayer, targetLayer)
	{
		if ( obj.collisionRules[sourceLayer] == null )
		{
			obj.collisionRules[sourceLayer] = new Array();
		}
		
		if (obj.collisionRules[sourceLayer][targetLayer] == null )
		{
			obj.collisionRules[sourceLayer][targetLayer] = targetLayer;
		}
	}
	
	obj.CollisionRuleDelete = function(sourceLayer, targetLayer)
	{
		if ( obj.collisionRules[sourceLayer] )
		{
			if ( obj.collisionRules[sourceLayer][targetLayer] )
			{
				obj.collisionRules[sourceLayer][targetLayer] = null;
				obj.collisionRules[sourceLayer] = CleanUpArray(obj.collisionRules[sourceLayer]);
			}
			if ( CountItemsInArray(obj.collisionRules[sourceLayer]) == 0 )
			{
				obj.collisionRules[sourceLayer] = null;
				obj.collisionRules = CleanUpArray(obj.collisionRules);
			}
		}
	}

	obj.WriteChar = function(char,xPos,yPos,colour,xbig,ybig)
	{
		charSet.WriteChar(char,screenBitmap,xPos,yPos,colour,xbig,ybig)
	}

	obj.WriteString = function(text,xPos,yPos,colour,xbig,ybig)
	{
		charSet.WriteString(text,screenBitmap,xPos,yPos,colour,xbig,ybig)
	}

	obj.WriteStringCentered=function(text,yPos,colour,xbig,ybig)
	{
		screenBitmap.WriteStringCentered(text,charSet, yPos,colour,xbig,ybig);
	}

	var mouseDownPos = Vector(0,0);
	var mouseUpPos = Vector(0,0);
	obj.mouseSwipe = Vector(0,0);

	function SetMousePos(xp,yp)
	{
		var bbox = canvas.getBoundingClientRect();
		obj.mousePos.x = (xp - bbox.left) * ( canvas.width / bbox.width);
		obj.mousePos.y = (yp - bbox.top) * ( canvas.height / bbox.height);
	}

	canvas.addEventListener("mousemove", function(evt){
		SetMousePos(evt.clientX,evt.clientY);
		evt.preventDefault();
	});

	canvas.addEventListener("touchmove", function(evt){
		SetMousePos(evt.targetTouches[0].pageX,evt.targetTouches[0].pageY);
		evt.preventDefault();
	});

	canvas.addEventListener("mousedown", function(evt){
		obj.mouseClicked = true;
		obj.mouseDown = true;
		mouseDownPos.x = obj.mousePos.x;
		mouseDownPos.y = obj.mousePos.y;
		evt.preventDefault();
	});

	canvas.addEventListener("touchstart", function(evt){
		SetMousePos(evt.targetTouches[0].pageX,evt.targetTouches[0].pageY);
		obj.mouseClicked = true;
		obj.mouseDown = true;
		mouseDownPos.x = obj.mousePos.x;
		mouseDownPos.y = obj.mousePos.y;
		if ( evt.targetTouches > 1 )
			obj.mouseTouchFire = true;
		evt.preventDefault();
	});

	canvas.addEventListener("mouseup", function(evt){
		obj.mouseDown = false;
		obj.mouseUnclicked = true;
		mouseUpPos.x = obj.mousePos.x;
		mouseUpPos.y = obj.mousePos.y;
		obj.mouseSwipe.x = mouseUpPos.x - mouseDownPos.x; 
		obj.mouseSwipe.y = mouseUpPos.y - mouseDownPos.y; 
		evt.preventDefault();
	});

	canvas.addEventListener("touchend", function(evt){
		obj.mouseDown = false;
		obj.mouseUnclicked = true;
		mouseUpPos.x = obj.mousePos.x;
		mouseUpPos.y = obj.mousePos.y;
		obj.mouseSwipe.x = mouseUpPos.x - mouseDownPos.x; 
		obj.mouseSwipe.y = mouseUpPos.y - mouseDownPos.y; 
		evt.preventDefault();
	});

	var tiltable = false;
	obj.tiltX = null;
	obj.tiltY = null;
	obj.tiltZ = null;

	var tiltXBase = 0;
	var tiltYBase = 0;
	var tiltZBase = 0;
	
	obj.Tilt=function(values)
	{
		obj.tiltX = values[0];
		obj.tiltY = values[1];
		obj.tiltZ = values[2];
		if ( tiltable == false && obj.tiltX != null )
		{
			tiltable = true;
			obj.TiltCalibrate();
		}
	}

	obj.TiltCalibrate = function()
	{
		tiltXBase = obj.tiltX;
		tiltYBase = obj.tiltY;
		tiltZBase = obj.tiltZ;
	}
	
	obj.Tiltable = function()
	{
		return tiltable;
	}

	obj.GetTiltX=function()
	{
		 var upsidedown = 1;
		 if(obj.tiltZ > 0 )
			upsidedown = -1;
		if ( window.innerWidth < window.innerHeight )
			return (obj.tiltX-tiltXBase);
		else
			return ( obj.tiltY - tiltYBase )*upsidedown;
	}
	
	// Tilt events
	if (window.DeviceOrientationEvent) 
	{
		window.addEventListener("deviceorientation", function () {
        obj.Tilt([event.gamma,event.beta, event.gamma]);
		}, true);
	}

	// keyboard handler
	var keycodes = [];
	
	obj.GetKeyState=function(keycode)
	{
		return keycodes[keycode];
	}
	
	document.addEventListener("keydown", function(evt){
		keycodes[evt.keyCode] = true;
	});

	document.addEventListener("keyup", function(evt){
		keycodes[evt.keyCode] = false;
	});

	obj.KEY_ENTER = 13;

	obj.KEY_ESCAPE = 27;

	obj.KEY_SPACE = 32;
	
	obj.KEY_LEFT = 37;
	obj.KEY_UP = 38;
	obj.KEY_RIGHT = 39;
	obj.KEY_DOWN = 40;

	obj.KEY_0 = 48;
	obj.KEY_1 = 49;
	obj.KEY_2 = 50;
	obj.KEY_3 = 51;
	obj.KEY_4 = 52;
	obj.KEY_5 = 53;
	obj.KEY_6 = 54;
	obj.KEY_7 = 55;
	obj.KEY_8 = 56;
	obj.KEY_9 = 57;

	obj.KEY_A = 65;
	obj.KEY_B = 66;
	obj.KEY_C = 67;
	obj.KEY_D = 68;
	obj.KEY_E = 69;
	obj.KEY_F = 70;
	obj.KEY_G = 71;
	obj.KEY_H = 72;
	obj.KEY_I = 73;
	obj.KEY_J = 74;
	obj.KEY_K = 75;
	obj.KEY_L = 76;
	obj.KEY_M = 77;
	obj.KEY_N = 78;
	obj.KEY_O = 79;
	obj.KEY_P = 80;
	obj.KEY_Q = 81;
	obj.KEY_R = 82;
	obj.KEY_S = 83;
	obj.KEY_T = 84;
	obj.KEY_U = 85;
	obj.KEY_V = 86;
	obj.KEY_W = 87;
	obj.KEY_X = 88;
	obj.KEY_Y = 89;
	obj.KEY_Z = 90;
	
	return obj;
}

Timer = function(fps,callFunction)
{
	var obj = {}
	
	var fps = fps;
	var callFunction = callFunction

	var timerId = setInterval ( callFunction, Math.floor(1000/fps));
	
	obj.Stop = function()
	{
		clearInterval(timerId);
	}
	
	return obj;
}

Colour = function(red,green,blue)
{
	obj = {}
	obj.red = red;
	obj.green = green;
	obj.blue = blue;
	
	return obj;
}

var BaseBitmap = {};

Bitmap = function(width,height)
{
	var obj = Object.create(BaseBitmap);
	obj.width = width;
	obj.height = height;
	
	var pixels = new Array()
	var scrollXFraction = 0.0;
	var scrollYFraction = 0.0;
	
	obj.GetPixelArray = function ()
	{
		return pixels;
	}
	
	obj.SetPixelArray = function (newArray)
	{
		pixels = newArray;
	}
	
	obj.GetPixel = function (xpos, ypos)
	{
		if (xpos >= 0 && xpos < obj.width && ypos >= 0 && ypos < obj.height)
		{
			return pixels[ypos*width+xpos];
		}
		return 0;
	}
	
	obj.SetPixel = function (xpos,ypos,colour)
	{
		if (xpos >= 0 && xpos < obj.width && ypos >= 0 && ypos < obj.height)
		{
			pixels[Math.floor(ypos)*width+Math.floor(xpos)] = colour;
		}
	}

	obj.Clear = function (colour)
	{
		for ( var ypos = 0; ypos < obj.height; ypos++)
		{
			for ( var xpos = 0; xpos < obj.width; xpos++)
			{
				obj.SetPixel(xpos,ypos,colour);
			}
		}
	}

	obj.PixelsFromArray = function(pixelsIn)
	{
		var minPixels = Math.min(obj.width*obj.height,pixelsIn.length);
		
		for(var p = 0; p < minPixels; p++)
		{
			pixels[p] = pixelsIn[p];
		}
		return obj;
	}
	
	obj.DrawLine = function(startX, startY, endX, endY, colour)
	{
		var xLen = endX - startX;
		var yLen = endY - startY;
		var maxPoints = Math.max(Math.abs(xLen), Math.abs(yLen))
		
		var xDisp = xLen / maxPoints;
		var yDisp = yLen / maxPoints;
		
		for ( var p = 0; p <= maxPoints; p++)
		{
			obj.SetPixel(startX + p*xDisp+0.5, startY + p*yDisp+0.5, colour)
		}
	}
	
	obj.DrawRect = function(xPos,yPos,width,height,colour)
	{
		for(var yDisp = 0; yDisp < height; yDisp++ )
		{
			obj.DrawLine(xPos, yPos+yDisp, xPos+width-1, yPos+yDisp,colour)
		}
	}

	obj.DrawCircle = function(xPos,yPos,radius,colour)
	{
		var radiusSquared = radius * radius;
		var xOff;
		
		for( var yOff = 0.0; yOff < radius; yOff+= 0.5)
		{
			xOff = Math.sqrt(radiusSquared-(yOff*yOff));
			obj.DrawLine(xPos-xOff+.5,yPos+yOff+.5,xPos+xOff+.5,yPos+yOff,colour)
			obj.DrawLine(xPos-xOff+.5,yPos-yOff+.5,xPos+xOff+.5,yPos-yOff,colour)
		}
	}

	obj.Scroll = function(xMovement,yMovement)
	{
		scrollXFraction += xMovement;
		scrollYFraction += yMovement;
	
		var xMove = Math.round(scrollXFraction);
		var yMove = Math.round(scrollYFraction);

		if(xMove == 0 && yMove == 0)
		{
			return;
		}

		scrollXFraction -= xMove;
		scrollYFraction -= yMove;

		var newPixels = new Array();

		var targetXPos = xMove;
		if(targetXPos < 0)
		{
			targetXPos += obj.width;
		}
		
		var targetYPos = yMove
		if(targetYPos < 0)
		{
			targetYPos += obj.height;
		}

		for(var yPos = 0; yPos < obj.height; yPos++)
		{
			for(var xPos = 0; xPos < obj.width; xPos++)
			{	
				newPixels[yPos*obj.width+xPos] = pixels[targetYPos*obj.width+targetXPos];
				targetXPos += 1
				if(targetXPos >= obj.width)
				{
					targetXPos -= obj.width;
				}
			}
			targetYPos += 1
			if(targetYPos >= obj.height)
			{
				targetYPos -= obj.height;
			}
		}

		pixels = newPixels;
	}
	
	// Not ready for relacing scroll function yet. Does not wrap pixels.
	obj.ScrollNew = function(xMovement,yMovement)
	{
		scrollXFraction -= xMovement;
		scrollYFraction -= yMovement;
	
		var xMove = Math.round(scrollXFraction);
		var yMove = Math.round(scrollYFraction);

		if(xMove == 0 && yMove == 0)
		{
			return;
		}

		scrollXFraction -= xMove;
		scrollYFraction -= yMove;

		var newBitmap = obj.Clone();

		obj.Clear(-1);
		
		var targetXPos = xMove;
		if(targetXPos < 0)
		{
			targetXPos += obj.width;
		}
		
		var targetYPos = yMove
		if(targetYPos < 0)
		{
			targetYPos += obj.height;
		}

		obj.Paste(xMove,yMove,newBitmap);
		if(targetYPos > 0 )
			obj.Paste(xMove,yMove-obj.height,newBitmap);
		if(targetYPos < 0 )
		obj.Paste(xMove,yMove+obj.height,newBitmap);
		
//		obj.Paste(0,0,newBitmap);
	}
	
	obj.FlipX = function ()
	{
		var newBitmap = Bitmap(obj.width,obj.height);

		for(var yPos = 0; yPos < obj.height; yPos++)
		{
			for(var xPos = 0; xPos < obj.width; xPos++)
			{
				newBitmap.SetPixel(xPos,yPos,obj.GetPixel(obj.width-1-xPos,yPos));
			}
		}
		return newBitmap;
	}
	
	obj.FlipY = function()
	{
		var newBitmap = Bitmap(obj.width,obj.height);

		for(var yPos = 0; yPos < obj.height; yPos++)
		{
			for(var xPos = 0; xPos < obj.width; xPos++)
			{
				newBitmap.SetPixel(xPos,yPos,obj.GetPixel(xPos,obj.height-1-yPos));
			}
		}
		return newBitmap;
	}
	
	obj.RotateRight = function()
	{
		var newBitmap = Bitmap(obj.width,obj.height);

		for(var yPos = 0; yPos < obj.height; yPos++)
		{
			for(var xPos = 0; xPos < obj.width; xPos++)
			{
				newBitmap.SetPixel(yPos,xPos,obj.GetPixel(xPos,obj.height-1-yPos));
			}
		}
		return newBitmap;
	}
	
	obj.RotateLeft = function()
	{
		var newBitmap = Bitmap(obj.width,obj.height);

		for(var yPos = 0; yPos < obj.height; yPos++)
		{
			for(var xPos = 0; xPos < obj.width; xPos++)
			{
				newBitmap.SetPixel(yPos,xPos,obj.GetPixel(obj.width-1-xPos,yPos));
			}
		}
		return newBitmap;
	}
	
	obj.Clone = function()
	{
		var newBitmap = Bitmap(obj.width,obj.height);

		newBitmap.SetPixelArray([].concat(pixels));
		
//	for(var yPos = 0; yPos < obj.height; yPos++)
//	{
//		for(var xPos = 0; xPos < obj.width; xPos++)
//		{
//			newBitmap.SetPixel(xPos,yPos,obj.GetPixel(xPos,yPos));
//		}
//	}
		return newBitmap;
	}
	
	obj.Paste = function(xp,yp,bitmap)
	{
		var xdisp = Math.round(xp);
		var ydisp = Math.round(yp);
		
		// find the area of overlap
		// calculate the start y pixel in source and target
		var srcY = 0;
		var destY = 0;
		if (ydisp>0) destY = ydisp;
		if (ydisp<0) srcY = -ydisp;
		
		// calculate the start x pixel in source and target
		var srcX = 0;
		var destX = 0;
		if (xdisp>0) destX = xdisp;
		if (xdisp<0) srcX = -xdisp;
		
		// calculate the height of the overlap
		var ydist = obj.height-destY;
		if(bitmap.height-srcY < ydist)
			ydist = bitmap.height-srcY;
	
		// calculate the width of the overlap
		var xdist = obj.width-destX;
		if(bitmap.width-srcX < xdist)
			xdist = bitmap.width-srcX;
	
		if ( ydist > 0 && xdist > 0)
		{
			for ( var y = 0; y < ydist; y++)
			{
				for(var xPos = 0; xPos < bitmap.width; xPos++)
				{
					if ( bitmap.GetPixel(xPos,srcY) >= 0 )
					{
						obj.SetPixel(xPos+xdisp,destY,bitmap.GetPixel(xPos,srcY));
					}
				}
				srcY++;
				destY++;
			}
		}
			
/*		
		for(var yPos = 0; yPos < bitmap.height; yPos++)
		{
			if ( yPos +ydisp >= 0 && yPos+ydisp < obj.height)
			for(var xPos = 0; xPos < bitmap.width; xPos++)
			{
				if ( bitmap.GetPixel(xPos,yPos) >= 0 )
				obj.SetPixel(xPos+xdisp,yPos+ydisp,bitmap.GetPixel(xPos,yPos));
			}
		}
*/
	}
	
	obj.WriteChar = function(char, charset, xPos,yPos,colour,xbig,ybig)
	{
		charSet.WriteChar(char,obj,xPos,yPos,colour,xbig,ybig);
	}

	obj.WriteString = function(text,charSet, xPos,yPos,colour,xbig,ybig)
	{
		charSet.WriteString(text,obj,xPos,yPos,colour,xbig,ybig);
	}

	obj.WriteStringCentered = function(text, charset, yPos,colour,xbig,ybig)
	{
		if (xbig == undefined) xbig = false;
		if ( xbig )
			charset.WriteString(text,obj,width/2-charset.GetWidth()/2*text.length*2,yPos, colour,xbig,ybig);
		else
			charset.WriteString(text,obj,width/2-charset.GetWidth()/2*text.length,yPos, colour,xbig,ybig);
	}

	obj.Clear(-1);
		
	return obj;
}

CharSet = function (width, height)
{
	if (width == undefined)
		width = 8;

	if (height == undefined)
		height = 8;

	var obj = {};
	var charData = {};

	obj.GetWidth = function ()
	{
		return width;
	}

	obj.GetHeight = function ()
	{
		return height;
	}
	obj.SetChar = function(char, chardata )
	{
		charData[char] = chardata;
	}

	obj.WriteChar = function(char,bitmap,xPos,yPos,colour,xbig,ybig)
	{
		if(typeof(xbig)==='undefined') xbig = false;
		if(typeof(ybig)==='undefined') ybig = false;
		var rowData = charData[char];
		if ( rowData != undefined )
		{
			for ( var row = 0; row < rowData.length; row++)
			{
				var line = rowData[row];
				for ( var charPos = 0; charPos < line.length; charPos++)
				{
					var chr = line.charAt(charPos);
					if ( chr != " " )
					{
						if ( !xbig && !ybig)
							bitmap.SetPixel(charPos+xPos, row+yPos, colour );
							
						if ( xbig && !ybig)
						{
							bitmap.SetPixel(charPos*2+xPos, row+yPos, colour );
							bitmap.SetPixel(charPos*2+xPos+1, row+yPos, colour );
						}
						if ( !xbig && ybig)
						{
							bitmap.SetPixel(charPos+xPos, row*2+yPos, colour );
							bitmap.SetPixel(charPos+xPos, row*2+yPos+1, colour );
						}
						if ( xbig && ybig)
						{
							bitmap.SetPixel(charPos*2+xPos, row*2+yPos, colour );
							bitmap.SetPixel(charPos*2+xPos+1, row*2+yPos, colour );
							bitmap.SetPixel(charPos*2+xPos, row*2+yPos+1, colour );
							bitmap.SetPixel(charPos*2+xPos+1, row*2+yPos+1, colour );
						}
					}
				}
			}
		}
	}

	obj.WriteString = function(text,bitmap,xPos,yPos,colour,xbig,ybig)
	{
		if(typeof(xbig)==='undefined') xbig = false;
		for ( var charPos = 0; charPos < text.length; charPos++)
		{
			var chr = text.charAt(charPos);
			if ( xbig)
				obj.WriteChar(chr,bitmap,xPos+charPos*2*width, yPos, colour,xbig,ybig );
			else
				obj.WriteChar(chr,bitmap,xPos+charPos*width, yPos, colour,xbig,ybig );
		}
	}

	return obj;
}

Sprite = function (xp,yp,costumeOrBitmap)
{
	if (costumeOrBitmap === null ) return null;
	var costume = costumeOrBitmap;
	if ( BaseBitmap.isPrototypeOf(costumeOrBitmap)) 
	{
		costume = Costume();
		costume.SetItem(0,costumeOrBitmap);
	}
	else
	{
		if ( !BaseCostume.isPrototypeOf(costumeOrBitmap)) return null;
	}
	var obj = {};

	var lifeSpan = -1;
	obj.died = false;
	obj.name = "";


	obj.pos = Vector(xp,yp);
	obj.vel = Vector(0,0);
	obj.costume = costume;
	obj.costumeAnimator = Animator([0]);
	obj.bitmap = costume.GetItem(0);
	obj.wrap = false;
	obj.collided = false;
	obj.collidedList = new Array();

	obj.SetLifeSpan = function(newLifeSpan)
	{
		lifeSpan = newLifeSpan;
	}

	obj.SetCostume = function(costume)
	{
		obj.costume = costume;
	}

	obj.SetWrapOn = function()
	{
		obj.wrap = true;
	}
	
	obj.SetWrapOff = function()
	{
		obj.wrap = false;
	}
	
	obj.SetAnimator = function(frameList)
	{
		obj.costumeAnimator = Animator(frameList);
	}
	
	obj.SetAnimatorBounce = function ()
	{
		obj.costumeAnimator.Bounce(obj.costume.Length());
	}
	
	obj.SetAnimatorLoop = function ()
	{
		obj.costumeAnimator.Loop(obj.costume.Length());
	}
	
	obj.SetAnimatorFrame = function(frame)
	{
		obj.costumeAnimator.Set(frame);
		obj.bitmap = obj.costume.GetItem(obj.costumeAnimator.Get());
	}
	
	obj.GetAnimatorFrame = function(frame)
	{
		return obj.costumeAnimator.Get();
	}
	
	obj.SetCostumeAnimator = function(animator)
	{
		obj.costumeAnimator = animator;
	}
	
	obj.SetAnimatorUpdateRate = function (updateRate)
	{
		obj.costumeAnimator.SetUpdateRate(updateRate);
	}
	
	obj.SetMovement = function(xm,ym)
	{
		obj.vel.x = xm;
		obj.vel.y = ym;
		return obj;
	}
	
	obj.IsCollidedWith = function(targetSpriteName)
	{
		var target = GE.SpriteGet(targetSpriteName);

		if ( target == undefined )
			return false;

		// simple bounding box check will do for now
		if ( obj.pos.x < target.pos.x + target.bitmap.width 
			&& obj.pos.x + obj.bitmap.width > target.pos.x 
			&& obj.pos.y < target.pos.y + target.bitmap.height 
			&& obj.pos.y + obj.bitmap.height > target.pos.y )
		{
//			return true;
			var collided = false;
			// now lets do a pixel perfect collision check
			// get the biggest left
			var boxLeftPos = obj.pos.x;
			if ( boxLeftPos < target.pos.x )
				boxLeftPos = target.pos.x;
			// get the smallest right
			var boxRightPos = obj.pos.x + obj.bitmap.width;
			if ( boxRightPos > target.pos.x + target.bitmap.width)
				boxRightPos = target.pos.x + target.bitmap.width;
			// get the biggest top
			var boxTopPos = obj.pos.y;
			if ( boxTopPos < target.pos.y )
				boxTopPos = target.pos.y;
			// get the smallest bottom
			var boxBottomPos = obj.pos.y + obj.bitmap.height;
			if ( boxBottomPos > target.pos.y + target.bitmap.height)
				boxBottomPos = target.pos.y + target.bitmap.height;
				
			var overlapWidth = boxRightPos - boxLeftPos;
			var overlapHeight = boxBottomPos - boxTopPos;
			
			var sx = Math.floor(boxLeftPos - obj.pos.x);
			var sy = Math.floor(boxTopPos - obj.pos.y);
			var tx = Math.floor(boxLeftPos - target.pos.x);
			var ty = Math.floor(boxTopPos - target.pos.y);
			for ( var y = 0; y < overlapHeight; y++)
			{
				for ( var x = 0; x < overlapWidth; x++ )
				{
					var p1 = obj.bitmap.GetPixel(sx+x,sy+y);
					var p2 = target.bitmap.GetPixel(tx+x,ty+y);
					if (p1 != -1 && p2 != -1 )
						collided = true;
				}
			}
			
			return collided;
		}

		return false;
	}
	
	obj.Update = function (scrWidth, scrHeight)
	{
		obj.pos.x += obj.vel.x;
		obj.pos.y += obj.vel.y;
		if ( obj.wrap )
		{
			if ( obj.pos.x < 0 )
				obj.pos.x += scrWidth;
			if ( obj.pos.y < 0 )
				obj.pos.y += scrHeight;
			if ( obj.pos.x >= scrWidth )
				obj.pos.x -= scrWidth;
			if ( obj.pos.y >= scrHeight )
				obj.pos.y -= scrHeight;
		}

		obj.costumeAnimator.Update();
		obj.bitmap = obj.costume.GetItem(obj.costumeAnimator.Get());
		obj.layerChanged = false;

		if ( lifeSpan != -1 )
		{
			lifeSpan--;
			if (lifeSpan == 0 )
				obj.died = true;
		}
	}

//	obj.Draw = function ()
//	{
//		
//	}

	return obj;
}

Vector = function(x,y)
{
	var obj = {};
	
	obj.x = x;
	obj.y = y;

	obj.Add = function(v1)
	{
		return Vector(obj.x+v1.x, obj.y+v1.y);
	}

	obj.Subtract = function(v1)
	{
		return Vector(obj.x-v1.x, obj.y-v1.y);
	}

	obj.Multiply = function(v1)
	{
		return Vector(obj.x*v1.x, obj.y*v1.y);
	}

	obj.Magnitude = function()
	{
		return Math.sqrt(obj.x*obj.x + obj.y*obj.y);
	}

	obj.Normalise = function()
	{
		var mag = obj.Magnitude();
		obj.x /= mag;
		obj.y /= mag;
	}

	obj.SetMagnitude = function(newMagnitude)
	{
		obj.Normalise();
		obj.x *= newMagnitude;
		obj.y *= newMagnitude;
	}

	obj.DotProduct = function(v)
	{
		return obj.x * v.x + obj.y * v.y;
	}

	obj.ScalarMultiply = function(scalar)
	{
		obj.x *= scalar;
		obj.y *= scalar;
	}

	return obj;
}

var BaseCostume = {};
Costume = function()
{
	var obj = Object.create(BaseCostume);
	
	obj.bitmaps = Array();
	
	obj.SetItem = function (frame, bitmap)
	{
		// try to set a frame to something other than a bitmap will result in nothing happening
		if ( !BaseBitmap.isPrototypeOf(bitmap)) return;
		obj.bitmaps[frame] = bitmap;
	};

	obj.SetItems = function (bitmaps,startFrame)
	{
		var frame = startFrame;
		for(var bitmapPos = 0; bitmapPos < bitmaps.length; bitmapPos++)
		{
			obj.SetItem(frame, bitmaps[bitmapPos]);
			frame++;
		}
	};

	obj.Length = function ()
	{
		return obj.bitmaps.length;
	}
	
	obj.GetItem = function (frame) 
	{
		return obj.bitmaps[frame];
	}
	
	obj.Update = function()
	{
	}
	
	return obj;
}

Animator = function (frameList)
{
	var obj = {};
	obj.frame = 0;
	obj.updateRate = 1;
	obj.repeat = true;
	
	if (frameList == null )
	{
		obj.frameList = new Array();
	}
	else
	{
		obj.frameList = frameList;
	}
	var paused = false;
	
	obj.Bounce = function (frames)
	{
		var list = new Array();
		var f = 0;
		for ( var i = 0; i < frames; i++)
		{
			list[f] = i;
			f++;
		}
		for ( var i = frames-2; i > 0; i--)
		{
			list[f] = i;
			f++;
		}
		obj.frameList = list;
	}
	
	obj.Loop = function (frames)
	{
		var list = new Array();
		var f = 0;
		for ( var i = 0; i < frames; i++)
		{
			list[f] = i;
			f++;
		}
		obj.frameList = list;
	}
	
	obj.Update = function ()
	{
		if ( paused == false )
		{
			var prevFrame = obj.frame;
			obj.frame = (obj.frame + obj.updateRate)  % obj.frameList.length;
			if ( obj.frame < prevFrame )
				if ( !obj.repeat )
				{
					obj.frame = prevFrame;
					obj.Pause();
				}
		}
	}
	
	obj.Get = function()
	{
		return obj.frameList[Math.floor(obj.frame)];
	}
	
	obj.Set = function(frame)
	{
		obj.frame = Math.floor(frame % obj.frameList.length);
	}
	
	obj.SetUpdateRate = function(updateRate)
	{
		obj.updateRate = updateRate;
		obj.waitTime = 0;
	}
	
	obj.Start = function () 
	{
		frame = 0;
		paused = false;
	}
	
	obj.Resume = function () 
	{
		paused = false;
	}
	
	obj.Stop = function () 
	{
		frame = 0;
		paused = true;
	}
	
	obj.Pause = function () 
	{
		paused = true;
	}
	
	obj.Resume = function () 
	{
		paused = false;
	}
	
	return obj;
}


function customSound(bitrate)
{
	this.bitrate = bitrate;
	this.angle = 0;
	this.customSoundData=[];
	this.totalDuration = 0;
	this.dataPos = 0;
	
	customSound.prototype.add = function(duration, startFreq, endFreq, startVol, endVol, startNoise, endNoise )
	{
		var vol = startVol;
		var freq = startFreq;
		var angleInc = (2*Math.PI)/this.bitrate * freq;
		var noise = startNoise;
		
		for ( var x=0; x < this.bitrate*duration; x++)
		{
			vol = (startVol + (endVol - startVol)*x/(this.bitrate*duration));
			this.customSoundData[this.dataPos] = (Math.sin(this.angle) + (Math.random()*noise)) * vol; 
			freq = startFreq + (endFreq - startFreq)*x/(this.bitrate*duration);
			noise = startNoise + (endNoise - startNoise)*x/(this.bitrate*duration);

			angleInc = (2*Math.PI)/this.bitrate * freq;
			this.angle+=angleInc;
			if ( this.angle > Math.PI * 2 )
			{
				this.angle -= Math.PI * 2;
			}
			this.dataPos++;
		}
	}
	
	customSound.prototype.createSound = function()
	{
		var n = this.customSoundData.length;
		var header = "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00********\x01\x00\x08\x00data****";

		// ChunkSize
		var numval = n + 36;
		header=insertLong(header,4,numval);

		numval = this.bitrate; // byterate
		header = insertLong(header,24,numval);
	 
		  // BitRate
		numval = this.bitrate * 8; //44100;
		header = insertLong(header,28,numval);
	 
		  // Subchunk2Size
	//      insertLong(n);
		numval = n;
		header = insertLong(header,40,numval);
		  
		// Output sound data
		for (var i = 0; i < n; ++i) 
		{
			var charCode = Math.round(Math.min(127, Math.max(-127, this.customSoundData[i]))+127);
			header += String.fromCharCode(charCode);
		}
		
//		var o= document.getElementById('output');
		var h = btoa(header);
		h = 'data:audio/wav;base64,' + h;
		
		var a = new Audio();
		a.src = h;
		return a;
	}
}

function insertLong(inString, index, inValue)
{
	var retString = inString.substr(0,index);
	for (i = 0; i < 4; ++i) {
	  retString += String.fromCharCode(inValue & 255);
	  inValue = inValue >> 8; 
	}
	retString += inString.substr(index+4);
	return retString;
}

// last piece of code is to start the game
init();
</script>

</html>

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required