/*
VERSION:	1.5
1.5		"undefined" can optionally be considered a wall, or not a wall
1.4		half-velocity while sliding around corners.  This avoids problems when using "slippery" physics settings.  (water, ice, etc...)
1.3		Added "mapTileSize" parameter

DECRIPTION:
	This system makes the player slide around the corners of tiles.
	It's meant to be used with the  walkInertia.as  style of movement.
	This collision should be applied before other tile & sprite collisions.

AVAILABLE DATA:
	This returns a collision function which changes its parent's objects & properties.
	The parent collision system (_this) contains:
		xOffset, yOffset
		player_mc
			_x, _y
		collision_array
		walk_obj
			xVel, yVel
	
*/
function makeCornerSlip( walk_obj, wallValues, mapTileSize )
{
	// misc
	var tileSize = mapTileSize || player_mc.tile.tileSize || 16;
	//walk_obj.wallValues = wallValues;
	// external information
	var xOffset = null;
	var yOffset = null;
	var player_mc = this;
	var collision_array = null;
	var walk_obj = null;		// populated by context-sensitive collision_funct()
	
	// settings
	var playerRadius = 4;
	var cornerSize = playerRadius;		// offset from center
	var lookAhead = playerRadius +(tileSize/2);
	
	
	
	
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////
	// HELPER FUNCTIONS
	var isWallId = function( collisionId ){
		// true = if the collisionId matches any wall value
		for(var i=0; i<wallValues.length; i++){
			if(wallValues[i] == collisionId)
				return true;
		}// for:  each wall value
		return false;
	}// isWallId()
	
	
	var isWall = function( xPixel, yPixel ){
		// get tile
		var xp = Math.floor(xPixel/tileSize);
		var yp = Math.floor(yPixel/tileSize);
		// get collision
		var id = collision_array[xp][yp];
		// state whether it's a wall
		return isWallId(id);
	}// isWall()
	
	
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////
	// EACH STEP
	var getWhichWay = function()
	{
		if(walk_obj.xVel==0  &&  walk_obj.yVel==0)
		{// if:  not moving
			return false;
		}// if:  not moving
		else if (Math.abs(walk_obj.xVel) == Math.abs(walk_obj.yVel) )
		{// if:  moving exactly diagonally
			return false;
		}// if:  moving exactly diagonally
		else
		{// if:  moving
			var abs = {};
			abs.x = Math.abs(walk_obj.xVel) /2;
			abs.y = Math.abs(walk_obj.yVel) /2;
			var slideSpeed = Math.max(abs.x, abs.y);
			if(slideSpeed > tileSize)		slideSpeed = tileSize;		// limit max speed
			var forwardAxis = (abs.x > abs.y)				? 'x' : 'y';
			var sideAxis 		= (forwardAxis == 'x')	? 'y' : 'x';
			// // look:   x=-1/+1 y=0  OR  x=0 y=-1/+1
			var moveDir = {};
			moveDir[forwardAxis] = 	abs[forwardAxis]	/walk_obj[forwardAxis	+'Vel'] || 0;	// moveDir.x = +1 / -1
			moveDir[sideAxis] =			abs[sideAxis]			/walk_obj[sideAxis		+'Vel'] || 0;	// moveDir.y = +1 / -1
			var output = {
				forwardAxis:forwardAxis,
				sideAxis:sideAxis,
				moveDir:moveDir,
				slideSpeed:slideSpeed
			}// output obj
			return output;
		}// if:  moving
	}// getWhichWay()
	
	
	
	var getSlideDir = function( dir )
	{
		var output = {x:0,y:0};
		// input
		var sideAxis = dir.sideAxis;
		var forwardAxis = dir.forwardAxis;
		var moveDir = dir.moveDir;
		//
		var check = {};
		// // top-left		(left by a quarter, up full)
			check[sideAxis]			= player_mc['_'+sideAxis]			-cornerSize;																				// check left by 4 pixels		(player._x -cornerSize)
			check[forwardAxis]	= player_mc['_'+forwardAxis]	+(lookAhead*moveDir[forwardAxis]);		// check forward by full		(player._y -playerRadius -tileSize)
			var checkA = isWall(check.x, check.y);
		// // top-right		(right by a quarter, up full)
			check[sideAxis]			= player_mc['_'+sideAxis]			+cornerSize;																				// check right by 4 pixels		(player._x +cornerSize)
			check[forwardAxis]	= player_mc['_'+forwardAxis]	+(lookAhead*moveDir[forwardAxis]);		// check forward by full			(player._y -playerRadius -tileSize)
			var checkB = isWall(check.x, check.y);
		if			(checkA && !checkB)	// if:  left corner hit, but not right corner
			output[sideAxis] = 1;
		else if	(!checkA && checkB)	// if:  right corner hit, but not left corner
			output[sideAxis] = -1;
		else		// if:  both corners or neither corner
			output = null;	// no sliding
		
		return output;
	}// getSlideDir()
	
	
	
	var setVelocity = function( slideDir, slideSpeed )
	{
		var slideVel = {x:slideSpeed, y:slideSpeed};
		slideVel.x *= slideDir.x;
		slideVel.y *= slideDir.y;
		walk_obj.xVel += slideVel.x;
		walk_obj.yVel += slideVel.y;
		// limit speed
		if(walk_obj.xVel > tileSize)
			walk_obj.xVel = tileSize;
		else if(walk_obj.xVel < -tileSize)
			walk_obj.xVel = -tileSize;
		if(walk_obj.yVel > tileSize)
			walk_obj.yVel = tileSize;
		else if(walk_obj.yVel < -tileSize)
			walk_obj.yVel = -tileSize;
	}// setVelocity()
	
	
	
	
	
	
	
	
	//////////////////////////////////////////////////////////////////////////////////////////
	// ALL STEPS
	var collision_funct = function()
	{
		xOffset = this.xOffset;
		yOffset = this.yOffset;
		player_mc = this.player_mc;
		collision_array = this.collision_array;
		walk_obj = this.walk_obj;
		
		if(!walk_obj.wallValues)			walk_obj.wallValues = [1,undefined];
		
		// which way are you going?
		var dir = getWhichWay();		// forwardAxis, sideAxis, moveDir, slideSpeed
		if(dir)
		{// if:  you are moving
			// check whether both forward points are hitting a wall
			var slideDir = getSlideDir( dir );
			if(slideDir)
			{// if:  exactly one point is empty
				setVelocity( slideDir, dir.slideSpeed );
			}// if:  exactly one point is empty
		}// if:  you are moving
	}// collision_funct()
	
	return collision_funct;
}// makeCornerSlip()