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

              
                <!-- World container - Renderer is placed here -->
<html>

<div id="world">

  <h1 class="gameholder"> 
Dodge the asteroids!
<div id="hitlabel" style="margin-top:0; font-size:16px" >Damage sustained: 0</div>
<div id="time" style="margin-top:0; font-size:16px" >Time: 0</div>
</h1>


</div>

</html>
              
            
!

CSS

              
                html,
body {
  margin: 0; //Remove default margins
  padding: 0;
}

#world {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: linear-gradient(#ffffff, #ffffff);
}

html,
body {
  margin: 0; //Remove default margins
  padding: 0;
}

.gameholder {
  position: absolute;
  text-align: center;
  width: 100%;
  color: white;
  margin-bottom: 0;
  padding-bottom: 0;
}

              
            
!

JS

              
                //Essential setup variables
var scene;
var renderer;
var container;

//Window constants
var HEIGHT = window.innerHeight;
var WIDTH = window.innerWidth;
var aspectRatio = WIDTH / HEIGHT;
var fieldOfView = 60;
var nearPlane = 1;
var farPlane = 10000;

//Lighting
var hemisphereLight, shadowLight, ambientLight;

//Scene variables (specific to sample) ----
var cube, cube2;

var mousePos = {
  x: 0,
  y: 0,
  targetx: 0,
  targety: 0,
  originalx: 0,
  originaly: 0
};

var Colors = {
  red: 0xf25346,
  white: 0xd8d0d1,
  brown: 0x59332e,
  pink: 0xf5986e,
  brownDark: 0x23190f,
  blue: 0x68c3c0
};

//Texture loading - recommended (but more complicated) to be done before use
var textures = {
  stone: {
    url:
      "https://cdn.rawgit.com/antu3199/WebAssets/master/textures/stonePattern.jpg"
  },
  stoneBump: {
    url: "https://cdn.rawgit.com/antu3199/WebAssets/master/textures/normal2.jpg"
  },
  space: {
    url: "https://cdn.rawgit.com/antu3199/WebAssets/master/textures/space.jpg"
  }
};

var texturesLoaded = 0; //Counts number of loaded textures for determining when to start

var player;

var models = {
  player: {
    url: "https://api.myjson.com/bins/64cgn",
    mesh: null
  }
};

var modelsLoaded = 0;
var tunnel;

var particles;
var particlesHolder;
var particlesPool = [];

var newTime = 0;
var deltaTime = 1;
var oldTime = 0;

var label;
var times_hit = 0;
var curTime = 0;
var timelabel;

var isMobile = window.innerWidth < 500;

var audio;

//Main function:
function init() {
  loadTexturesAndStart(); //must load before creating scene
}

//Foreach texture, load, and then check if completed
function loadTexturesAndStart() {
  var loader = new THREE.TextureLoader(); //Textures must be loaded via TextureLoader

  //Prevent crossorigin issue
  loader.crossOrigin = "anonymous";

  //Load textures one by one (for a loading screen) - searches for .url tag, and adds a .texture field to the object
  for (var name in textures) {
    (function(name) {
      loader.load(textures[name].url, function(texture) {
        textures[name].texture = texture;
        checkLoadingTexturesFinished();
      });
    })(name);
  }
}

//Check if loading completed, if yes then createScene()!
function checkLoadingTexturesFinished() {
  texturesLoaded++;
  if (texturesLoaded == Object.keys(textures).length) {
    //Object.keys gives an array of the keys
    loadOBJsAndStart();
    // createScene();
  }
}
//Note: In blender, be sure to check Type: Geometry, and Textures: true

function loadOBJsAndStart() {
  var modelLoader = new THREE.JSONLoader();

  for (var name in models) {
    (function(name) {
      modelLoader.load(models[name].url, function(geometry, materials) {
        mesh = new THREE.Mesh(geometry, materials);
        models[name].mesh = mesh;
        checkModelsLoadingFinished();
      });
    })(name);
  }
}

function checkModelsLoadingFinished() {
  modelsLoaded++;
  if (modelsLoaded == Object.keys(models).length) {
    //Object.keys gives an array of the keys
    document.body.classList.remove("loading");
    createScene();
  }
}

//Real scene init function
function createScene() {
  initalizeScene();
  createLights();
  loadPlayer();
  createSpline();
  player.mesh.lookAt(tunnel.curve.points[4]);
  player.initalPos = player.mesh.rotation.clone();

  addParticles();
  createHTMLLabels();
  createAudio();
  document.addEventListener("mousemove", handleMouseMove, false); //Add mouse listener
  document.addEventListener("touchmove", handleTouchMove, false);

  loop(); //Main Game Loop
}
function createHTMLLabels() {
  label = document.getElementById("hitlabel");
  label.innerHTML = "Damage sustained: " + times_hit;
  timelabel = document.getElementById("time");
}

function createAudio() {
  var audioLoader = new THREE.AudioLoader();
  var listener = new THREE.AudioListener();
  camera.add(listener);
  var audio = new THREE.Audio(listener);
  audioLoader.load("sounds/space.mp3", function(buffer) {
    audio.setBuffer(buffer);
    audio.setLoop(true);
    audio.play();
    audio.setVolume(0.5);
  });
}

Player = function() {
  this.ZDistance = 10;
  this.originalZDistance = this.ZDistance;

  this.mesh = models.player.mesh;
  //Color intensity, distance
  var light = new THREE.PointLight(0xffffff, 1, 100);
  light.position.set(0, 1, 0);
  this.mesh.add(light);

  this.collisionDisplacementX = 0;
  this.collisionDisplacementY = 0;
  this.collisionDisplacementZ = 0;

  this.collisionSpeedX = 0;
  this.collisionSpeedY = 0;
  this.collisionSpeedZ = 0;

  this.recoverySpeed = 0.03;
  this.recoveryDisplacement = 0.01;
};

function loadPlayer() {
  player = new Player();
  //	player.mesh.scale.set(10, 10, 10);

  scene.add(player.mesh);
}

//Initalizes the camera and the renderer
function initalizeScene() {
  scene = new THREE.Scene(); //Create scene - used to add objects inside
  scene.fog = new THREE.Fog(0xd387ff, 100, 950); //Fog( hex, near, far )

  //Create camera
  camera = new THREE.PerspectiveCamera(
    fieldOfView, //Constants at the top of the file
    aspectRatio,
    nearPlane,
    farPlane
  );

  camera.position.x = 0;
  camera.position.z = 200;
  camera.position.y = 0;

  //Create renderer
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
  renderer.setSize(WIDTH, HEIGHT);
  renderer.shadowMap.enabled = true;

  //Attach renderer to container in html
  container = document.getElementById("world");
  container.appendChild(renderer.domElement);

  window.addEventListener("resize", handleWindowResize, false); //Handle resizing
}

// Handle window resizing
function handleWindowResize() {
  HEIGHT = window.innerHeight;
  WIDTH = window.innerWidth;
  renderer.setSize(WIDTH, HEIGHT);
  camera.aspect = WIDTH / HEIGHT;
  camera.updateProjectionMatrix();
}

function createLights() {
  //DirectionalLight (color, intensity)
  shadowLight = new THREE.DirectionalLight(0xffffff, 0.9);
  shadowLight.position.set(150, 350, 350); // Set the direction of the light
  shadowLight.castShadow = true; // Allow shadow casting

  //define the visible area of the projected shadowLight
  shadowLight.shadow.camera.left = -400;
  shadowLight.shadow.camera.right = 400;
  shadowLight.shadow.camera.top = 400;
  shadowLight.shadow.camera.bottom = -400;
  shadowLight.shadow.camera.near = 1;
  shadowLight.shadow.camera.far = 1000;

  //Ambient lighting
  //An ambient light modifies the global colour of a scene and makes the shadows softer
  ambientLight = new THREE.AmbientLight(0x6600cc, 0.7);

  //Activate lights - just add them to the scene
  //	scene.add(hemisphereLight);
  scene.add(shadowLight);
  scene.add(ambientLight);
}

//Adding a cube to the scene ---
//Cube object definiton
myCube = function(isUsingMaterial) {
  this.mesh = new THREE.Object3D();

  var cubeGeom = new THREE.BoxGeometry(45, 45, 45); //BoxGeometry(size-x, size-y, size-z)

  var cubeMat;
  if (isUsingMaterial == false) {
    //Regular flat shading material
    cubeMat = new THREE.MeshPhongMaterial({
      color: Colors.brown,
      flatShading: true
    });
  } else {
    //Material using loaded texture
    cubeMat = new THREE.MeshStandardMaterial({
      map: textures.stone.texture,
      bumpMap: textures.stoneBump.texture,
      bumpScale: 0.0003
    });
    // Repeat the pattern
    cubeMat.map.wrapS = THREE.RepeatWrapping;
    cubeMat.map.wrapT = THREE.RepeatWrapping;
    cubeMat.map.repeat.set(2, 2); //Value = # of repetitions in (x = s) / (y = t)
    cubeMat.bumpMap.wrapS = THREE.RepeatWrapping;
    cubeMat.bumpMap.wrapT = THREE.RepeatWrapping;
    cubeMat.bumpMap.repeat.set(2, 2);
  }

  var cubeMesh = new THREE.Mesh(cubeGeom, cubeMat); //create mesh
  this.mesh.add(cubeMesh); //add mesh to Object3D() container

  this.mesh.receiveShadow = true;
  this.mesh.castShadow = true;
};

function handleMouseMove(event) {
  var tx = -1 + event.clientX / WIDTH * 2; //Convert mouse position to values from -1 to 1

  var ty = 1 - event.clientY / HEIGHT * 2; //2D y-axis goes opposite direction of 3D y-axis
  mousePos.originalx = tx;
  mousePos.originaly = ty;
  mousePos.targetx = tx;
  mousePos.targety = ty;
}
function handleTouchMove(event) {
  var tx = -1 + event.touches[0].pageX / WIDTH * 2;
  var ty = 1 - event.touches[0].pageY / HEIGHT * 2;
  mousePos.originalx = tx;
  mousePos.originaly = ty;
  mousePos.targetx = tx;
  mousePos.targety = ty;
}

function playerMovement() {
  player.collisionDisplacementX += player.collisionSpeedX;
  player.collisionDisplacementY += player.collisionSpeedY;
  player.ZDistance += player.collisionSpeedZ;

  mousePos.targetx += player.collisionDisplacementX;
  mousePos.targety += player.collisionDisplacementY;

  this.collisionSpeedX = 0;
  this.collisionSpeedY = 0;

  mousePos.x += (mousePos.targetx - mousePos.x) / 10;
  mousePos.y += (mousePos.targety - mousePos.y) / 10;
  player.ZDistance += (player.originalZDistance - player.ZDistance) / 10;

  playerFollowCursor();

  //Recovery displacement
  player.collisionSpeedX +=
    -player.collisionSpeedX * deltaTime * player.recoverySpeed;
  player.collisionSpeedY +=
    -player.collisionSpeedY * deltaTime * player.recoverySpeed;
  player.collisionSpeedZ += -player.collisionSpeedZ * deltaTime * 0.001;

  player.collisionDisplacementX +=
    -player.collisionDisplacementX * deltaTime * player.recoveryDisplacement;

  player.collisionDisplacementY +=
    -player.collisionDisplacementY * deltaTime * player.recoveryDisplacement;
  player.collisionDisplacementZ +=
    -player.collisionDisplacementZ *
    deltaTime *
    player.recoveryDisplacement *
    0.001;

  if (player.collisionDisplacementX < 0.01) {
    mousePos.targetx = mousePos.originalx;
  }
  if (player.collisionDisplacementY < 0.01) {
    mousePos.targety = mousePos.originaly;
  }
  if (player.collisionDisplacementZ < 0.01) {
    player.ZDistance = player.originalZDistance;
  }

  player.mesh.rotation.x +=
    (player.initalPos.x - player.mesh.rotation.x) * deltaTime * 0.005;
  player.mesh.rotation.y +=
    (player.initalPos.y - player.mesh.rotation.y) * deltaTime * 0.005;

  updateCameraPosition();
}

function playerFollowCursor() {
  var vector = new THREE.Vector3(mousePos.x, mousePos.y, 0.5);
  vector.unproject(camera);
  var dir = vector.sub(camera.position).normalize();
  var pos = camera.position.clone().add(dir.multiplyScalar(player.ZDistance));
  player.mesh.position.copy(pos);
}

function updateCameraPosition() {
  // Rotate Z & Y axis
  camera.rotation.z = mousePos.x * 0.2;
  camera.rotation.y = -mousePos.x * 0.1;
  // Move a bit the camera horizontally & vertically
  camera.position.x = mousePos.x * 0.015;
  camera.position.y = -mousePos.y * 0.015;
}

Tunnel = function() {
  this.tunnelSpeed = 0.05;
  var points = [];
  // Define points along Z axis to create a curve
  for (var i = 0; i < 5; i += 1) {
    points.push(new THREE.Vector3(0, 0, 200 - 1000 * (i / 4)));
  }
  // Set custom Y position for the last point
  points[4].y = -0.06;

  // Create a curve based on the points
  this.curve = new THREE.CatmullRomCurve3(points);
  // Empty geometry
  var geometry = new THREE.Geometry();
  // Create vertices based on the curve
  geometry.vertices = this.curve.getPoints(70);
  // Create a line from the points with a basic line material
  this.splineMesh = new THREE.Line(geometry, new THREE.LineBasicMaterial());

  // Create a material for the tunnel with a custom texture
  // Set side to BackSide since the camera is inside the tunnel
  this.tubeMaterial = new THREE.MeshPhongMaterial({
    side: THREE.BackSide,
    map: textures.space.texture
    // color:0xcc00ff
  });

  this.tubeMaterial.map.wrapS = THREE.RepeatWrapping;
  this.tubeMaterial.map.wrapT = THREE.RepeatWrapping;
  this.tubeMaterial.map.repeat.set(5, 1);

  // Create a tube geometry based on the curve
  this.tubeGeometry = new THREE.TubeGeometry(this.curve, 70, 150, 50, false);
  // Create a mesh based on the tube geometry and its material
  this.tubeMesh = new THREE.Mesh(this.tubeGeometry, this.tubeMaterial);
};

//Particle creation and movement (specifics not important)
function Particle() {
  this.radius = Math.random() * 4 + 0.2;
  var geom = new THREE.IcosahedronBufferGeometry(1, 0);
  var random = Math.random();
  geom = new THREE.SphereBufferGeometry(1, 6, 6);

  var range = 50;
  var offset = 180;
  this.color = new THREE.Color(
    "hsl(" + (Math.random() * range + offset) + ",100%,80%)"
  );
  var mat = new THREE.MeshPhongMaterial({
    color: this.color,
    flatShading: true
  });
  this.mesh = new THREE.Mesh(geom, mat);
  this.mesh.scale.set(this.radius, this.radius, this.radius);
  this.mesh.position.set(0, 0, tunnel.curve.points[4] - 100);
  this.percent = Math.random(); //burst is when holding click ?
  this.offset = new THREE.Vector3(
    -15 + Math.random() * 30,
    -15 + Math.random() * 30,
    300
  ); //end of tunnel
  this.speed = Math.random() * 0.05 + 0.001; //random speed
  this.rotate = new THREE.Vector3(
    -Math.random() * 0.1 + 0.01,
    Math.random() * 0.01
  );
  this.pos = new THREE.Vector3(0, 0, 0);

  scene.add(this.mesh);
}

function addParticles() {
  particles = [];
  for (var i = 0; i < (isMobile ? 100 : 160); i++) {
    particles.push(new Particle());
  }
  particlesHolder = new ParticlesHolder();
  scene.add(particlesHolder.mesh);
}

function updateParticles() {
  for (var i = 0; i < particles.length; i++) {
    particles[i].update(this);
  }
}

Particle.prototype.update = function() {
  this.percent += this.speed * tunnel.tunnelSpeed; //Percent = speed * (1 or tunnel.speed)

  this.pos = tunnel.curve.getPoint(1 - this.percent % 1).add(this.offset); //offset = end position (behind camera)
  //Note: Mod 1 makes it loop
  this.mesh.position.x = this.pos.x;
  this.mesh.position.y = this.pos.y;
  this.mesh.position.z = this.pos.z;
  this.mesh.rotation.x += this.rotate.x;
  this.mesh.rotation.y += this.rotate.y;
  this.mesh.rotation.z += this.rotate.z;

  //collision detection
  var diffPos = player.mesh.position.clone().sub(this.mesh.position.clone());
  var distance = diffPos.length(); //Distance
  if (distance < this.radius) {
    player.collisionSpeedX = Math.random() * 1 * diffPos.x / distance;
    player.collisionSpeedY = Math.random() * 1 * diffPos.y / distance;
    player.mesh.rotation.x += Math.random() * -(diffPos.y / distance) * 20;
    player.mesh.rotation.y += Math.random() * (diffPos.x / distance) * 20;
    player.collisionSpeedZ = -10;

    particlesHolder.spawnParticles(
      this.mesh.position.clone(),
      25,
      this.color,
      1
    );
    times_hit++;
    label.innerHTML = "Damage sustained: " + times_hit;
  }
};

function createSpline() {
  tunnel = new Tunnel();
  scene.add(tunnel.tubeMesh);
}

function updateTunnel() {
  tunnel.tubeMaterial.map.offset.x += tunnel.tunnelSpeed;
  tunnel.tubeMaterial.map.offset.y += tunnel.tunnelSpeed * 0.01;
}

//Particle explosion
ParticlesHolder = function() {
  this.mesh = new THREE.Object3D();
  this.particlesInUse = [];
};

ParticlesHolder.prototype.spawnParticles = function(
  pos,
  density,
  color,
  scale
) {
  var particle = new Particle();

  var nParticles = density;

  for (var i = 0; i < nParticles; i++) {
    var particle;
    if (particlesPool.length) {
      particle = particlesPool.pop();
    } else {
      particle = new Particle();
    }
    this.mesh.add(particle.mesh);
    particle.mesh.position.set(pos.x, pos.y, pos.z);
    var randScale = 0.1 + scale * Math.random();
    particle.mesh.scale.set(randScale, randScale, randScale);
    particle.explode(pos, color, scale);
  }
};

Particle.prototype.explode = function(pos, color, scale) {
  var _this = this;
  var _p = this.mesh.parent;
  this.mesh.material.color = new THREE.Color(color);
  this.mesh.material.needsUpdate = true;

  var targetX = pos.x + (-1 + Math.random() * 2) * 10;
  var targetY = pos.y + (-1 + Math.random() * 2) * 10;
  var targetZ = pos.z + (-1 + Math.random() * 2) * 10;

  var speed = 2 + Math.random() * 0.2;

  TweenMax.to(this.mesh.rotation, speed, {
    x: Math.random() * 12,
    y: Math.random() * 12
  });

  TweenMax.to(this.mesh.scale, speed, { x: 0, y: 0, z: 0 });

  TweenMax.to(this.mesh.position, speed, {
    x: targetX,
    y: targetY,
    z: targetZ,
    delay: Math.random() * 0.1,
    ease: Power2.easeOut,
    onComplete: function() {
      if (_p) _p.remove(_this.mesh);
      _this.mesh.scale.set(1, 1, 1);
      _p.percent = 0;
      particlesPool.unshift(_this);
    }
  });
};

//Render loop
function loop() {
  if (deltaTime < 100000) {
    curTime += deltaTime;
    timelabel.innerHTML = "Time: " + Math.floor(curTime / 1000);
  }

  newTime = new Date().getTime();
  deltaTime = newTime - oldTime;
  oldTime = newTime;

  playerMovement();
  updateTunnel();
  updateParticles();

  renderer.render(scene, camera); // render the scene

  window.requestAnimationFrame(loop); // call the loop function again
}

init();

              
            
!
999px

Console