JSFiddle - React, Tailwind, and code Playground

by Michael Prosser

HTML

<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="stage">
  <div id="googleMap"></div>
  <div id="googleMapBack"></div>
  <div class="playership thrust">
    <div class="rotator">
      <div class="playerfront"></div>
      <div class="playerfrontwing"></div>
      <div class="playerback"></div>
      <div class="playerbottom"></div>
      <div class="playertop"></div>
      <div class="playerleft"></div>
      <div class="playerlefttop"></div>
      <div class="playerleftbottom"></div>
      <div class="playerright"></div>
      <div class="playerrighttop"></div>
      <div class="playerrightbottom"></div>
      <div class="playergun1"></div>
      <div class="playergun2"></div>
      <div class="playerthrust1"></div>
      <div class="playerthrust2"></div>
    </div>
  </div>

</div>

CSS

html,
body{
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px;
  perspective:500px;
  background-color:#000;
}
.stage{
  position:fixed;
  left:50%;
  top:50%;
  right:50%;
  bottom:50%;
  height:0px;
  width:0px;
  transform-style:preserve-3d;
  transform:rotateX(-10deg);
}
#googleMap {
  height: 1000px;
  width: 1000px;
  margin: 0px;
  padding: 0px;
  margin-top:1500px;
  margin-left:-1000px;
  transform:rotateX(90deg) translateZ(500px) scaleX(10) scaleY(10) scaleZ(10);
  background-color:#000;
backface-visibility:hidden;
pointer-events:none;
position:absolute;
}
#googleMapBack {
  height: 1000px;
  width: 1000px;
  margin: 0px;
  padding: 0px;
  margin-top:1500px;
  margin-left:-1000px;
  background-color:#ff0000;
backface-visibility:hidden;
pointer-events:none;
transform:rotateX(45deg) translateZ(-3000px) translateY(-3500px) scaleX(10) scaleY(10) scaleZ(10);
  position:absolute;
}






.playership{
	width:0px;
	height:0px;
  left:50%;
  top:50%;
	transform-style:preserve-3d;
	position:absolute;
	transform-origin:50% 50% !important;
}
.playership>.rotator{
	width:0px;
	height:0px;
  left:50%;
  top:50%;
	transform-style:preserve-3d;
	position:absolute;
  transform-origin:50% 50% !important;
  transform:rotateY(180deg);
}
.playership.killed>.rotator{
  animation:spin infinite 3s ease-in;
}
@keyframes rotate {
  0% { transform:rotateY(0deg) rotateX(-30deg); }
  100% { transform:rotateY(360deg) rotateX(-30deg); }
}
@keyframes spin {
  0% { transform:rotateY(180deg) rotateX(0deg) rotateZ(0deg); }
  100% { transform:rotateY(180deg) rotateX(-40deg) rotateZ(1840deg); }
}
.playership>.rotator div{
  filter: hue-rotate(90deg) opacity(1);
}
.playership .playerfront{
  width:200px;
  height:60px;
  position:absolute;
  margin-left:-100px;
  margin-top:-40px;
  transform:translateZ(35px);
  background-image:url(http://aninoob.com/particles/assets/player/player-front.png?1);
  background-size:cover;
}
.playership .playerback{
  width:200px;
  height:40px;
 ...

JavaScript

var terrain = {
	
  mapid: 'googleMap',
  map: null,
  mapid2: 'googleMapBack',
  map2: null,
  latitude: 49.2404653,
  longitude: -123.1050752,
  zoom: 17,
  inc: .00001,
  tilt: 0,
  
  key_left_down: false,
  key_up_down: false,
  key_right_down: false,
  key_down_down: false,
  
  x: 0,
  y: 0,
  z: 0,
  rx: 0,
  ry: 0,
  rz: 0,
  speed: .1,
  
  
  pixel_ratio: .0002,
  
  init: function(){
  
  	var mapProp = {
      center: new google.maps.LatLng(this.latitude+(this.x*this.pixel_ratio), this.longitude+(this.z*this.pixel_ratio)),
      zoom: this.zoom,
      keyboardShortcuts: false,
      mapTypeId: google.maps.MapTypeId.SATELLITE
    };
    
    this.map = new google.maps.Map(document.getElementById(this.mapid), mapProp);
    this.map.setTilt(this.tilt);
    
    this.map2 = new google.maps.Map(document.getElementById(this.mapid2), mapProp);
    this.map2.setTilt(this.tilt);
    // setup keyhandlers
    
    $(document).keydown(function(event){
    	
      switch(event.keyCode){
      
      	case 37: // left arrow
        terrain.key_left_down = true;
  			break;
        
        case 38: // up arrow
        terrain.key_up_down = true;
        break;
        
        case 39: // right arrow
        terrain.key_right_down = true;
        break;
        
        case 40: // down arrow
        terrain.key_down_down = true;
        break;
        
        }
      
      }).keyup(function(event){
    	
        switch(event.keyCode){

          case 37: // left arrow
          terrain.key_left_down = false
          break;

          case 38: // up arrow
          terrain.key_up_down = false;
          break;

          case 39: // right arrow
          terrain.key_right_down = false;
          break;

          case 40: // down arrow
          terrain.key_down_down = false;
          break;

        }
        
      	
      
    });
    
    requestAnimationFrame(terrain.render);
    
  },
  normalizeAngle: function(angle){
			var newAngle = angle;
			while...