Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div id="scene">
  <div id="blocker">
    <div id="instructions">
				<span style="font-size:36px">Click to start</span>
				<br /><br />
				Move: WASD<br/>
				Jump: SPACE<br/>
				Look: MOUSE
			</div>
  </div>
  <div id="hint"><span>ESC to exit</span></div>
</div>


<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://threejs.org/examples/js/controls/PointerLockControls.js"></script>


              
            
!

CSS

              
                 body {
    margin: 0;
    overflow: hidden;
  }
canvas {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

#blocker {
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: rgba(0,0,0,0.5);
}

#instructions {
  width: 100%;
  height: 100%;

  display: -webkit-box;
  display: -moz-box;
  display: box;

  -webkit-box-orient: horizontal;
  -moz-box-orient: horizontal;
  box-orient: horizontal;

  -webkit-box-pack: center;
  -moz-box-pack: center;
  box-pack: center;

  -webkit-box-align: center;
  -moz-box-align: center;
  box-align: center;

  color: #ffffff;
  text-align: center;
  font-family: Arial;
  font-size: 14px;
  line-height: 24px;

  cursor: pointer;
}

#hint {
  position: absolute;
  top: 5px;
  right: 10px;
  color: #ddd;
  font-size: 10px;
  font-family: Arial;
  display: none;
}
              
            
!

JS

              
                
let particleSystem, particleCount, particles, controls, onKeyDown, onKeyUp, raycaster, scene, stats, camera;
let objects = [];
const lightColors = [
  '#2980b9',
  '#16a085',
  '#d35400',
  '#8e44ad',
  '#c0392b',
  '#2c3e50',
  '#b33939',
  '#218c74'
]
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;
let canJump = false;
let prevTime = performance.now();
let velocity = new THREE.Vector3();
let direction = new THREE.Vector3();
let vertex = new THREE.Vector3();
let color = new THREE.Color();
let clock = new THREE.Clock();



function setupStats() {
  stats = new Stats();
  stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
  document.body.appendChild( stats.dom );
}
function setupCamera() {
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
  camera.position.y = 10;
  camera.rotation.y = 180.65;
}
function setupScene() {
  scene = new THREE.Scene();
  scene.fog = new THREE.Fog(0x242426, 20, 250);
}
function setupRenderer() {
  renderer = new THREE.WebGLRenderer( { antialias: true } );
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize(window.innerWidth, window.innerHeight);

  renderer.setClearColor( 0x242426 );
  renderer.toneMapping = THREE.LinearToneMapping;
 
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  document.body.appendChild(renderer.domElement);
}
function setupControls() {
  raycaster = new THREE.Raycaster( new THREE.Vector3(), new THREE.Vector3( 0, - 1, 0 ), 0, 10 );
  
  let onKeyDown = function ( event ) {
    
   switch ( event.keyCode ) {
              case 27:
                moveForward = false;
                moveBackward = false;
                moveLeft = false;
                moveRight = false;
                break
              case 38: // up
              case 87: // w
                moveForward = true;
                break;
              case 37: // left
              case 65: // a
                moveLeft = true; break;
              case 40: // down
              case 83: // s
                moveBackward = true;
                break;
              case 39: // right
              case 68: // d
                moveRight = true;
                break;
              case 32: // space
                if ( canJump === true ) velocity.y += 350;
                canJump = false;
                break;
            }
  };
  let onKeyUp = function ( event ) {
    switch( event.keyCode ) {
      case 38: // up
      case 87: // w
        moveForward = false;
        break;
      case 37: // left
      case 65: // a
        moveLeft = false;
        break;
      case 40: // down
      case 83: // s
        moveBackward = false;
        break;
      case 39: // right
      case 68: // d
        moveRight = false;
        break;
    }
  };

  document.addEventListener( 'keydown', onKeyDown, false );
  document.addEventListener( 'keyup', onKeyUp, false );
  
  controls = new THREE.PointerLockControls( camera );
  
  let blocker = document.getElementById( 'blocker' );
  let instructions = document.getElementById( 'instructions' );
  let hint = document.getElementById( 'hint' );

  instructions.addEventListener( 'click', function () { controls.lock(); }, false );

  controls.addEventListener( 'lock', function () {
    instructions.style.display = 'none';
    blocker.style.display = 'none';
    hint.style.display = 'block';
  } );

  controls.addEventListener( 'unlock', function () {
    blocker.style.display = 'block';
    instructions.style.display = '';
    hint.style.display = 'none';
  } );
 
  scene.add( controls.getObject() );
 
}
function handleWindowResize() {
  window.addEventListener( 'resize', onWindowResize, false );
  function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );

  }
}
function snow() {
   let loader = new THREE.TextureLoader();
    loader.crossOrigin = '';
   particleCount = 15000;
   let pMaterial = new THREE.PointCloudMaterial({
      color: 0xFFFFFF,
      size: 1.5,
      map: loader.load(
         "https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/sprites/snowflake2.png"
       ),
       blending: THREE.AdditiveBlending,
       depthTest: false,
       transparent: true
    });

    particles = new THREE.Geometry;
    for (var i = 0; i < particleCount; i++) {
        var pX = Math.random()*500 - 250,
            pY = Math.random()*500 - 250,
            pZ = Math.random()*500 - 250,
            particle = new THREE.Vector3(pX, pY, pZ);
        particle.velocity = {};
        particle.velocity.y = 0;
        particles.vertices.push(particle);
    }
    particleSystem = new THREE.PointCloud(particles, pMaterial);
    particleSystem.position.x = 100;
    particleSystem.position.y = 100;
    scene.add(particleSystem);
}
function makeItSnow() {
    var pCount = particleCount;
    while (pCount--) {
    var particle = particles.vertices[pCount];
    if (particle.y < -200) {
      particle.y = 200;
      particle.velocity.y = 0;
    }
    particle.velocity.y -= Math.random() * .02;
    particle.y += particle.velocity.y;
    }
    particles.verticesNeedUpdate = true;
}
function ground() {  
  let geometry = new THREE.PlaneGeometry( 700, 600, 22, 12 );
  for (let i = 0; i < geometry.vertices.length; i++) {
    geometry.vertices[i].z = (Math.sin(i * i * i)+1/2) * 3;
  }
  geometry.verticesNeedUpdate = true;
  geometry.normalsNeedUpdate = true;
  geometry.computeFaceNormals(); 

  let material = new THREE.MeshPhongMaterial({ 
    color: 0xFFFFFF, 
    shininess: 60,
    bumpScale: 0.045,
    emissive: 0xEBF7FD,
    emissiveIntensity: 0.03,
  }); 

  let plane = new THREE.Mesh( geometry, material );
  plane.rotation.x = Math.PI / -2;
  plane.receiveShadow = true;
  plane.position.y = -5;

  scene.add(plane)
}
function light() {
    var ambientLight = new THREE.AmbientLight(0x222222);
    scene.add(ambientLight);
  
    let hemiLight = new THREE.HemisphereLight( 0xEBF7FD, 0xEBF7FD, 0.2 );
    hemiLight.color.setRGB(0.75,0.8,0.95);
    hemiLight.position.set( 0, 100, 0 );
    scene.add( hemiLight );
}
function createTree() {
  // tree
  var tree = new THREE.Group();
  var trunkGeometry = new THREE.CylinderBufferGeometry(5, 10, 50);
  var trunkMaterial = new THREE.MeshPhongMaterial({ color: 0x49311c });
  var trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
  tree.add(trunk);

  // leaves
  var leavesMaterial = new THREE.MeshPhongMaterial({ color: 0x3d5e3a });
 
  
  var leavesCone= new THREE.ConeBufferGeometry(20, 40, 6);
  var leavesBottom = new THREE.Mesh(leavesCone, leavesMaterial);
  leavesBottom.position.y = 35;
  tree.add(leavesBottom);

  addRingOfLights(leavesBottom, 15, 17, -15, 0)
  addRingOfLights(leavesBottom, 16, 16, -15,  Math.PI  / 4)
  addRingOfLights(leavesBottom, 10, 11, -3,  0)
  addRingOfLights(leavesBottom, 10, 11, -3,  Math.PI  / 4)

  
  var middleLeaveCone = new THREE.ConeBufferGeometry(15, 30, 6);    
  var leavesMiddle = new THREE.Mesh(middleLeaveCone, leavesMaterial );
  leavesMiddle.position.y = 55;
  tree.add(leavesMiddle);
  
  addRingOfLights(leavesMiddle, 10, 11, -8)
  addRingOfLights(leavesMiddle, 10, 11, -8, Math.PI  / 4)

  var topLeaveCone = new THREE.ConeBufferGeometry(10, 20, 6);  
  var leavesTop = new THREE.Mesh(topLeaveCone, leavesMaterial);
  leavesTop.position.y = 70;
  tree.add(leavesTop);
  
  addRingOfLights(leavesTop, 6, 6, -3)
  addRingOfLights(leavesTop, 6, 6, -3, Math.PI  / 4)
  
  return tree
}
function createForest() {
  let numOfTrees = 4;
  
  // Right Line of Trees
  for(let i = 0; i <= numOfTrees; i++) {
    placeTree(100, 0,40 * i + 40);
  }
  
  // Right Wall
  for(let i = 0; i <= numOfTrees + 1; i++) {
     placeTree(40 * i + 100, 0,40 * numOfTrees + 40);
  }
  
  // Right Back Wall
  for(let i = 0; i <= numOfTrees + 1; i++) {
    placeTree(40 * (numOfTrees + 1) + 100, 0, (40 * numOfTrees + 40) - (40 * i + 40));
  }
  
  // Left Line of Trees
  for(let i = 0; i <= numOfTrees; i++) {
    placeTree(100, 0, -(40 * i + 40));
  }
  
  // Left Wall of Trees
  for(let i = 0; i <= numOfTrees + 1; i++) {
     placeTree( 40 * i + 100, 0, -(40 * numOfTrees + 40));
  }
  
   // Left Wall Back of Trees
  for(let i = 0; i <= numOfTrees; i++) {
     placeTree(40 * (numOfTrees + 1) + 100 , 0, -(40 * numOfTrees + 40) + (40 * i + 40));
  }
   
  // Right Entrance
  placeTree(80, 0, 40);
  placeTree(60, 0, 40);
  placeTree(40, 0, 40);
  placeTree(20, 0, 40);
  placeTree(0, 0, 40);
  placeTree(-20, 0, 40);
  // Left Entrance
  placeTree(80, 0, -40);
  placeTree(60, 0, -40);
  placeTree(40, 0, -40);
  placeTree(20, 0, -40);
  placeTree(0, 0, -40);
  placeTree(-20, 0, -40);
  
  // Back of Entrance
  placeTree(-40, 0, -40);
  placeTree(-40, 0, -20);
  placeTree(-40, 0, 0);
  placeTree(-40, 0, 20);
  placeTree(-40, 0, 40);
    

}
function placeTree(x, y, z) {
  let newTree = createTree();
  newTree.position.y = y;
  newTree.position.x = x;
  newTree.position.z = z;
  scene.add(newTree);
  objects.push( newTree );
}
function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
function addRingOfLights(thing, left, right, y, rotation = 0) {
    let group = new THREE.Group();
    let light = christmasLight(left, y, 0, randomChristmasColor())  
    let light2 = christmasLight(-left, y, 0, randomChristmasColor())  
    let light3 = christmasLight(0, y, right, randomChristmasColor())  
    let light4 = christmasLight(0, y, -right, randomChristmasColor())  
    group.add( light );
    group.add( light2 );
    group.add( light3 );
    group.add( light4 );
    group.rotation.y = rotation;
    thing.add(group);
}
function randomChristmasColor() {
  const numOfLightColors = lightColors.length;
  const color = lightColors[getRandomInt(0, numOfLightColors - 1)];
  return color;
}
function christmasLight(x,y,z, color) {
  var bulbGeometry = new THREE.SphereBufferGeometry( 1, 16, 8 );
  bulbMat = new THREE.MeshStandardMaterial( {
    emissive:color || 0xffffee,
    emissiveIntensity: 3,
    color: color || 0x000000
  } );
  const bulbMesh = new THREE.Mesh( bulbGeometry, bulbMat );
  bulbMesh.position.set(x,y,z);
  return bulbMesh;
}
function createFireLight(color, power = 7){
  var light = new THREE.PointLight( color || 0xFFFFFF , 1, 0 );
  light.castShadow = true;
  light.shadow.mapSize.width = 512;
  light.shadow.mapSize.height = 512;
  light.shadow.camera.near = 0.1;
  light.shadow.camera.far = 120;
  light.shadow.bias = 0.9;
  light.shadow.radius = 5;
  light.power = power;

  return light;
}
function createFlame(x, y, z, color, outerColor, hasLight) {
  const fireLight = createFireLight(color);
  let geometry =  new THREE.ConeGeometry( .5, 4, 6, 10 );
  let material = new THREE.MeshPhongMaterial({ 
    color: color, 
    shininess: 550, 
    emissive: color,
    transparent: true,
    opacity: 0.4,
  });
   let flame = new THREE.Mesh( geometry, material );
  
  if(hasLight) flame.add(fireLight)

  flame.position.x = x;
  flame.position.y = 0;
  flame.position.z = z;
  
  let outerGeometry = new THREE.ConeGeometry( 1, 6, 6, 10 );
  let outerMaterial = new THREE.MeshPhongMaterial({ 
    color: outerColor, 
    shininess: 550, 
    emissive: outerColor,
    transparent: true,
    opacity: .4,
  });
  let outerFlame = new THREE.Mesh( outerGeometry, outerMaterial );
  flame.add(outerFlame)
  outerFlame.position.y =  1;
  
  return flame;
}
function createLog(x,y,z){
   let geometry = new THREE.CylinderBufferGeometry( 1, 1, 6, 8 );
   let material = new THREE.MeshPhongMaterial({ 
    color: 0x5C2626, 
    shininess: 10, 
    emissive: 0x5C2626,
  });
  var log = new THREE.Mesh( geometry, material );
  log.rotation.z = Math.PI / 2;
  log.position.x = x;
  log.position.y = y - 3;
  log.position.z = z;
  return log;
}
function campFire() {
  const log1 = createLog(172, 0, 0);
  log1.rotation.y = Math.PI / 2;
  const log2 = createLog(168, 0, 0);
  log2.rotation.y = Math.PI / 2;
  const log3 = createLog(170, 1, 2);
  const log4 = createLog(170, 1, -2);
  
  const flame1 = createFlame(172, 3, 0, 0xdb2902, 0xfb4402, false );
  const flame2 = createFlame(170, 3, 2, 0xdb2902, 0xfb4402 );
  const flame3 = createFlame(170, 3, -2, 0xdb2902, 0xfb4402 );
  const flame4 = createFlame(168, 3, 0, 0xdb2902, 0xfb4402, false );
  const flame5 = createFlame(170, 3, 0, 0xdb2902, 0xfb4402, true );
  flame5.scale.set(2,2,2);
  
  scene.add(flame1);
  scene.add(flame2);
  scene.add(flame3);
  scene.add(flame4);
  scene.add(flame5);
  
  scene.add(log1);
  scene.add(log2);
  scene.add(log3);
  scene.add(log4);
}
function snowman(x,y,z) {
  
  const snowMaterial = new THREE.MeshPhongMaterial({ 
    color: 0xFFFFFF, 
    shininess: 60,
    bumpScale: 0.045,
    emissive: 0xEBF7FD,
    emissiveIntensity: 0.03,
  }); 
  const bottomBall = new THREE.Mesh( new THREE.SphereBufferGeometry( 22, 32, 32 ) , snowMaterial );	
  bottomBall.position.set(x, y, z);
  bottomBall.rotation.y = - Math.PI / 2;
	
  
  const middleBall = new THREE.Mesh( new THREE.SphereBufferGeometry( 16, 32, 32 ) , snowMaterial );	
  middleBall.position.set(0, 24, 0);
	bottomBall.add(middleBall);

  
  const head = new THREE.Mesh( new THREE.SphereBufferGeometry( 12, 24, 24 ) , snowMaterial );
  head.position.y = 20;
  middleBall.add(head);

	
  const armMaterial = new THREE.MeshBasicMaterial( { color: 0x111111 , side:THREE.DoubleSide} );	
	const rightBicep = new THREE.Mesh( new THREE.CylinderBufferGeometry(1, 1, 22, 12, 1), armMaterial);
  rightBicep.position.x = 20;
	rightBicep.position.y = 5;
	rightBicep.rotation.z = Math.PI / 2;
	middleBall.add( rightBicep );
  
  const rightForearm = new THREE.Mesh( new THREE.CylinderBufferGeometry(1, 1, 15, 12, 1), armMaterial);
  rightForearm.position.x = 31;
	rightForearm.position.y = 12;
	rightForearm.rotation.z = Math.PI + .03;
  middleBall.add( rightForearm );
  
  const leftBicep = new THREE.Mesh( new THREE.CylinderBufferGeometry(1, 1, 22, 12, 1), armMaterial);
  leftBicep.position.x = -20;
  leftBicep.position.z = 10;
	leftBicep.position.y = 5;
	leftBicep.rotation.z = Math.PI / 2;
  leftBicep.rotation.y = Math.PI / 4;
	middleBall.add( leftBicep );
  
  const leftForearm = new THREE.Mesh( new THREE.CylinderBufferGeometry(1, 1, 15, 12, 1), armMaterial);
  leftForearm.position.x = -27;
  leftForearm.position.z = 22;
	leftForearm.position.y = 10;
	leftForearm.rotation.z = Math.PI + .03;
  leftForearm.rotation.x = Math.PI / 4;
  middleBall.add( leftForearm );
  
  const leftFinger = new THREE.Mesh( new THREE.CylinderBufferGeometry(.4, .4, 4, 12, 1), armMaterial);
  leftFinger.position.x = 0;
  leftFinger.position.z = 0;
	leftFinger.position.y = -9;
  leftForearm.add( leftFinger );
  
  const leftLeftFinger = new THREE.Mesh( new THREE.CylinderBufferGeometry(.4, .4, 5, 12, 1), armMaterial);
  leftLeftFinger.position.x = 2;
  leftLeftFinger.position.z = 0;
	leftLeftFinger.position.y = -8;
  leftLeftFinger.rotation.x = Math.PI / 8;
  leftLeftFinger.rotation.z = Math.PI / 8;
  leftForearm.add( leftLeftFinger );
  
  const leftRightFinger = new THREE.Mesh( new THREE.CylinderBufferGeometry(.4, .4, 5, 12, 1), armMaterial);
  leftRightFinger.position.x = -2;
  leftRightFinger.position.z = 0;
	leftRightFinger.position.y = -8;
  leftRightFinger.rotation.x = Math.PI / 8;
  leftRightFinger.rotation.z = -Math.PI / 8;
  leftForearm.add( leftRightFinger );

 
  const noseMaterial = new THREE.MeshPhongMaterial({ 
    color: 0xff1133, 
    shininess: 60,
    bumpScale: 0.045,
    emissive: 0xff1133,
    emissiveIntensity: 0.03,
  }); 
	const nose = new THREE.Mesh(new THREE.CylinderBufferGeometry(0.5, 2.5, 8, 12, 4), noseMaterial);
  nose.position.z = 15;
	nose.rotation.x = 1.6;
  nose.rotation.y = -1;
	head.add(nose);
  
  const eyeMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
	const leftEye = new THREE.Mesh( new THREE.CylinderBufferGeometry(1.75, 1.75, 2, 12, 1), eyeMaterial); 	
  leftEye.rotation.x = 1.57;
	leftEye.position.set(5,3,11);	
	head.add(leftEye)

	const rightEye = leftEye.clone();
  rightEye.rotation.x = 1.57;
	rightEye.position.set(-5,3,11);
	head.add(rightEye);
  
  snowmanHat = topHat(0, 12, 0);
  head.add(snowmanHat);
  
  objects.push(bottomBall);
  return bottomBall;
}
function topHat(x = 0, y = 0, z = 0, brimY = -5) {
  let hatMaterial = new THREE.MeshBasicMaterial( { color: 0x111111 , side:THREE.DoubleSide} );	
  let hat = new THREE.Mesh( new THREE.CylinderGeometry(10, 10, 14, 12, 1), hatMaterial); 
  hat.position.x = x;
	hat.position.y = y;
  hat.position.z = z;
  
  
	let brim = new THREE.Mesh( new THREE.RingGeometry( 10, 16, 24, 1 ), hatMaterial);
	hat.add( brim );
	brim.position.y = brimY;
	brim.rotation.x = 1.57;	
  
  return hat;
}
function createSnowmen() {
  const mainSnowman = snowman(220, 10, 0);
  scene.add(mainSnowman);
  
  const glowingGlobe = christmasLight(193, 53, -27);
  glowingGlobe.scale.x = 3;
  glowingGlobe.scale.y = 3;
  glowingGlobe.scale.z = 3;
  scene.add(glowingGlobe)
  
  const rightSnowman = snowman(215, 7, 50);
  rightSnowman.scale.x = .75;
  rightSnowman.scale.y = .75;
  rightSnowman.scale.z = .75;
  scene.add(rightSnowman)
  
  const glowingGlobe2 = christmasLight(195, 39, 30);
  glowingGlobe2.scale.x = 2;
  glowingGlobe2.scale.y = 2;
  glowingGlobe2.scale.z = 2;
  scene.add(glowingGlobe2)
  
  const leftSnowman = snowman(210, 7, -45);
  leftSnowman.scale.x = .5;
  leftSnowman.scale.y = .5;
  leftSnowman.scale.z = .5;
  scene.add(leftSnowman)
  
  const glowingGlobe3 = christmasLight(197, 28, -59);
  glowingGlobe2.scale.x = 1.25;
  glowingGlobe2.scale.y = 1.25;
  glowingGlobe2.scale.z =  1.25;
  scene.add(glowingGlobe3)
  
 
}
function createTopHats() {
  snowmanHat1 = topHat(128, 1, -50);
  snowmanHat1.scale.set(.25, .25, .25);
  snowmanHat2 = topHat(130, 2, -70);
  snowmanHat2.scale.set(.5, .5, .5);
  snowmanHat3 = topHat(140, 4, -100);  
  snowmanHat4 = topHat(170, 6, -130);
  snowmanHat4.scale.set(1.5, 1.5, 1.5);
  snowmanHat5 = topHat(240, 15, -140, -7);
  snowmanHat5.scale.set(2, 2, 2);
  
  
  snowmanHat6 = topHat(128, 1, 50);
  snowmanHat6.scale.set(.25, .25, .25);
  snowmanHat7 = topHat(130, 2, 70);
  snowmanHat7.scale.set(.5, .5, .5);
  snowmanHat8 = topHat(140, 4, 100);  
  snowmanHat9 = topHat(170, 6, 130);
  snowmanHat9.scale.set(1.5, 1.5, 1.5);
  snowmanHat10 = topHat(240, 15, 140, -7);
  snowmanHat10.scale.set(2, 2, 2);
  
  
  scene.add(snowmanHat1);
  scene.add(snowmanHat2);
  scene.add(snowmanHat3);
  scene.add(snowmanHat4);
  scene.add(snowmanHat5);
  scene.add(snowmanHat6);
  scene.add(snowmanHat7);
  scene.add(snowmanHat8);
  scene.add(snowmanHat9);
  scene.add(snowmanHat10);
  objects.push(snowmanHat1, snowmanHat2 ,snowmanHat3, snowmanHat4, snowmanHat5, snowmanHat6, snowmanHat7, snowmanHat8, snowmanHat9, snowmanHat10)
}
function animate() {
  requestAnimationFrame( animate );
  stats.begin();
  particleSystem.rotation.y += 0.01;
  makeItSnow();
 
  if ( controls.isLocked === true ) {
    raycaster.ray.origin.copy( controls.getObject().position );
	  raycaster.ray.origin.y -= 10;
    
  	var intersections = raycaster.intersectObjects( objects );
    var onObject = intersections.length > 0;
    var time = performance.now();
    var delta = ( time - prevTime ) / 1000;
    velocity.x -= velocity.x * 10.0 * delta;
    velocity.z -= velocity.z * 10.0 * delta;
    velocity.y -= 9.8 * 100.0 * delta; // 100.0 = mass
    direction.z = Number( moveForward ) - Number( moveBackward );
    direction.x = Number( moveRight ) - Number( moveLeft );
    direction.normalize(); // this ensures consistent movements in all directions

    if ( moveForward || moveBackward ) velocity.z -= direction.z * 400.0 * delta;
    if ( moveLeft || moveRight ) velocity.x -= direction.x * 400.0 * delta;

    if ( onObject === true ) {
      velocity.y = Math.max( 0, velocity.y );
      canJump = true;
    }

    controls.moveRight( - velocity.x * delta );
    controls.moveForward( - velocity.z * delta );
    controls.getObject().position.y += ( velocity.y * delta ); // new behavior

    if ( controls.getObject().position.y < 10 ) {
      velocity.y = 0;
      controls.getObject().position.y = 10;
      canJump = true;
    }

    prevTime = time;

  	stats.end();
  } else {
    // Prevent Player from continuing if esc and forward at the same time
    velocity.x = 0;
    velocity.z = 0;
    controls.moveRight(0);
    controls.moveForward( 0 );
    moveForward = false;
    moveBackward = false;
    moveLeft = false;
    moveRight = false;
  }
  render();
}
function render() {
  renderer.render( scene, camera );
}
const init = () => {
  setupStats();
  setupCamera();
  setupScene();
  setupRenderer();
  setupControls();
  handleWindowResize();
  ground();
  createForest();
  snow();
  light();
  campFire();
  createSnowmen();
  createTopHats();
}



init();
animate();



              
            
!
999px

Console