//THREEJS RELATED VARIABLES var scene, camera, fieldOfView, aspectRatio, nearPlane, farPlane, gobalLight, shadowLight, backLight, renderer, container, controls, clock; var delta = 0; var floorRadius = 200; var speed = 6; var distance = 0; var level = 1; var levelInterval; var levelUpdateFreq = 3000; var initSpeed = 5; var maxSpeed = 48; var monsterPos = .65; var monsterPosTarget = .65; var floorRotation = 0; var collisionObstacle = 10; var collisionBonus = 20; var gameStatus = "play"; var cameraPosGame = 160; var cameraPosGameOver = 260; var monsterAcceleration = 0.004; var malusClearColor = 0xb44b39; var malusClearAlpha = 0; var audio = new Audio('https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/Antonio-Vivaldi-Summer_01.mp3'); var fieldGameOver, fieldDistance; //SCREEN & MOUSE VARIABLES var HEIGHT, WIDTH, windowHalfX, windowHalfY, mousePos = { x: 0, y: 0 }; //3D OBJECTS VARIABLES var hero; // Materials var blackMat = new THREE.MeshPhongMaterial({ color: 0x100707, shading:THREE.FlatShading, }); var brownMat = new THREE.MeshPhongMaterial({ color: 0xb44b39, shininess:0, shading:THREE.FlatShading, }); var greenMat = new THREE.MeshPhongMaterial({ color: 0x7abf8e, shininess:0, shading:THREE.FlatShading, }); var pinkMat = new THREE.MeshPhongMaterial({ color: 0xdc5f45,//0xb43b29,//0xff5b49, shininess:0, shading:THREE.FlatShading, }); var lightBrownMat = new THREE.MeshPhongMaterial({ color: 0xe07a57, shading:THREE.FlatShading, }); var whiteMat = new THREE.MeshPhongMaterial({ color: 0xa49789, shading:THREE.FlatShading, }); var skinMat = new THREE.MeshPhongMaterial({ color: 0xff9ea5, shading:THREE.FlatShading }); // OTHER VARIABLES var PI = Math.PI; //INIT THREE JS, SCREEN AND MOUSE EVENTS function initScreenAnd3D() { HEIGHT = window.innerHeight; WIDTH = window.innerWidth; windowHalfX = WIDTH / 2; windowHalfY = HEIGHT / 2; scene = new THREE.Scene(); scene.fog = new THREE.Fog(0xd6eae6, 160,350); aspectRatio = WIDTH / HEIGHT; fieldOfView = 50; nearPlane = 1; farPlane = 2000; camera = new THREE.PerspectiveCamera( fieldOfView, aspectRatio, nearPlane, farPlane ); camera.position.x = 0; camera.position.z = cameraPosGame; camera.position.y = 30; camera.lookAt(new THREE.Vector3(0, 30, 0)); renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setClearColor( malusClearColor, malusClearAlpha); renderer.setSize(WIDTH, HEIGHT); renderer.shadowMap.enabled = true; container = document.getElementById('world'); container.appendChild(renderer.domElement); window.addEventListener('resize', handleWindowResize, false); document.addEventListener('mousedown', handleMouseDown, false); document.addEventListener("touchend", handleMouseDown, false); /* controls = new THREE.OrbitControls(camera, renderer.domElement); //controls.minPolarAngle = -Math.PI / 2; //controls.maxPolarAngle = Math.PI / 2; //controls.noZoom = true; controls.noPan = true; //*/ clock = new THREE.Clock(); } function handleWindowResize() { HEIGHT = window.innerHeight; WIDTH = window.innerWidth; windowHalfX = WIDTH / 2; windowHalfY = HEIGHT / 2; renderer.setSize(WIDTH, HEIGHT); camera.aspect = WIDTH / HEIGHT; camera.updateProjectionMatrix(); } function handleMouseDown(event){ if (gameStatus == "play") hero.jump(); else if (gameStatus == "readyToReplay"){ replay(); } } function createLights() { globalLight = new THREE.AmbientLight(0xffffff, .9); shadowLight = new THREE.DirectionalLight(0xffffff, 1); shadowLight.position.set(-30, 40, 20); shadowLight.castShadow = true; 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 = 2000; shadowLight.shadow.mapSize.width = shadowLight.shadow.mapSize.height = 2048; scene.add(globalLight); scene.add(shadowLight); } function createFloor() { floorShadow = new THREE.Mesh(new THREE.SphereGeometry(floorRadius, 50, 50), new THREE.MeshPhongMaterial({ color: 0x7abf8e, specular:0x000000, shininess:1, transparent:true, opacity:.5 })); //floorShadow.rotation.x = -Math.PI / 2; floorShadow.receiveShadow = true; floorGrass = new THREE.Mesh(new THREE.SphereGeometry(floorRadius-.5, 50, 50), new THREE.MeshBasicMaterial({ color: 0x7abf8e })); //floor.rotation.x = -Math.PI / 2; floorGrass.receiveShadow = false; floor = new THREE.Group(); floor.position.y = -floorRadius; floor.add(floorShadow); floor.add(floorGrass); scene.add(floor); } Hero = function() { this.status = "running"; this.runningCycle = 0; this.mesh = new THREE.Group(); this.body = new THREE.Group(); this.mesh.add(this.body); var torsoGeom = new THREE.CubeGeometry(7, 7, 10, 1); this.torso = new THREE.Mesh(torsoGeom, brownMat); this.torso.position.z = 0; this.torso.position.y = 7; this.torso.castShadow = true; this.body.add(this.torso); var pantsGeom = new THREE.CubeGeometry(9, 9, 5, 1); this.pants = new THREE.Mesh(pantsGeom, whiteMat); this.pants.position.z = -3; this.pants.position.y = 0; this.pants.castShadow = true; this.torso.add(this.pants); var tailGeom = new THREE.CubeGeometry(3, 3, 3, 1); tailGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0,0,-2)); this.tail = new THREE.Mesh(tailGeom, lightBrownMat); this.tail.position.z = -4; this.tail.position.y = 5; this.tail.castShadow = true; this.torso.add(this.tail); this.torso.rotation.x = -Math.PI/8; var headGeom = new THREE.CubeGeometry(10, 10, 13, 1); headGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0,0,7.5)); this.head = new THREE.Mesh(headGeom, brownMat); this.head.position.z = 2; this.head.position.y = 11; this.head.castShadow = true; this.body.add(this.head); var cheekGeom = new THREE.CubeGeometry(1, 4, 4, 1); this.cheekR = new THREE.Mesh(cheekGeom, pinkMat); this.cheekR.position.x = -5; this.cheekR.position.z = 7; this.cheekR.position.y = -2.5; this.cheekR.castShadow = true; this.head.add(this.cheekR); this.cheekL = this.cheekR.clone(); this.cheekL.position.x = - this.cheekR.position.x; this.head.add(this.cheekL); var noseGeom = new THREE.CubeGeometry(6, 6, 3, 1); this.nose = new THREE.Mesh(noseGeom, lightBrownMat); this.nose.position.z = 13.5; this.nose.position.y = 2.6; this.nose.castShadow = true; this.head.add(this.nose); var mouthGeom = new THREE.CubeGeometry(4, 2, 4, 1); mouthGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0,0,3)); mouthGeom.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI/12)); this.mouth = new THREE.Mesh(mouthGeom, brownMat); this.mouth.position.z = 8; this.mouth.position.y = -4; this.mouth.castShadow = true; this.head.add(this.mouth); var pawFGeom = new THREE.CubeGeometry(3,3,3, 1); this.pawFR = new THREE.Mesh(pawFGeom, lightBrownMat); this.pawFR.position.x = -2; this.pawFR.position.z = 6; this.pawFR.position.y = 1.5; this.pawFR.castShadow = true; this.body.add(this.pawFR); this.pawFL = this.pawFR.clone(); this.pawFL.position.x = - this.pawFR.position.x; this.pawFL.castShadow = true; this.body.add(this.pawFL); var pawBGeom = new THREE.CubeGeometry(3,3,6, 1); this.pawBL = new THREE.Mesh(pawBGeom, lightBrownMat); this.pawBL.position.y = 1.5; this.pawBL.position.z = 0; this.pawBL.position.x = 5; this.pawBL.castShadow = true; this.body.add(this.pawBL); this.pawBR = this.pawBL.clone(); this.pawBR.position.x = - this.pawBL.position.x; this.pawBR.castShadow = true; this.body.add(this.pawBR); var earGeom = new THREE.CubeGeometry(7, 18, 2, 1); earGeom.vertices[6].x+=2; earGeom.vertices[6].z+=.5; earGeom.vertices[7].x+=2; earGeom.vertices[7].z-=.5; earGeom.vertices[2].x-=2; earGeom.vertices[2].z-=.5; earGeom.vertices[3].x-=2; earGeom.vertices[3].z+=.5; earGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0,9,0)); this.earL = new THREE.Mesh(earGeom, brownMat); this.earL.position.x = 2; this.earL.position.z = 2.5; this.earL.position.y = 5; this.earL.rotation.z = -Math.PI/12; this.earL.castShadow = true; this.head.add(this.earL); this.earR = this.earL.clone(); this.earR.position.x = -this.earL.position.x; this.earR.rotation.z = -this.earL.rotation.z; this.earR.castShadow = true; this.head.add(this.earR); var eyeGeom = new THREE.CubeGeometry(2,4,4); this.eyeL = new THREE.Mesh(eyeGeom, whiteMat); this.eyeL.position.x = 5; this.eyeL.position.z = 5.5; this.eyeL.position.y = 2.9; this.eyeL.castShadow = true; this.head.add(this.eyeL); var irisGeom = new THREE.CubeGeometry(.6,2,2); this.iris = new THREE.Mesh(irisGeom, blackMat); this.iris.position.x = 1.2; this.iris.position.y = 1; this.iris.position.z = 1; this.eyeL.add(this.iris); this.eyeR = this.eyeL.clone(); this.eyeR.children[0].position.x = -this.iris.position.x; this.eyeR.position.x = -this.eyeL.position.x; this.head.add(this.eyeR); this.body.traverse(function(object) { if (object instanceof THREE.Mesh) { object.castShadow = true; object.receiveShadow = true; } }); } BonusParticles = function(){ this.mesh = new THREE.Group(); var bigParticleGeom = new THREE.CubeGeometry(10,10,10,1); var smallParticleGeom = new THREE.CubeGeometry(5,5,5,1); this.parts = []; for (var i=0; i<10; i++){ var partPink = new THREE.Mesh(bigParticleGeom, pinkMat); var partGreen = new THREE.Mesh(smallParticleGeom, greenMat); partGreen.scale.set(.5,.5,.5); this.parts.push(partPink); this.parts.push(partGreen); this.mesh.add(partPink); this.mesh.add(partGreen); } } BonusParticles.prototype.explose = function(){ var _this = this; var explosionSpeed = .5; for(var i=0; i.2) TweenMax.to([this.eyeR.scale, this.eyeL.scale], sp/8, {y:0, ease:Power1.easeInOut, yoyo:true, repeat:1}); } Hero.prototype.hang = function(){ var _this = this; var sp = 1; var ease = Power4.easeOut; TweenMax.killTweensOf(this.eyeL.scale); TweenMax.killTweensOf(this.eyeR.scale); this.body.rotation.x = 0; this.torso.rotation.x = 0; this.body.position.y = 0; this.torso.position.y = 7; TweenMax.to(this.mesh.rotation, sp, {y:0, ease:ease}); TweenMax.to(this.mesh.position, sp, {y:-7, z:6, ease:ease}); TweenMax.to(this.head.rotation, sp, {x:Math.PI/6, ease:ease, onComplete:function(){_this.nod();}}); TweenMax.to(this.earL.rotation, sp, {x:Math.PI/3, ease:ease}); TweenMax.to(this.earR.rotation, sp, {x:Math.PI/3, ease:ease}); TweenMax.to(this.pawFL.position, sp, {y:-1, z:3, ease:ease}); TweenMax.to(this.pawFR.position, sp, {y:-1, z:3, ease:ease}); TweenMax.to(this.pawBL.position, sp, {y:-2, z:-3, ease:ease}); TweenMax.to(this.pawBR.position, sp, {y:-2, z:-3, ease:ease}); TweenMax.to(this.eyeL.scale, sp, {y:1, ease:ease}); TweenMax.to(this.eyeR.scale, sp, {y:1, ease:ease}); } Monster.prototype.nod = function(){ var _this = this; var sp = 1 + Math.random()*2; // HEAD var tHeadRotY = -Math.PI/3 + Math.random()*.5; var tHeadRotX = Math.PI/3 - .2 + Math.random()*.4; TweenMax.to(this.head.rotation, sp, {x:tHeadRotX, y:tHeadRotY, ease:Power4.easeInOut, onComplete:function(){_this.nod()}}); // TAIL var tTailRotY = -Math.PI/4; TweenMax.to(this.tail.rotation, sp/8, {y:tTailRotY, ease:Power1.easeInOut, yoyo:true, repeat:8}); // EYES TweenMax.to([this.eyeR.scale, this.eyeL.scale], sp/20, {y:0, ease:Power1.easeInOut, yoyo:true, repeat:1}); } Monster.prototype.sit = function(){ var sp = 1.2; var ease = Power4.easeOut; var _this = this; TweenMax.to(this.torso.rotation, sp, {x:-1.3, ease:ease}); TweenMax.to(this.torso.position, sp, {y:-5, ease:ease, onComplete:function(){ _this.nod(); gameStatus = "readyToReplay"; }}); TweenMax.to(this.head.rotation, sp, {x:Math.PI/3, y :-Math.PI/3, ease:ease}); TweenMax.to(this.tail.rotation, sp, {x:2, y:Math.PI/4, ease:ease}); TweenMax.to(this.pawBL.rotation, sp, {x:-.1, ease:ease}); TweenMax.to(this.pawBR.rotation, sp, {x:-.1, ease:ease}); TweenMax.to(this.pawFL.rotation, sp, {x:1, ease:ease}); TweenMax.to(this.pawFR.rotation, sp, {x:1, ease:ease}); TweenMax.to(this.mouth.rotation, sp, {x:.3, ease:ease}); TweenMax.to(this.eyeL.scale, sp, {y:1, ease:ease}); TweenMax.to(this.eyeR.scale, sp, {y:1, ease:ease}); //TweenMax.to(this.body.rotation, sp, {y:Math.PI/4}); } Carrot = function() { this.angle = 0; this.mesh = new THREE.Group(); var bodyGeom = new THREE.CylinderGeometry(5,3, 10, 4,1); bodyGeom.vertices[8].y+=2; bodyGeom.vertices[9].y-=3; this.body = new THREE.Mesh(bodyGeom, pinkMat); var leafGeom = new THREE.CubeGeometry(5,10,1,1); leafGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0,5,0)); leafGeom.vertices[2].x-=1; leafGeom.vertices[3].x-=1; leafGeom.vertices[6].x+=1; leafGeom.vertices[7].x+=1; this.leaf1 = new THREE.Mesh(leafGeom,greenMat); this.leaf1.position.y = 7; this.leaf1.rotation.z = .3; this.leaf1.rotation.x = .2; this.leaf2 = this.leaf1.clone(); this.leaf2.scale.set(1,1.3,1); this.leaf2.position.y = 7; this.leaf2.rotation.z = -.3; this.leaf2.rotation.x = -.2; this.mesh.add(this.body); this.mesh.add(this.leaf1); this.mesh.add(this.leaf2); this.body.traverse(function(object) { if (object instanceof THREE.Mesh) { object.castShadow = true; object.receiveShadow = true; } }); } Hedgehog = function() { this.angle = 0; this.status="ready"; this.mesh = new THREE.Group(); var bodyGeom = new THREE.CubeGeometry(6,6,6,1); this.body = new THREE.Mesh(bodyGeom, blackMat); var headGeom = new THREE.CubeGeometry(5,5,7,1); this.head= new THREE.Mesh(headGeom, lightBrownMat); this.head.position.z = 6; this.head.position.y = -.5; var noseGeom = new THREE.CubeGeometry(1.5,1.5,1.5,1); this.nose = new THREE.Mesh(noseGeom, blackMat); this.nose.position.z = 4; this.nose.position.y = 2; var eyeGeom = new THREE.CubeGeometry(1,3,3); this.eyeL = new THREE.Mesh(eyeGeom, whiteMat); this.eyeL.position.x = 2.2; this.eyeL.position.z = -.5; this.eyeL.position.y = .8; this.eyeL.castShadow = true; this.head.add(this.eyeL); var irisGeom = new THREE.CubeGeometry(.5,1,1); this.iris = new THREE.Mesh(irisGeom, blackMat); this.iris.position.x = .5; this.iris.position.y = .8; this.iris.position.z = .8; this.eyeL.add(this.iris); this.eyeR = this.eyeL.clone(); this.eyeR.children[0].position.x = -this.iris.position.x; this.eyeR.position.x = -this.eyeL.position.x; var spikeGeom = new THREE.CubeGeometry(.5,2,.5,1); spikeGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0,1,0)); for (var i=0; i<9; i++){ var row = (i%3); var col = Math.floor(i/3); var sb = new THREE.Mesh(spikeGeom, blackMat); sb.rotation.x =-Math.PI/2 + (Math.PI/12*row) -.5 + Math.random(); sb.position.z = -3; sb.position.y = -2 + row*2; sb.position.x = -2 + col*2; this.body.add(sb); var st = new THREE.Mesh(spikeGeom, blackMat); st.position.y = 3; st.position.x = -2 + row*2; st.position.z = -2 + col*2; st.rotation.z = Math.PI/6 - (Math.PI/6*row) -.5 + Math.random(); this.body.add(st); var sr = new THREE.Mesh(spikeGeom, blackMat); sr.position.x = 3; sr.position.y = -2 + row*2; sr.position.z = -2 + col*2; sr.rotation.z = -Math.PI/2 + (Math.PI/12*row) -.5 + Math.random(); this.body.add(sr); var sl = new THREE.Mesh(spikeGeom, blackMat); sl.position.x = -3; sl.position.y = -2 + row*2; sl.position.z = -2 + col*2; sl.rotation.z = Math.PI/2 - (Math.PI/12*row) -.5 + Math.random();; this.body.add(sl); } this.head.add(this.eyeR); var earGeom = new THREE.CubeGeometry(2, 2, .5, 1); this.earL = new THREE.Mesh(earGeom, lightBrownMat); this.earL.position.x = 2.5; this.earL.position.z = -2.5; this.earL.position.y = 2.5; this.earL.rotation.z = -Math.PI/12; this.earL.castShadow = true; this.head.add(this.earL); this.earR = this.earL.clone(); this.earR.position.x = -this.earL.position.x; this.earR.rotation.z = -this.earL.rotation.z; this.earR.castShadow = true; this.head.add(this.earR); var mouthGeom = new THREE.CubeGeometry( 1, 1,.5, 1); this.mouth = new THREE.Mesh(mouthGeom, blackMat); this.mouth.position.z = 3.5; this.mouth.position.y = -1.5; this.head.add(this.mouth); this.mesh.add(this.body); this.body.add(this.head); this.head.add(this.nose); this.mesh.traverse(function(object) { if (object instanceof THREE.Mesh) { object.castShadow = true; object.receiveShadow = true; } }); } Hedgehog.prototype.nod = function(){ var _this = this; var speed = .1 + Math.random()*.5; var angle = -Math.PI/4 + Math.random()*Math.PI/2; TweenMax.to(this.head.rotation, speed, {y:angle, onComplete:function(){ _this.nod(); }}); } function createHero() { hero = new Hero(); hero.mesh.rotation.y = Math.PI/2; scene.add(hero.mesh); hero.nod(); } function createMonster() { monster = new Monster(); monster.mesh.position.z = 20; //monster.mesh.scale.set(1.2,1.2,1.2); scene.add(monster.mesh); updateMonsterPosition(); } function updateMonsterPosition(){ monster.run(); monsterPosTarget -= delta*monsterAcceleration; monsterPos += (monsterPosTarget-monsterPos) *delta; if (monsterPos < .56){ gameOver(); } var angle = Math.PI*monsterPos; monster.mesh.position.y = - floorRadius + Math.sin(angle)*(floorRadius + 12); monster.mesh.position.x = Math.cos(angle)*(floorRadius+15); monster.mesh.rotation.z = -Math.PI/2 + angle; } function gameOver(){ fieldGameOver.className = "show"; gameStatus = "gameOver"; monster.sit(); hero.hang(); monster.heroHolder.add(hero.mesh); TweenMax.to(this, 1, {speed:0}); TweenMax.to(camera.position, 3, {z:cameraPosGameOver, y: 60, x:-30}); carrot.mesh.visible = false; obstacle.mesh.visible = false; clearInterval(levelInterval); } function replay(){ gameStatus = "preparingToReplay" fieldGameOver.className = ""; TweenMax.killTweensOf(monster.pawFL.position); TweenMax.killTweensOf(monster.pawFR.position); TweenMax.killTweensOf(monster.pawBL.position); TweenMax.killTweensOf(monster.pawBR.position); TweenMax.killTweensOf(monster.pawFL.rotation); TweenMax.killTweensOf(monster.pawFR.rotation); TweenMax.killTweensOf(monster.pawBL.rotation); TweenMax.killTweensOf(monster.pawBR.rotation); TweenMax.killTweensOf(monster.tail.rotation); TweenMax.killTweensOf(monster.head.rotation); TweenMax.killTweensOf(monster.eyeL.scale); TweenMax.killTweensOf(monster.eyeR.scale); //TweenMax.killTweensOf(hero.head.rotation); monster.tail.rotation.y = 0; TweenMax.to(camera.position, 3, {z:cameraPosGame, x:0, y:30, ease:Power4.easeInOut}); TweenMax.to(monster.torso.rotation,2, {x:0, ease:Power4.easeInOut}); TweenMax.to(monster.torso.position,2, {y:0, ease:Power4.easeInOut}); TweenMax.to(monster.pawFL.rotation,2, {x:0, ease:Power4.easeInOut}); TweenMax.to(monster.pawFR.rotation,2, {x:0, ease:Power4.easeInOut}); TweenMax.to(monster.mouth.rotation,2, {x:.5, ease:Power4.easeInOut}); TweenMax.to(monster.head.rotation,2, {y:0, x:-.3, ease:Power4.easeInOut}); TweenMax.to(hero.mesh.position, 2, { x:20, ease:Power4.easeInOut}); TweenMax.to(hero.head.rotation, 2, { x:0, y:0, ease:Power4.easeInOut}); TweenMax.to(monster.mouth.rotation, 2, {x:.2, ease:Power4.easeInOut}); TweenMax.to(monster.mouth.rotation, 1, {x:.4, ease:Power4.easeIn, delay: 1, onComplete:function(){ resetGame(); }}); } Fir = function() { var height = 200; var truncGeom = new THREE.CylinderGeometry(2,2,height, 6,1); truncGeom.applyMatrix(new THREE.Matrix4().makeTranslation(0,height/2,0)); this.mesh = new THREE.Mesh(truncGeom, greenMat); this.mesh.castShadow = true; } var firs = new THREE.Group(); function createFirs(){ var nTrees = 100; for(var i=0; i< nTrees; i++){ var phi = i*(Math.PI*2)/nTrees; var theta = Math.PI/2; //theta += .25 + Math.random()*.3; theta += (Math.random()>.05)? .25 + Math.random()*.3 : - .35 - Math.random()*.1; var fir = new Tree(); fir.mesh.position.x = Math.sin(theta)*Math.cos(phi)*floorRadius; fir.mesh.position.y = Math.sin(theta)*Math.sin(phi)*(floorRadius-10); fir.mesh.position.z = Math.cos(theta)*floorRadius; var vec = fir.mesh.position.clone(); var axis = new THREE.Vector3(0,1,0); fir.mesh.quaternion.setFromUnitVectors(axis, vec.clone().normalize()); floor.add(fir.mesh); } } function createCarrot(){ carrot = new Carrot(); scene.add(carrot.mesh); } function updateCarrotPosition(){ carrot.mesh.rotation.y += delta * 6; carrot.mesh.rotation.z = Math.PI/2 - (floorRotation+carrot.angle); carrot.mesh.position.y = -floorRadius + Math.sin(floorRotation+carrot.angle) * (floorRadius+50); carrot.mesh.position.x = Math.cos(floorRotation+carrot.angle) * (floorRadius+50); } function updateObstaclePosition(){ if (obstacle.status=="flying")return; // TODO fix this, if (floorRotation+obstacle.angle > 2.5 ){ obstacle.angle = -floorRotation + Math.random()*.3; obstacle.body.rotation.y = Math.random() * Math.PI*2; } obstacle.mesh.rotation.z = floorRotation + obstacle.angle - Math.PI/2; obstacle.mesh.position.y = -floorRadius + Math.sin(floorRotation+obstacle.angle) * (floorRadius+3); obstacle.mesh.position.x = Math.cos(floorRotation+obstacle.angle) * (floorRadius+3); } function updateFloorRotation(){ floorRotation += delta*.03 * speed; floorRotation = floorRotation%(Math.PI*2); floor.rotation.z = floorRotation; } function createObstacle(){ obstacle = new Hedgehog(); obstacle.body.rotation.y = -Math.PI/2; obstacle.mesh.scale.set(1.1,1.1,1.1); obstacle.mesh.position.y = floorRadius+4; obstacle.nod(); scene.add(obstacle.mesh); } function createBonusParticles(){ bonusParticles = new BonusParticles(); bonusParticles.mesh.visible = false; scene.add(bonusParticles.mesh); } function checkCollision(){ var db = hero.mesh.position.clone().sub(carrot.mesh.position.clone()); var dm = hero.mesh.position.clone().sub(obstacle.mesh.position.clone()); if(db.length() < collisionBonus){ getBonus(); } if(dm.length() < collisionObstacle && obstacle.status != "flying"){ getMalus(); } } function getBonus(){ bonusParticles.mesh.position.copy(carrot.mesh.position); bonusParticles.mesh.visible = true; bonusParticles.explose(); carrot.angle += Math.PI/2; //speed*=.95; monsterPosTarget += .025; } function getMalus(){ obstacle.status="flying"; var tx = (Math.random()>.5)? -20-Math.random()*10 : 20+Math.random()*5; TweenMax.to(obstacle.mesh.position, 4, {x:tx, y:Math.random()*50, z:350, ease:Power4.easeOut}); TweenMax.to(obstacle.mesh.rotation, 4, {x:Math.PI*3, z:Math.PI*3, y:Math.PI*6, ease:Power4.easeOut, onComplete:function(){ obstacle.status = "ready"; obstacle.body.rotation.y = Math.random() * Math.PI*2; obstacle.angle = -floorRotation - Math.random()*.4; obstacle.angle = obstacle.angle%(Math.PI*2); obstacle.mesh.rotation.x = 0; obstacle.mesh.rotation.y = 0; obstacle.mesh.rotation.z = 0; obstacle.mesh.position.z = 0; }}); // monsterPosTarget -= .04; TweenMax.from(this, .5, {malusClearAlpha:.5, onUpdate:function(){ renderer.setClearColor(malusClearColor, malusClearAlpha ); }}) } function updateDistance(){ distance += delta*speed; var d = distance/2; fieldDistance.innerHTML = Math.floor(d); } function updateLevel(){ if (speed >= maxSpeed) return; level++; speed += 2; } function loop(){ delta = clock.getDelta(); updateFloorRotation(); if (gameStatus == "play"){ if (hero.status == "running"){ hero.run(); } updateDistance(); updateMonsterPosition(); updateCarrotPosition(); updateObstaclePosition(); checkCollision(); } render(); requestAnimationFrame(loop); } function render(){ renderer.render(scene, camera); } window.addEventListener('load', init, false); function init(event){ initScreenAnd3D(); createLights(); createFloor() createHero(); createMonster(); createFirs(); createCarrot(); createBonusParticles(); createObstacle(); initUI(); resetGame(); loop(); //setInterval(hero.blink.bind(hero), 3000); } function resetGame(){ scene.add(hero.mesh); hero.mesh.rotation.y = Math.PI/2; hero.mesh.position.y = 0; hero.mesh.position.z = 0; hero.mesh.position.x = 0; monsterPos = .56; monsterPosTarget = .65; speed = initSpeed; level = 0; distance = 0; carrot.mesh.visible = true; obstacle.mesh.visible = true; gameStatus = "play"; hero.status = "running"; hero.nod(); audio.play(); updateLevel(); levelInterval = setInterval(updateLevel, levelUpdateFreq); } function initUI(){ fieldDistance = document.getElementById("distValue"); fieldGameOver = document.getElementById("gameoverInstructions"); } //////////////////////////////////////////////// // MODELS //////////////////////////////////////////////// // TREE Tree = function(){ this.mesh = new THREE.Object3D(); this.trunc = new Trunc(); this.mesh.add(this.trunc.mesh); } Trunc = function(){ var truncHeight = 50 + Math.random()*150; var topRadius = 1+Math.random()*5; var bottomRadius = 5+Math.random()*5; var mats = [blackMat, brownMat, pinkMat, whiteMat, greenMat, lightBrownMat, pinkMat]; var matTrunc = blackMat;//mats[Math.floor(Math.random()*mats.length)]; var nhSegments = 3;//Math.ceil(2 + Math.random()*6); var nvSegments = 3;//Math.ceil(2 + Math.random()*6); var geom = new THREE.CylinderGeometry(topRadius,bottomRadius,truncHeight, nhSegments, nvSegments); geom.applyMatrix(new THREE.Matrix4().makeTranslation(0,truncHeight/2,0)); this.mesh = new THREE.Mesh(geom, matTrunc); for (var i=0; i.7){ var size = Math.random()*3; var fruitGeometry = new THREE.CubeGeometry(size,size,size,1); var matFruit = mats[Math.floor(Math.random()*mats.length)]; var fruit = new THREE.Mesh(fruitGeometry, matFruit); fruit.position.x = v.x; fruit.position.y = v.y+3; fruit.position.z = v.z; fruit.rotation.x = Math.random()*Math.PI; fruit.rotation.y = Math.random()*Math.PI; this.mesh.add(fruit); } // BRANCHES if (Math.random()>.5 && v.y > 10 && v.y < truncHeight - 10){ var h = 3 + Math.random()*5; var thickness = .2 + Math.random(); var branchGeometry = new THREE.CylinderGeometry(thickness/2, thickness, h, 3, 1); branchGeometry.applyMatrix(new THREE.Matrix4().makeTranslation(0,h/2,0)); var branch = new THREE.Mesh(branchGeometry, matTrunc); branch.position.x = v.x; branch.position.y = v.y; branch.position.z = v.z; var vec = new THREE.Vector3(v.x, 2, v.z); var axis = new THREE.Vector3(0,1,0); branch.quaternion.setFromUnitVectors(axis, vec.clone().normalize()); this.mesh.add(branch); } } this.mesh.castShadow = true; }