Google Street Car - JavaScript Source


var geocoder;
var map;
var pano;
var canvas;
var snapMap;
var latLng;
 
var zooom = 19;
var rotateAngle = 0;
 
var xAdd = 0;
var yAdd = 0;
var carRotation = 0;
var cycle = 0;
const cycleTop = 10;
 
var x = 0;
var y = 0;
const xMultiply = 1.7;
const yMultiply = 1.7;
const tol = 0.06;
const tolNeg = -0.06;
 
var frameCount = 0;
var staticMapAddy;
var staticMapError = false;
var staticMapReady = true;
var seekOnce = true;
var seekCount = 0;
var pCounterLeft = 0;
var pCounterRight = 0;
var once = true;
 
var music = new Audio("music1.mp3");
var startSound = new Audio("start.mp3");
var fotoSound = new Audio("foto.mp3");
var hornSound = new Audio("horn.mp3");
var curveSound = new Audio("curve.mp3");
var crashSound0 = new Audio("crash0.mp3");
var crashSound1 = new Audio("crash1.mp3");
var crashSound2 = new Audio("crash2.mp3");
var carSound0 = new Howl({loop: true, preload: true, volume: 0.3, src: ["car0.mp3"]});
var carSound1 = new Howl({loop: true, preload: true, volume: 0.1, src: ["car1.mp3"]});
var carSound2 = new Howl({loop: true, preload: true, volume: 0.15, src: ["car2.mp3"]});
var carSound3 = new Howl({loop: true, preload: true, volume: 0.2, src: ["car3.mp3"]});
var carSound4 = new Howl({loop: true, preload: true, volume: 0.3, src: ["car4.mp3"]});
var carSound5 = new Howl({loop: true, preload: true, volume: 0.4, src: ["car5.mp3"]});
 
var hitTestData;
var hitTestTopLeft = false;
var hitTestTopRight = false;
var hitTestBottomLeft = false;
var hitTestBottomRight = false;
 
const FRICTIONMOD = 0.97;
const MAXSPEED = 5;
const ACCELERTAION = 0.15;
const REVMAXSPEED = -2;
const REVACCELERTAION = 0.05;
const MAXTURNRATE = 5;
const TURNIMPACTONSPEED = 0.99;
 
var speed = 0;
var pressUp = false;
var pressDown = false;
var pressLeft = false;
var pressRight = false;
var pressSpace = false;
var pressCtrl = false;
 
function modifyKeyStatus(e, keyActive) {
	switch(e.keyCode)
	{
		case 38 :
			pressUp = keyActive;
			break;
		case 83 :
			pressDown = keyActive;
			break;
		case 87 :
			pressUp = keyActive;
			break;
		case 65 :
			pressLeft = keyActive;
			break;
		case 68 :
			pressRight = keyActive;
			break;
		case 40 :
			pressDown = keyActive;
			break;
		case 39 :
			pressRight = keyActive;
			break;
		case 37 :
			pressLeft = keyActive;
			break;
		case 32 :
			pressSpace = keyActive;
			break;
		case 17 :
			pressCtrl = keyActive;
			break;
	}
}
 
function snap() {
	staticMapReady = false;
	staticMapAddy = "https://maps.googleapis.com/maps/api/staticmap";
	staticMapAddy += "?center=" + latValue + "," + lngValue;
	staticMapAddy += "&size=800x800";
	staticMapAddy += "&scale=1&format=jpg&visual_refresh=true";
	staticMapAddy += "&zoom=" + zooom;
	staticMapAddy += "&style=feature:road|color:0x000000";
	staticMapAddy += "&style=feature:water|color:0xFFFFFF";
	staticMapAddy += "&style=feature:landscape|color:0xFFFFFF";
	staticMapAddy += "&style=element:labels|visibility:off";
	staticMapAddy += "&key=ABC";
	staticMapAddy += "&maptype=" + google.maps.MapTypeId.ROADMAP;
	snapMap = document.getElementById("imgMap");
	snapMap.style.display = "None";
	snapMap.setAttribute("crossOrigin", "");
	$(snapMap).attr("src", staticMapAddy).load(function(){
		staticMapReady = true;
	});
	x = 0; y = 0;
}
 
function hitTest() {
	hitTestTopLeft = false;
	hitTestTopRight = false;
	hitTestBottomLeft = false;
	hitTestBottomRight = false;
	hitTestData = context.getImageData(800/2 - y, 800/2 - x, 1, 1).data;
	if (hitTestData[0] == hitTestData[1] & hitTestData[1] == hitTestData[2] & hitTestData[2] == hitTestData[0]) {
		if (hitTestData[0] < 250) hitTestTopLeft = false;
		else hitTestTopLeft = true;
	} else hitTestTopLeft = false;
 
	hitTestData = context.getImageData(800/2 - y + 20, 800/2 - x, 1, 1).data;
	if (hitTestData[0] == hitTestData[1] & hitTestData[1] == hitTestData[2] & hitTestData[2] == hitTestData[0]) {
		if (hitTestData[0] < 250) hitTestTopRight = false;
		else hitTestTopRight = true;
	} else hitTestTopRight = false;
 
	hitTestData = context.getImageData(800/2 - y, 800/2 - x + 20, 1, 1).data;
	if (hitTestData[0] == hitTestData[1] & hitTestData[1] == hitTestData[2] & hitTestData[2] == hitTestData[0]) {
		if (hitTestData[0] < 250) hitTestBottomLeft = false;
		else hitTestBottomLeft = true;
	} else hitTestBottomLeft = false;
 
	hitTestData = context.getImageData(800/2 - y + 20, 800/2 - x + 20, 1, 1).data;
	if (hitTestData[0] == hitTestData[1] & hitTestData[1] == hitTestData[2] & hitTestData[2] == hitTestData[0]) {
		if (hitTestData[0] < 250) hitTestBottomRight = false;
		else hitTestBottomRight = true;
	} else hitTestBottomRight = false;
}
 
function geocode() {
	var addy = document.getElementById("inputtext").value;
	geocoder.geocode({"address": addy}, function(results, status) {
		if (status === "OK") {
			location.href = encodeURI("http://codewelt.com/gcar?startAt=" + addy + "&lat=" + results[0].geometry.location.lat() + "&lng=" + results[0].geometry.location.lng());
		} else alert("Could not find location: " + addy + ". Please enter another location.");
	});
}
 
function initMap() {
	geocoder = new google.maps.Geocoder();
	latLng = new google.maps.LatLng(latValue, lngValue);
	divMap = document.getElementById("divMap");
	map = new google.maps.Map(divMap, {
		zoom: zooom,
		center: latLng,
		mapTypeId: google.maps.MapTypeId.SATELLITE,
		disableDefaultUI: true,
		backgroundColor:"#FFFFFF"
	});
	map.setTilt(0);
	pano = new google.maps.StreetViewPanorama(
		document.getElementById("divPano"), {
			position: latLng,
			zoomControl: false,
			disableDefaultUI: true,
			pov: {
				heading: 90,
				pitch: 0
			}
	});
	google.maps.event.addDomListener(map, "click", function() {
		null;
	});
	google.maps.event.addDomListener(map, "mousewheel", function() {
		map.setZoom(zooom);
	});
	document.getElementById('canv').innerHTML = '<canvas id="drawCanvas" width="800" height="800"></canvas>';
	canvas = document.getElementById('drawCanvas');
	context = canvas.getContext("2d");
	context.filter = "blur(23px)";
	snap();
	document.getElementById("imgMap").onerror = function() {
		null;
	}
	crashSound0.volume = 0.2;
	crashSound1.volume = 0.1;
	crashSound2.volume = 0.1;
	curveSound.volume = 0.05;
	hornSound.volume = 0.1;
	fotoSound.volume = 0.8;
 
	$('body').keydown(function(e) {
		evt = e || window.event;
		modifyKeyStatus(evt, true);
		if (e.keyCode == 72) hornSound.play();
		if (e.keyCode == 32) {
			$( "#imgPano" ).css( "opacity", 1.0);
			var pov = 0;
			if (carRotation + 90 > 360) pov = carRotation + 90 - 360;
			else pov = carRotation + 90;
			pano.setPosition(new google.maps.LatLng(latValue, lngValue));		
			pano.setPov({
				heading: pov,
				pitch: 0
			});
			$( "#imgPano" ).fadeTo( "slow" , 0.0, function() {
				null;
			});
			fotoSound.play();
		}
		if (once) {
			once = false;
			$( "#imgTop" ).fadeTo("fast", 0.0, function() {
				null;
			});
		}  
	}).keyup(function(e) {
		evt = e || window.event;
		modifyKeyStatus(evt, false);
	});
 
(function drawFrame () {
	window.requestAnimationFrame(drawFrame, canvas);
	frameCount++;
	if (frameCount % 2 == 0) return;
	if (pressUp && !pressCtrl) speed += ACCELERTAION;
	speed = speed * FRICTIONMOD;
	if (pressDown) speed -= REVACCELERTAION;
	if (pressRight) {
		if (speed > MAXSPEED / 4) carRotation += MAXTURNRATE;
		else if (speed < (MAXSPEED / 4) && speed >= 0) carRotation += ((MAXTURNRATE / 4) * speed);
		else if (speed < 0) carRotation += (MAXTURNRATE * speed / ((MAXSPEED / 4) * 3));
		speed *= TURNIMPACTONSPEED;
	}
	if (pressLeft) {
		if (speed > MAXSPEED / 4) carRotation -= MAXTURNRATE; 
		else if (speed < (MAXSPEED / 4) && speed >= 0) carRotation -= (MAXTURNRATE / 4) * speed;
		else if (speed < 0) carRotation -= MAXTURNRATE * speed / ((MAXSPEED / 4) * 3);
		speed *= TURNIMPACTONSPEED;
	}
	xAdd = Math.sin (carRotation * Math.PI / 180) * speed;
	yAdd = Math.cos (carRotation* Math.PI / 180) * -speed;
	if (Math.abs (speed) > MAXSPEED) speed = MAXSPEED;
	if (speed < REVMAXSPEED) speed = REVMAXSPEED;
	if (pressCtrl) {
		speed -= speed / (MAXSPEED/2);
		if (pressRight) carRotation += speed / 2;
		if (pressLeft) carRotation -= speed / 2;
	}
	if (pressUp || pressDown) {
		if (pressLeft) {
			pCounterLeft++;
			if (pCounterLeft > 11 && speed > 4) curveSound.play();
		} else {
			if (pCounterLeft > 1) pCounterLeft -= 2;
		}
		if (pressRight) {
			pCounterRight++;
			if (pCounterRight > 11 && speed > 4) curveSound.play();
		} else {
			if (pCounterRight > 1) pCounterRight -= 2;
		}
	}
	if (speed < 0.3) {
		if (!carSound0.playing()) carSound0.play();
	} else carSound0.pause();
	if (pressUp) {
		carSound0.pause();
		if (speed < 1) {
			if (!carSound1.playing()) carSound1.play();
			carSound2.pause();
			carSound3.pause();
			carSound4.pause();
			carSound5.pause();
		} else if (speed < 2) {
			carSound1.pause();
			if (!carSound2.playing()) carSound2.play();
			carSound3.pause();
			carSound4.pause();
			carSound5.pause();
		} else if (speed < 3) {
			carSound1.pause();
			carSound2.pause();
			if (!carSound3.playing()) carSound3.play();
			carSound4.pause();
			carSound5.pause();
		} else if (speed < 4) {
			carSound1.pause();
			carSound2.pause();
			carSound3.pause();
			if (!carSound4.playing()) carSound4.play();
			carSound5.pause();
		} else {
			carSound1.pause();
			carSound2.pause();
			carSound3.pause();
			carSound4.pause();
			if (!carSound5.playing()) carSound5.play();
		}
	} else {
		carSound1.pause();
		carSound2.pause();
		carSound3.pause();
		carSound4.pause();
		carSound5.pause();
	}
	music.volume = speed / 10 + 0.15;
 
	if (snapMap && staticMapReady) {
		if (frameCount % 5 == 0) context.drawImage(snapMap, 0, 0, 800, 800);
		hitTest();
		if (hitTestTopRight || hitTestTopLeft || hitTestBottomRight || hitTestBottomLeft) {
			cycle = 0;
			while (hitTestTopRight) {
				latValue -= tol * 3 / 300000.0;
				lngValue -= tol * 3 / 300000.0;
				x -= tol * 3 * xMultiply;
				y += tol * 3 * yMultiply;
				latLngValue = new google.maps.LatLng(latValue, lngValue);
				map.setCenter(latLngValue);
				hitTest();
				if (cycle == cycleTop) break;
				else cycle++;
			}
			cycle = 0;
			while (hitTestTopLeft) {
				latValue -= tol / 300000.0;
				lngValue -= tolNeg / 300000.0;
				x -= tol * xMultiply;
				y += tolNeg * yMultiply;
				latLngValue = new google.maps.LatLng(latValue, lngValue);
				map.setCenter(latLngValue);
				hitTest();
				if (cycle == cycleTop) break;
				else cycle++;
			}
			cycle = 0;
			while (hitTestBottomRight) {
				latValue -= tolNeg / 300000.0;
				lngValue -= tol / 300000.0;
				x -= tolNeg * xMultiply;
				y += tol * yMultiply;
				latLngValue = new google.maps.LatLng(latValue, lngValue);
				map.setCenter(latLngValue);
				hitTest();
				if (cycle == cycleTop) break;
				else cycle++;
			}
			cycle = 0;
			while (hitTestBottomLeft) {
				latValue -= -2 / 300000.0;
				lngValue -= -2 / 300000.0;
				x -= -2 * xMultiply;
				y += -2 * yMultiply;
				latLngValue = new google.maps.LatLng(latValue, lngValue);
				map.setCenter(latLngValue);
				hitTest();
				if (cycle == cycleTop) break;
				else cycle++;
			}
 
			if (speed > 4.5) {
				if ((Math.random() * (2.0 - 1.0) + 1.0) > 1.5) crashSound1.play();
				else crashSound2.play();
			} else crashSound0.play();
		} else {
			seekCount++;
			if (seekCount > 5 && seekOnce) {
				seekOnce = false;
				$( "#divMap").css( "opacity", 1.0);
				$( "#divPano").css( "opacity", 1.0);
				$( "#carImage").css( "opacity", 0.6);
				startSound.volume = 0.6;
				startSound.play();
				startSound.addEventListener("ended", function() {
					if ((Math.random() * (2.0 - 1.0) + 1.0) > 1.5) music = new Audio("music1.mp3");
					else music = new Audio("music2.mp3");
					music.volume = 0.1;
					music.loop = true;
					music.play();
					carSound0.play();
				});
			}
			latValue -= xAdd / 300000.0;
			lngValue -= yAdd / 300000.0;
			x -= xAdd * xMultiply;
			y += yAdd * yMultiply;	
			latLngValue = new google.maps.LatLng(latValue, lngValue);
			map.setCenter(latLngValue);
		}
	$("#carImage").rotate(carRotation);
	if (Math.abs(x) > 800/2 - 20 || Math.abs(y) > 800/2 - 20) snap();
}
}
());
null;
}
 
back