function gameLogic() {
	keyLogic();		
	movementLogic();
	networkLogic();
}

var joyx = 0.0;
var joyy = 0.0;
var joyx_last = 0.0;
var joyy_last = 0.0;
var lt = 0.0;
var joystick = [0.0, 0.0];

function keyLogic(){
	joyx = KEY_D - KEY_A;
	joyy = KEY_W - KEY_S;
}

var velx = 0.0;
var vely = 0.0;
var velz = 0.0;

var accx = 0.0;
var accy = 0.0;
var accz = 0.0;

var posx = -2300.0;
var posy = -760.0;
var posz = 1000.0;

var angle = 0.0;

var ACC_BLEED = 0.001;
var ACC_MAX = 0.07;

var TURN_FACTOR = 10;
var ROT_FACTOR = 0.04;

var DIST_BASE = 5;

var VEL_MAX = 30;
var VEL_BLEED = 0.1;

var GRAVITY = 0.15;
var HOVER_HEIGHT = 4;
var Z_DAMPENING = 0.99;
var ACC_MAX_Z = 5;
var STABLE_FRAMES = 60;
var STABLE_COUNT = 0;

function movementLogic(){
	accz = (GRAVITY / (Math.pow( belowMe() / HOVER_HEIGHT , 2))) - GRAVITY;
	
	if(accz > ACC_MAX_Z)
		accz = ACC_MAX_Z;
	if(accz < -ACC_MAX_Z)
		accz = -ACC_MAX_Z;
		
	velz += scale*accz;
	
	accy = joyy*ACC_MAX;
	
	if(joyy > 0.1){
		vely += scale*accy;	
	}					
	else{
		vely -= (VEL_BLEED)*(vely/VEL_MAX);
	}
	
	if(vely > VEL_MAX)	{				
		vely = VEL_MAX;
	}
	if(vely < 0){
		vely = 0;
	}
	

	rampCollision();
	mapCollision();
	updateFacing(); // Must be called before updatePosition
	updatePosition();	
	updateCamera();
	if(KEY_R){
		velx = 0.0;
		vely = 0.0;
		velz = 0.0;

		accx = 0.0;
		accy = 0.0;
		accz = 0.0;

		posx = -2300.0;
		posy = -760.0;
		posz = 1000.0;
	}
}

function rampCollision(){
	if(onRamp() && rampDist < vely && belowMeRamp() < 10 && rampAngle < Math.PI / 10){
		rampAngle = Math.PI / 24;
		vely *= Math.cos(rampAngle);	
		velz += scale*vely*Math.abs(Math.sin(rampAngle));		
	}
}

function updateCamera(){
	dist = DIST_BASE + (20 * vely/VEL_MAX);
	
	camera.position.x = posx - (dist * Math.sin(angle));	
	camera.position.y = posy - (dist * Math.cos(angle));
	
	camera.position.z = PlayerAvatar.getMesh().position.z + 8 - (1.5 * vely/VEL_MAX);
	camera.fov = 100 + 10*(vely/VEL_MAX);
	
	camera.updateProjectionMatrix();
	
	camera.target.position.x = posx;
	camera.target.position.y = posy;
	camera.target.position.z = posz;
}

function updateFacing(){	// Update facing record, and update mesh facing.
	angle += scale * ROT_FACTOR * mouse.x; 
	if(angle > 2 * Math.PI){
		angle -= 2 * Math.PI;
	}
	if(angle < - 2 * Math.PI){
		angle += 2 * Math.PI;
	}
	
	PlayerAvatar.getMesh().rotation.z = -0.6 * mouse.x - angle;
}

function updatePosition(){				   // Update Position record, and update mesh/lighting position
	posx += scale * (velx * Math.cos(angle) + vely * Math.sin(angle));						
	posy += scale * (vely * Math.cos(angle) + velx * Math.sin(angle));
	posz += scale * velz;
	
	PlayerAvatar.getMesh().position.x = posx;
	PlayerAvatar.getMesh().position.y = posy;		
	PlayerAvatar.getMesh().position.z = posz;
	
	PlayerLight.position.x = posx;
	PlayerLight.position.y = posy;
}

function mapCollision(){
	var r = new THREE.Ray( new THREE.Vector3(posx, posy, posz), new THREE.Vector3(0,0,-1));
	
	cl = r.intersectScene( scene );
	
	for(var i = 0; i < cl.length; i++){
		if(cl[i].object.name == "TRACK" || cl[i].object.name == "RAMP"){
			if(cl[i].distance < scale*Math.abs(velz)){
				velz = 0;
				posz += cl[i].distance;				
			}
		}
	}
	
	var wallLhit = false;
	var r2 = new THREE.Ray( new THREE.Vector3(posx+2, posy, posz), new THREE.Vector3(Math.cos(angle),Math.sin(angle),0));	
	cl2 = r2.intersectScene( scene );
	for(var i = 0; i < cl2.length; i++){
		if(cl2[i].object.name == "RAMP" || cl2[i].object.name == "TRACK"){
			if(cl2[i].distance < vely*scale){
				posy += (vely*Math.sin(angle))*scale;
				posx -= (vely*Math.cos(angle))*scale;
				wallLhit = true;
				vely /= -2;
				//document.getElementById("ping").innerHTML += "LEFT HIT";
			}
		}
	}
	
	var wallRhit = false;
	var r2 = new THREE.Ray( new THREE.Vector3(posx+2, posy, posz), new THREE.Vector3(-Math.cos(angle),Math.sin(angle),0));	
	cl2 = r2.intersectScene( scene );
	for(var i = 0; i < cl2.length; i++){
		if(cl2[i].object.name == "RAMP" || cl2[i].object.name == "TRACK"){
			if(cl2[i].distance < vely*scale){
				posy -= (vely*Math.sin(angle))*scale;
				posx += (vely*Math.cos(angle))*scale;
				wallRhit = true;
				vely /= -2;
				//document.getElementById("ping").innerHTML += "RIGHT HIT";
			}
		}
	}
}

var cl;
var cl2;
function belowMe(){
	var r = new THREE.Ray( new THREE.Vector3(posx, posy, posz), new THREE.Vector3(0,0,-1));
	cl = r.intersectScene( scene );
	
	for(var i = 0; i < cl.length; i++){
		if(cl[i].object.name == "RAMP" || cl[i].object.name == "TRACK"){
			return cl[i].distance;
		}
	}
	
	return 2000000000;
	
}

var rampposz;
function belowMeRamp(){
	var r = new THREE.Ray( new THREE.Vector3(posx, posy, posz), new THREE.Vector3(0,0,-1));	
	cl = r.intersectScene( scene );
	
	for(var i = 0; i < cl.length; i++){
		if(cl[i].object.name == "RAMP"){
			rampposz = cl[i].point.z;
			return cl[i].distance;
		}
	}
	
	return 2000000000;
	
}

var rampAngle;
var rampDist;
var cl;

function onRamp(){
	var r = new THREE.Ray( new THREE.Vector3(posx, posy, posz), new THREE.Vector3(0,0,-1));	
	cl = r.intersectScene( scene );
	
	for(var i = 0; i < cl.length; i++){
		if(cl[i].object.name == "RAMP"){
			if(cl[i].object.rotation.x == 0)
				rampAngle = cl[i].object.rotation.y;
			if(cl[i].object.rotation.y == 0)
				rampAngle = cl[i].object.rotation.x;
				
				
			rampDist = cl[i].distance;
			return true;			
		}
	}
	
	return false;
}

function networkLogic(){
	if(lastcall == "" && connected && !requestPlayerlist){
		update(Math.floor(posx), 
			   Math.floor(posy), 
			   Math.floor(velx), 
			   Math.floor(vely));
	}else if(requestPlayerlist){
		requestList();
		requestPlayerlist = false;
	}
}

