diff --git a/bkcore/hexgl/HexGL.js b/bkcore/hexgl/HexGL.js index b2b6b1b..657e798 100644 --- a/bkcore/hexgl/HexGL.js +++ b/bkcore/hexgl/HexGL.js @@ -1,7 +1,7 @@ /* * HexGL * @author Thibaut 'BKcore' Despoulain - * @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License. + * @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License. * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/. */ @@ -73,9 +73,9 @@ bkcore.hexgl.HexGL = function(opts) this.initRenderer(); - function onKeyPress(event) + function onKeyPress(event) { - if(event.keyCode == 27/*escape*/) + if(event.keyCode == 27/*escape*/) { self.reset(); } @@ -155,6 +155,7 @@ bkcore.hexgl.HexGL.prototype.initGameplay = function() pixelRatio: this.track.pixelRatio, track: this.track, onFinish: function() { + self.components.shipControls.terminate(); self.displayScore(this.finishTime, this.lapTimes); } }); @@ -173,12 +174,12 @@ bkcore.hexgl.HexGL.prototype.displayScore = function(f, l) bkcore.Timer.msToTimeString(l[2]) ]; - if(this.mobile) + if(this.gameover !== null) { this.gameover.style.display = "block"; - this.gameover.innerHTML = tf.m + "'" + tf.s + "''" + tf.ms; - this.containers.main.style.display = "none"; - return; + this.gameover.children[0].innerHTML = tf.m + "'" + tf.s + "''" + tf.ms; + this.containers.main.parentElement.style.display = "none"; + return; } var t = this.track; @@ -286,7 +287,7 @@ bkcore.hexgl.HexGL.prototype.initRenderer = function() renderer.setSize( this.width, this.height ); renderer.domElement.style.position = "relative"; - this.containers.main.appendChild( renderer.domElement ); + this.containers.main.appendChild( renderer.domElement ); this.canvas = renderer.domElement; this.renderer = renderer; this.manager = new bkcore.threejs.RenderManager(renderer); @@ -302,7 +303,7 @@ bkcore.hexgl.HexGL.prototype.initHUD = function() bg: this.track.lib.get("images", "hud.bg"), speed: this.track.lib.get("images", "hud.speed"), shield: this.track.lib.get("images", "hud.shield") - }); + }); this.containers.overlay.appendChild(this.hud.canvas); } @@ -311,7 +312,7 @@ bkcore.hexgl.HexGL.prototype.initGameComposer = function() var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false }; var renderTarget = new THREE.WebGLRenderTarget( this.width, this.height, renderTargetParameters ); - // GAME COMPOSER + // GAME COMPOSER var renderSky = new THREE.RenderPass( this.manager.get("sky").scene, this.manager.get("sky").camera ); var renderModel = new THREE.RenderPass( this.manager.get("game").scene, this.manager.get("game").camera ); @@ -319,8 +320,8 @@ bkcore.hexgl.HexGL.prototype.initGameComposer = function() this.composers.game = new THREE.EffectComposer( this.renderer, renderTarget ); - var effectScreen = new THREE.ShaderPass( THREE.ShaderExtras[ "screen" ] ); - effectScreen.renderToScreen = true; + var effectScreen = new THREE.ShaderPass( THREE.ShaderExtras[ "screen" ] ); + effectScreen.renderToScreen = true; var effectVignette = new THREE.ShaderPass( THREE.ShaderExtras[ "vignette" ] ); var effectHex = new THREE.ShaderPass( bkcore.threejs.Shaders[ "hexvignette" ] ); @@ -335,17 +336,17 @@ bkcore.hexgl.HexGL.prototype.initGameComposer = function() this.composers.game.addPass( renderSky ); this.composers.game.addPass( renderModel ); - if(this.quality > 0 && !this.mobile) - { - var effectFXAA = new THREE.ShaderPass( THREE.ShaderExtras[ "fxaa" ] ); - effectFXAA.uniforms[ 'resolution' ].value.set( 1 / this.width, 1 / this.height ); + // if(this.quality > 0 && !this.mobile) + // { + // var effectFXAA = new THREE.ShaderPass( THREE.ShaderExtras[ "fxaa" ] ); + // effectFXAA.uniforms[ 'resolution' ].value.set( 1 / this.width, 1 / this.height ); - this.composers.game.addPass( effectFXAA ); - - this.extras.fxaa = effectFXAA; - } + // this.composers.game.addPass( effectFXAA ); + + // this.extras.fxaa = effectFXAA; + // } if(this.quality > 1 && !this.mobile) - { + { var effectBloom = new THREE.BloomPass( 0.8, 25, 4 , 256); this.composers.game.addPass( effectBloom ); @@ -358,10 +359,10 @@ bkcore.hexgl.HexGL.prototype.initGameComposer = function() else this.composers.game.addPass( effectScreen ); - + } -bkcore.hexgl.HexGL.prototype.createMesh = function(parent, geometry, x, y, z, mat) +bkcore.hexgl.HexGL.prototype.createMesh = function(parent, geometry, x, y, z, mat) { geometry.computeTangents(); @@ -422,4 +423,4 @@ bkcore.hexgl.HexGL.prototype.tweakShipControls = function() if(this.godmode) c.shieldDamage = 0.0; -} \ No newline at end of file +} diff --git a/bkcore/hexgl/ShipControls.js b/bkcore/hexgl/ShipControls.js index 5a27256..31478e5 100644 --- a/bkcore/hexgl/ShipControls.js +++ b/bkcore/hexgl/ShipControls.js @@ -1,7 +1,7 @@ /* * HexGL * @author Thibaut 'BKcore' Despoulain - * @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License. + * @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License. * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/. */ @@ -27,7 +27,7 @@ bkcore.hexgl.ShipControls = function(ctx) this.thrust = 0.02; this.airBrake = 0.02; this.maxSpeed = 7.0; - this.boosterSpeed = this.maxSpeed * 0.4; + this.boosterSpeed = this.maxSpeed * 0.2; this.boosterDecay = 0.01; this.angularSpeed = 0.005; this.airAngularSpeed = 0.0065; @@ -75,7 +75,7 @@ bkcore.hexgl.ShipControls = function(ctx) this.rollAngle = 0.6; this.rollLerp = 0.08; this.rollDirection = new THREE.Vector3(0,0,1); - + this.gradient = 0.0; this.gradientTarget = 0.0; this.gradientLerp = 0.05; @@ -124,7 +124,7 @@ bkcore.hexgl.ShipControls = function(ctx) if(ctx.controlType == 1 && bkcore.controllers.TouchController.isCompatible()) { this.touchController = new bkcore.controllers.TouchController( - domElement, ctx.width/2, + domElement, ctx.width/2, function(state, touch, event){ if(event.touches.length >= 4) window.location.reload(false); @@ -136,12 +136,11 @@ bkcore.hexgl.ShipControls = function(ctx) self.key.forward = true; }); } - else if(ctx.controlType == 2 && bkcore.controllers.OrientationController.isCompatible()) + else if(ctx.controlType == 3 && bkcore.controllers.OrientationController.isCompatible()) { this.orientationController = new bkcore.controllers.OrientationController( domElement, true, function(state, touch, event){ - console.log(event.touches.length); if(event.touches.length >= 4) window.location.reload(false); else if(event.touches.length == 3) @@ -152,10 +151,88 @@ bkcore.hexgl.ShipControls = function(ctx) self.key.forward = true; }); } - - function onKeyDown(event) + else if(ctx.controlType == 2) { - switch(event.keyCode) + if(Leap == null) + throw new Error("Unable to reach LeapJS!"); + + var leapInfo = this.leapInfo = document.getElementById('leapinfo'); + isServerConnected = false; + var lb = this.leapBridge = { + isConnected: true, + hasHands: false, + palmNormal: [0, 0, 0] + }; + + function updateInfo() + { + if(!isServerConnected) + { + leapInfo.innerHTML = 'Waiting for the Leap Motion Controller server...' + leapInfo.style.display = 'block'; + } + else if(lb.isConnected && lb.hasHands) + { + leapInfo.style.display = 'none'; + } + else if(!lb.isConnected) + { + leapInfo.innerHTML = 'Please connect your Leap Motion Controller.' + leapInfo.style.display = 'block'; + } + else if(!lb.hasHands) + { + leapInfo.innerHTML = 'Put your hand over the Leap Motion Controller to play.' + leapInfo.style.display = 'block'; + } + } + updateInfo(); + + var lc = this.leapController = new Leap.Controller({enableGestures: false}); + lc.on('connect', function() + { + isServerConnected = true; + updateInfo(); + }); + lc.on('deviceConnected', function() + { + lb.isConnected = true; + updateInfo(); + }); + lc.on('deviceDisconnected', function() + { + lb.isConnected = false; + updateInfo(); + }); + lc.on('frame', function(frame) + { + if(!lb.isConnected) return; + hand = frame.hands[0]; + if(typeof hand === 'undefined') + { + if(lb.hasHands) + { + lb.hasHands = false; + updateInfo(); + } + lb.palmNormal = [0, 0, 0]; + } + else + { + if(!lb.hasHands) + { + lb.hasHands = true; + updateInfo(); + } + lb.palmNormal = hand.palmNormal; + } + }); + lc.connect(); + } + + function onKeyDown(event) + { + switch(event.keyCode) { case 38: /*up*/ self.key.forward = true; break; @@ -173,7 +250,7 @@ bkcore.hexgl.ShipControls = function(ctx) } }; - function onKeyUp(event) + function onKeyUp(event) { switch(event.keyCode) { @@ -225,11 +302,22 @@ bkcore.hexgl.ShipControls.prototype.reset = function(position, rotation) this.dummy.matrix.setPosition(this.dummy.position); this.dummy.matrix.setRotationFromQuaternion(this.dummy.quaternion); - + this.mesh.matrix.identity(); this.mesh.applyMatrix(this.dummy.matrix); } +bkcore.hexgl.ShipControls.prototype.terminate = function() +{ + this.destroy(); + + if(this.leapController != null) + { + this.leapController.disconnect(); + this.leapInfo.style.display = 'none'; + } +} + bkcore.hexgl.ShipControls.prototype.destroy = function() { this.active = false; @@ -239,7 +327,6 @@ bkcore.hexgl.ShipControls.prototype.destroy = function() this.collision.right = false; } - bkcore.hexgl.ShipControls.prototype.fall = function() { this.active = false; @@ -261,8 +348,6 @@ bkcore.hexgl.ShipControls.prototype.update = function(dt) return; } - if(!this.active) return; - this.rotation.y = 0; this.movement.set(0,0,0); this.drift += (0.0 - this.drift) * this.driftLerp; @@ -270,57 +355,73 @@ bkcore.hexgl.ShipControls.prototype.update = function(dt) var rollAmount = 0.0; var angularAmount = 0.0; + var yawLeap = 0.0; - if(this.touchController != null) + if(this.leapBridge != null && this.leapBridge.hasHands) { - angularAmount -= this.touchController.stickVector.x/100 * this.angularSpeed * dt; - rollAmount += this.touchController.stickVector.x/100 * this.rollAngle; - } - if(this.orientationController != null) - { - angularAmount += this.orientationController.beta/45 * this.angularSpeed * dt; - rollAmount -= this.orientationController.beta/45 * this.rollAngle; + rollAmount -= this.leapBridge.palmNormal[0] * 3.5 * this.rollAngle; + yawLeap = -this.leapBridge.palmNormal[2] * 0.6; } - if(this.key.forward) - this.speed += this.thrust * dt; - else - this.speed -= this.airResist * dt; - if(this.key.left) - { - angularAmount += this.angularSpeed * dt; - rollAmount -= this.rollAngle; - } - if(this.key.right) - { - angularAmount -= this.angularSpeed * dt; - rollAmount += this.rollAngle; - } - if(this.key.ltrigger) + if(this.active) { + + if(this.touchController != null) + { + angularAmount -= this.touchController.stickVector.x/100 * this.angularSpeed * dt; + rollAmount += this.touchController.stickVector.x/100 * this.rollAngle; + } + if(this.orientationController != null) + { + angularAmount += this.orientationController.beta/45 * this.angularSpeed * dt; + rollAmount -= this.orientationController.beta/45 * this.rollAngle; + } + if(this.leapBridge != null && this.leapBridge.hasHands) + { + angularAmount += this.leapBridge.palmNormal[0] * 2 * this.angularSpeed * dt; + this.speed += Math.max(0.0, (0.5 + this.leapBridge.palmNormal[2])) * 3 * this.thrust * dt; + } + + if(this.key.forward) + this.speed += this.thrust * dt; + else + this.speed -= this.airResist * dt; if(this.key.left) - angularAmount += this.airAngularSpeed * dt; - else - angularAmount += this.airAngularSpeed * 0.5 * dt; - this.speed -= this.airBrake * dt; - this.drift += (this.airDrift - this.drift) * this.driftLerp; - this.movement.x += this.speed * this.drift * dt; - if(this.drift > 0.0) - this.movement.z -= this.speed * this.drift * dt; - rollAmount -= this.rollAngle * 0.7; - } - if(this.key.rtrigger) - { + { + angularAmount += this.angularSpeed * dt; + rollAmount -= this.rollAngle; + } if(this.key.right) - angularAmount -= this.airAngularSpeed * dt; - else - angularAmount -= this.airAngularSpeed * 0.5 * dt; - this.speed -= this.airBrake * dt; - this.drift += (-this.airDrift - this.drift) * this.driftLerp; - this.movement.x += this.speed * this.drift * dt; - if(this.drift < 0.0) - this.movement.z += this.speed * this.drift * dt; - rollAmount += this.rollAngle * 0.7; + { + angularAmount -= this.angularSpeed * dt; + rollAmount += this.rollAngle; + } + if(this.key.ltrigger) + { + if(this.key.left) + angularAmount += this.airAngularSpeed * dt; + else + angularAmount += this.airAngularSpeed * 0.5 * dt; + this.speed -= this.airBrake * dt; + this.drift += (this.airDrift - this.drift) * this.driftLerp; + this.movement.x += this.speed * this.drift * dt; + if(this.drift > 0.0) + this.movement.z -= this.speed * this.drift * dt; + rollAmount -= this.rollAngle * 0.7; + } + if(this.key.rtrigger) + { + if(this.key.right) + angularAmount -= this.airAngularSpeed * dt; + else + angularAmount -= this.airAngularSpeed * 0.5 * dt; + this.speed -= this.airBrake * dt; + this.drift += (-this.airDrift - this.drift) * this.driftLerp; + this.movement.x += this.speed * this.drift * dt; + if(this.drift < 0.0) + this.movement.z += this.speed * this.drift * dt; + rollAmount += this.rollAngle * 0.7; + } } this.angular += (angularAmount - this.angular) * this.angularLerp; @@ -376,7 +477,7 @@ bkcore.hexgl.ShipControls.prototype.update = function(dt) this.mesh.matrix.identity(); // Gradient (Mesh only, no dummy physics impact) - var gradientDelta = (this.gradientTarget - this.gradient) * this.gradientLerp; + var gradientDelta = (this.gradientTarget - (yawLeap + this.gradient)) * this.gradientLerp; if(Math.abs(gradientDelta) > this.epsilon) this.gradient += gradientDelta; if(Math.abs(this.gradient) > this.epsilon) { @@ -505,9 +606,9 @@ bkcore.hexgl.ShipControls.prototype.collisionCheck = function(dt) var rPos = this.repulsionVRight.addSelf(pos); var lCol = this.collisionMap.getPixel(Math.round(lPos.x), Math.round(lPos.z)).r; var rCol = this.collisionMap.getPixel(Math.round(rPos.x), Math.round(rPos.z)).r; - - this.repulsionAmount = Math.max(0.8, - Math.min(this.repulsionCap, + + this.repulsionAmount = Math.max(0.8, + Math.min(this.repulsionCap, this.speed * this.repulsionRatio ) ); @@ -608,7 +709,7 @@ bkcore.hexgl.ShipControls.prototype.heightCheck = function(dt) x = this.heightMap.pixels.width/2 + this.tiltVector.x * this.heightPixelRatio; z = this.heightMap.pixels.height/2 + this.tiltVector.z * this.heightPixelRatio; - nheight = this.heightMap.getPixelFBilinear(x, z) / this.heightScale + this.heightBias; + nheight = this.heightMap.getPixelFBilinear(x, z) / this.heightScale + this.heightBias; } if(nheight < 16777) @@ -626,7 +727,7 @@ bkcore.hexgl.ShipControls.prototype.getRealSpeed = function(scale) bkcore.hexgl.ShipControls.prototype.getRealSpeedRatio = function() { return Math.min( - this.maxSpeed, + this.maxSpeed, this.speed+this.boost ) / this.maxSpeed; }; @@ -662,4 +763,4 @@ bkcore.hexgl.ShipControls.prototype.getPosition = function() bkcore.hexgl.ShipControls.prototype.getQuaternion = function() { return this.dummy.quaternion; -} \ No newline at end of file +} diff --git a/bkcore/hexgl/ShipEffects.js b/bkcore/hexgl/ShipEffects.js index 3faf4a7..1be2920 100644 --- a/bkcore/hexgl/ShipEffects.js +++ b/bkcore/hexgl/ShipEffects.js @@ -1,7 +1,7 @@ /* * HexGL * @author Thibaut 'BKcore' Despoulain - * @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License. + * @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License. * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/. */ @@ -46,7 +46,7 @@ bkcore.hexgl.ShipEffects = function(opts) texture: opts.textureSpark, size: 2, life: 60, - max: 500 + max: 200 }), leftClouds: new bkcore.threejs.Particles( @@ -59,7 +59,7 @@ bkcore.hexgl.ShipEffects = function(opts) size: 6, blending: THREE.NormalBlending, life: 60, - max: 500, + max: 200, spawn: new THREE.Vector3(3,-0.3,0), spawnRadius: new THREE.Vector3(1,1,2), velocity: new THREE.Vector3(0,0,-0.4), @@ -75,7 +75,7 @@ bkcore.hexgl.ShipEffects = function(opts) texture: opts.textureSpark, size: 2, life: 60, - max: 500 + max: 200 }), rightClouds: new bkcore.threejs.Particles( @@ -88,7 +88,7 @@ bkcore.hexgl.ShipEffects = function(opts) size: 6, blending: THREE.NormalBlending, life: 60, - max: 500, + max: 200, spawn: new THREE.Vector3(-3,-0.3,0), spawnRadius: new THREE.Vector3(1,1,2), velocity: new THREE.Vector3(0,0,-0.4), @@ -105,7 +105,7 @@ bkcore.hexgl.ShipEffects = function(opts) bkcore.hexgl.ShipEffects.prototype.update = function(dt) { - var boostRatio, opacity, scale, intensity, random; + var boostRatio, opacity, scale, intensity, random; if(this.shipControls.destroyed) { @@ -144,8 +144,8 @@ bkcore.hexgl.ShipEffects.prototype.update = function(dt) this.particles.leftSparks.velocity.copy(this.pVel).x *= -1; this.particles.leftSparks.spawn.copy(this.pOffset).x *= -1; - if(this.shipControls.mesh) - { + if(this.shipControls.mesh) + { // RIGHT this.shipControls.mesh.matrix.rotateAxis(this.particles.rightSparks.spawn); this.particles.rightSparks.spawn.multiplyScalar(this.pOffsetS).addSelf(this.shipControls.dummy.position); @@ -168,14 +168,14 @@ bkcore.hexgl.ShipEffects.prototype.update = function(dt) if(this.shipControls.collision.right) { - this.particles.rightSparks.emit(Math.round(30*dt)); - this.particles.rightClouds.emit(Math.round(10*dt)); + this.particles.rightSparks.emit(10); + this.particles.rightClouds.emit(5); } if(this.shipControls.collision.left) { - this.particles.leftSparks.emit(Math.round(30*dt)); - this.particles.leftClouds.emit(Math.round(10*dt)); + this.particles.leftSparks.emit(10); + this.particles.leftClouds.emit(5); } this.particles.rightSparks.update(dt); @@ -183,4 +183,4 @@ bkcore.hexgl.ShipEffects.prototype.update = function(dt) this.particles.leftSparks.update(dt); this.particles.leftClouds.update(dt); } -} \ No newline at end of file +} diff --git a/bkcore/hexgl/tracks/Cityscape.js b/bkcore/hexgl/tracks/Cityscape.js index 6902147..5f5ecf2 100644 --- a/bkcore/hexgl/tracks/Cityscape.js +++ b/bkcore/hexgl/tracks/Cityscape.js @@ -1,7 +1,7 @@ /* * HexGL * @author Thibaut 'BKcore' Despoulain - * @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License. + * @license This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License. * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0/. */ @@ -23,8 +23,8 @@ bkcore.hexgl.tracks.Cityscape = { }, spawn: { - x: -1134*2, - y: 387, + x: -1134*2, + y: 387, z: -443*2 }, @@ -46,6 +46,8 @@ bkcore.hexgl.tracks.Cityscape = { this.lib.load({ textures: { 'hex' : "textures/hud/hex.jpg", + 'spark' : "textures/particles/spark.png", + 'cloud' : "textures/particles/cloud.png", 'ship.feisar.diffuse' : "textures/ships/feisar/diffuse.jpg", 'booster.diffuse' : "textures/ships/feisar/booster/booster.png", 'booster.sprite' : "textures/ships/feisar/booster/boostersprite.jpg", @@ -82,36 +84,36 @@ bkcore.hexgl.tracks.Cityscape = { }); } else // HIGH - { + {console.log('HIGH'); this.lib.load({ textures: { - 'hex' : "textures/hud/hex.jpg", - 'spark' : "textures/particles/spark.png", - 'cloud' : "textures/particles/cloud.png", - 'ship.feisar.diffuse' : "textures/ships/feisar/diffuse.jpg", - 'ship.feisar.specular' : "textures/ships/feisar/specular.jpg", - 'ship.feisar.normal' : "textures/ships/feisar/normal.jpg", - 'booster.diffuse' : "textures/ships/feisar/booster/booster.png", - 'booster.sprite' : "textures/ships/feisar/booster/boostersprite.jpg", - 'track.cityscape.diffuse' : "textures/tracks/cityscape/diffuse.jpg", - 'track.cityscape.specular' : "textures/tracks/cityscape/specular.jpg", - 'track.cityscape.normal' : "textures/tracks/cityscape/normal.jpg", - 'track.cityscape.scrapers1.diffuse' : "textures/tracks/cityscape/scrapers1/diffuse.jpg", - 'track.cityscape.scrapers1.specular': "textures/tracks/cityscape/scrapers1/specular.jpg", - 'track.cityscape.scrapers1.normal' : "textures/tracks/cityscape/scrapers1/normal.jpg", - 'track.cityscape.scrapers2.diffuse' : "textures/tracks/cityscape/scrapers2/diffuse.jpg", - 'track.cityscape.scrapers2.specular': "textures/tracks/cityscape/scrapers2/specular.jpg", - 'track.cityscape.scrapers2.normal' : "textures/tracks/cityscape/scrapers2/normal.jpg", - 'track.cityscape.start.diffuse' : "textures/tracks/cityscape/start/diffuse.jpg", - 'track.cityscape.start.specular' : "textures/tracks/cityscape/start/specular.jpg", - 'track.cityscape.start.normal' : "textures/tracks/cityscape/start/normal.jpg", - 'track.cityscape.start.banner' : "textures/tracks/cityscape/start/start.jpg", - 'bonus.base.diffuse' : "textures/bonus/base/diffuse.jpg", - 'bonus.base.normal' : "textures/bonus/base/normal.jpg", - 'bonus.base.specular' : "textures/bonus/base/specular.jpg" + 'hex' : "textures.full/hud/hex.jpg", + 'spark' : "textures.full/particles/spark.png", + 'cloud' : "textures.full/particles/cloud.png", + 'ship.feisar.diffuse' : "textures.full/ships/feisar/diffuse.jpg", + 'ship.feisar.specular' : "textures.full/ships/feisar/specular.jpg", + 'ship.feisar.normal' : "textures.full/ships/feisar/normal.jpg", + 'booster.diffuse' : "textures.full/ships/feisar/booster/booster.png", + 'booster.sprite' : "textures.full/ships/feisar/booster/boostersprite.jpg", + 'track.cityscape.diffuse' : "textures.full/tracks/cityscape/diffuse.jpg", + 'track.cityscape.specular' : "textures.full/tracks/cityscape/specular.jpg", + 'track.cityscape.normal' : "textures.full/tracks/cityscape/normal.jpg", + 'track.cityscape.scrapers1.diffuse' : "textures.full/tracks/cityscape/scrapers1/diffuse.jpg", + 'track.cityscape.scrapers1.specular': "textures.full/tracks/cityscape/scrapers1/specular.jpg", + 'track.cityscape.scrapers1.normal' : "textures.full/tracks/cityscape/scrapers1/normal.jpg", + 'track.cityscape.scrapers2.diffuse' : "textures.full/tracks/cityscape/scrapers2/diffuse.jpg", + 'track.cityscape.scrapers2.specular': "textures.full/tracks/cityscape/scrapers2/specular.jpg", + 'track.cityscape.scrapers2.normal' : "textures.full/tracks/cityscape/scrapers2/normal.jpg", + 'track.cityscape.start.diffuse' : "textures.full/tracks/cityscape/start/diffuse.jpg", + 'track.cityscape.start.specular' : "textures.full/tracks/cityscape/start/specular.jpg", + 'track.cityscape.start.normal' : "textures.full/tracks/cityscape/start/normal.jpg", + 'track.cityscape.start.banner' : "textures.full/tracks/cityscape/start/start.jpg", + 'bonus.base.diffuse' : "textures.full/bonus/base/diffuse.jpg", + 'bonus.base.normal' : "textures.full/bonus/base/normal.jpg", + 'bonus.base.specular' : "textures.full/bonus/base/specular.jpg" }, texturesCube: { - 'skybox.dawnclouds' : "textures/skybox/dawnclouds/%1.jpg" + 'skybox.dawnclouds' : "textures.full/skybox/dawnclouds/%1.jpg" }, geometries: { 'bonus.base' : "geometries/bonus/base/base.js", @@ -125,13 +127,13 @@ bkcore.hexgl.tracks.Cityscape = { 'track.cityscape.bonus.speed' : "geometries/tracks/cityscape/bonus/speed.js" }, analysers: { - 'track.cityscape.collision' : "textures/tracks/cityscape/collision.png", - 'track.cityscape.height' : "textures/tracks/cityscape/height.png" + 'track.cityscape.collision' : "textures.full/tracks/cityscape/collision.png", + 'track.cityscape.height' : "textures.full/tracks/cityscape/height.png" }, images: { - 'hud.bg' : "textures/hud/hud-bg.png", - 'hud.speed' : "textures/hud/hud-fg-speed.png", - 'hud.shield' : "textures/hud/hud-fg-shield.png" + 'hud.bg' : "textures.full/hud/hud-bg.png", + 'hud.speed' : "textures.full/hud/hud-fg-speed.png", + 'hud.shield' : "textures.full/hud/hud-fg-shield.png" } }); } @@ -161,7 +163,7 @@ bkcore.hexgl.tracks.Cityscape = { }); this.materials.booster = new THREE.MeshBasicMaterial({ - map: this.lib.get("textures", "booster.diffuse"), + map: this.lib.get("textures", "booster.diffuse"), transparent: true }); @@ -177,11 +179,11 @@ bkcore.hexgl.tracks.Cityscape = { this.materials.start = new THREE.MeshBasicMaterial({ map: this.lib.get("textures", "track.cityscape.start.diffuse"), - ambient: 0xcccccc + ambient: 0xcccccc }); this.materials.startBanner = new THREE.MeshBasicMaterial({ - map: this.lib.get("textures", "track.cityscape.start.banner"), + map: this.lib.get("textures", "track.cityscape.start.banner"), transparent: false }); } @@ -223,7 +225,7 @@ bkcore.hexgl.tracks.Cityscape = { }); this.materials.booster = new THREE.MeshBasicMaterial({ - map: this.lib.get("textures", "booster.diffuse"), + map: this.lib.get("textures", "booster.diffuse"), transparent: true }); @@ -262,7 +264,7 @@ bkcore.hexgl.tracks.Cityscape = { }); this.materials.startBanner = new THREE.MeshBasicMaterial({ - map: this.lib.get("textures", "track.cityscape.start.banner"), + map: this.lib.get("textures", "track.cityscape.start.banner"), transparent: false }); } @@ -299,9 +301,9 @@ bkcore.hexgl.tracks.Cityscape = { var ambient = 0xbbbbbb, diffuse = 0xffffff, specular = 0xffffff, shininess = 42, scale = 23; - // MAIN SCENE + // MAIN SCENE var camera = new THREE.PerspectiveCamera( 70, ctx.width / ctx.height, 1, 60000 ); - + var scene = new THREE.Scene(); scene.add( camera ); scene.add( new THREE.AmbientLight( ambient ) ); @@ -330,15 +332,15 @@ bkcore.hexgl.tracks.Cityscape = { // SHIP var ship = ctx.createMesh(scene, this.lib.get("geometries", "ship.feisar"), -1134*2, 10, -443*2, this.materials.ship); - + var booster = ctx.createMesh(ship, this.lib.get("geometries", "booster"), 0, 0.665, -3.8, this.materials.booster); booster.depthWrite = false; - var boosterSprite = new THREE.Sprite({ - map: this.lib.get("textures", "booster.sprite"), - blending: THREE.AdditiveBlending, - useScreenCoordinates: false, - color: 0xffffff + var boosterSprite = new THREE.Sprite({ + map: this.lib.get("textures", "booster.sprite"), + blending: THREE.AdditiveBlending, + useScreenCoordinates: false, + color: 0xffffff }); boosterSprite.scale.set(0.02, 0.02, 0.02); boosterSprite.mergeWith3D = false; @@ -408,7 +410,7 @@ bkcore.hexgl.tracks.Cityscape = { var dt = delta/16.6; this.objects.components.shipControls.update(dt); - + this.objects.components.shipEffects.update(dt); this.objects.components.cameraChase.update(dt, this.objects.components.shipControls.getSpeedRatio()); @@ -424,9 +426,9 @@ bkcore.hexgl.tracks.Cityscape = { this.objects.composers.game.render(dt); if(this.objects.hud) this.objects.hud.update( - this.objects.components.shipControls.getRealSpeed(100), - this.objects.components.shipControls.getRealSpeedRatio(), - this.objects.components.shipControls.getShield(100), + this.objects.components.shipControls.getRealSpeed(100), + this.objects.components.shipControls.getRealSpeedRatio(), + this.objects.components.shipControls.getShield(100), this.objects.components.shipControls.getShieldRatio() ); if(this.objects.components.shipControls.getShieldRatio() < 0.2) @@ -444,4 +446,4 @@ bkcore.hexgl.tracks.Cityscape = { lowFPS: 0 }); } -} \ No newline at end of file +} diff --git a/css/bg.jpg b/css/bg.jpg new file mode 100644 index 0000000..dbf5ed2 Binary files /dev/null and b/css/bg.jpg differ diff --git a/css/help-0.png b/css/help-0.png new file mode 100644 index 0000000..27c3735 Binary files /dev/null and b/css/help-0.png differ diff --git a/css/help-1.png b/css/help-1.png new file mode 100644 index 0000000..28d36d2 Binary files /dev/null and b/css/help-1.png differ diff --git a/css/help-2.png b/css/help-2.png new file mode 100644 index 0000000..97910f0 Binary files /dev/null and b/css/help-2.png differ diff --git a/css/multi.css b/css/multi.css new file mode 100644 index 0000000..5047357 --- /dev/null +++ b/css/multi.css @@ -0,0 +1,234 @@ +@-webkit-keyframes anim { + 0% { -webkit-transform: translateY(10px) } + 50% { -webkit-transform: translateY(-10px) } + 100% { -webkit-transform: translateY(10px) } +} +@-moz-keyframes anim { + 0% { -moz-transform: translateY(10px) } + 50% { -moz-transform: translateY(-10px) } + 100% { -moz-transform: translateY(10px) } +} +@-o-keyframes anim { + 0% { -o-transform: translateY(10px) } + 50% { -o-transform: translateY(-10px) } + 100% { -o-transform: translateY(10px) } +} +@keyframes anim { + 0% { transform: translateY(10px) } + 50% { transform: translateY(-10px) } + 100% { transform: translateY(10px) } +} + +@-webkit-keyframes animbg { + 0% { -webkit-transform: translateY(5px) } + 50% { -webkit-transform: translateY(-5px) } + 100% { -webkit-transform: translateY(5px) } +} +@-moz-keyframes animbg { + 0% { -moz-transform: translateY(5px) } + 50% { -moz-transform: translateY(-5px) } + 100% { -moz-transform: translateY(5px) } +} +@-o-keyframes animbg { + 0% { -o-transform: translateY(5px) } + 50% { -o-transform: translateY(-5px) } + 100% { -o-transform: translateY(5px) } +} +@keyframes animbg { + 0% { transform: translateY(5px) } + 50% { transform: translateY(-5px) } + 100% { transform: translateY(5px) } +} + +* { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +html, body { + overflow: hidden; + font-family: 'BebasNeueRegular', arial, sans-serif; + background: white; +} + +#global { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 0; + background: url('bg.jpg') no-repeat center center fixed; + overflow: hidden; + text-align: center; + -moz-background-size: cover; + -webkit-background-size: cover; + -ms-background-size: cover; + -o-background-size: cover; + background-size: cover; + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: animbg 3s ease-in-out infinite; + -moz-animation: animbg 3s ease-in-out infinite; + -o-animation: animbg 3s ease-in-out infinite; + animation: animbg 3s ease-in-out infinite; +} + +#title { + position: absolute; + top: 5%; + right: 0; + bottom: 5%; + left: 0; + z-index: 1; + background: url('title.png') no-repeat center top; + -moz-background-size: auto 50%; + -webkit-background-size: auto 50%; + -ms-background-size: auto 50%; + -o-background-size: auto 50%; + background-size: auto 50%; + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: anim 3s ease-in-out infinite; + -moz-animation: anim 3s ease-in-out infinite; + -o-animation: anim 3s ease-in-out infinite; + animation: anim 3s ease-in-out infinite; +} + +#menucontainer { + position: absolute; + top: auto; + right: 0; + bottom: 10%; + left: 0; + z-index: 2; +} + +#menu { + position: relative; + display: block; + width: 100%; + max-width: 600px; + margin: auto; + text-align: center; + font-size: 2em; + font-family: 'BebasNeueRegular', arial, sans-serif; + text-transform: uppercase; + color: #4190bb; +} + +#menu div { + padding: 0.1em 0 0 0; + margin: 0 0; + cursor: pointer; + -moz-text-shadow: 0 0 10px rgb(255,255,255); + -webkit-text-shadow: 0 0 10px rgb(255,255,255); + text-shadow: 0 0 10px rgb(255,255,255); + -webkit-transform-origin-y: 50%; + -webkit-transition: -webkit-transform 0.2s; + -webkit-transform: translateZ(0px) scaleY(0.8); + transform-origin-y: 50%; + transition: transform 0.2s ease; + transform: translateZ(0px) scaleY(0.8); + background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIwIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIwLjUiLz4KICAgIDxzdG9wIG9mZnNldD0iNjAlIiBzdG9wLWNvbG9yPSIjZmZmZmZmIiBzdG9wLW9wYWNpdHk9IjAuNSIvPgogICAgPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjZmZmZmZmIiBzdG9wLW9wYWNpdHk9IjAiLz4KICA8L2xpbmVhckdyYWRpZW50PgogIDxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZC11Y2dnLWdlbmVyYXRlZCkiIC8+Cjwvc3ZnPg==); + background: -moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.5) 40%, rgba(255,255,255,0.5) 60%, rgba(255,255,255,0) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0)), color-stop(40%,rgba(255,255,255,0.5)), color-stop(60%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(left, rgba(255,255,255,0) 0%,rgba(255,255,255,0.5) 40%,rgba(255,255,255,0.5) 60%,rgba(255,255,255,0) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(left, rgba(255,255,255,0) 0%,rgba(255,255,255,0.5) 40%,rgba(255,255,255,0.5) 60%,rgba(255,255,255,0) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(left, rgba(255,255,255,0) 0%,rgba(255,255,255,0.5) 40%,rgba(255,255,255,0.5) 60%,rgba(255,255,255,0) 100%); /* IE10+ */ + background: linear-gradient(to right, rgba(255,255,255,0) 0%,rgba(255,255,255,0.5) 40%,rgba(255,255,255,0.5) 60%,rgba(255,255,255,0) 100%); /* W3C */ +} + +#menu div:hover { + color: #f66439; + -webkit-transform: scaleY(1.0); + transform: scaleY(1.1); +} + +#start { + font-size: 1.8em; + color: #f66439; +} + +#start:hover { + color: #f8854b !important; +} + +#step-2 { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: black; + vertical-align: bottom; + text-align: center; + padding: 20px; + color: white; + font-size: 2em; + background-repeat: no-repeat; + background-position: center center; + -moz-background-size: 60% auto; + -webkit-background-size: 60% auto; + -ms-background-size: 60% auto; + -o-background-size: 60% auto; + background-size: 60% auto; +} + +#step-3 { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: black; +} + +#step-3 #progressbar { + position: absolute; + top: 0; + right: auto; + bottom: 0; + left: 0; + width: 0%; + background: white; +} + +#step-5 { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: black; + text-align: center; + padding: 100px 20px; + color: white; + font-size: 2em; +} + +#step-5 #time { + font-size: 4em +} + +#leapinfo { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgba(0,0,0,0.8); + color: white; + text-align: center; + font-size: 3em; + padding-top: 200px; + z-index: 999999; +} diff --git a/css/title.png b/css/title.png new file mode 100644 index 0000000..9a3a509 Binary files /dev/null and b/css/title.png differ diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000..d7e74ff Binary files /dev/null and b/favicon.png differ diff --git a/index-leap.html b/index-leap.html new file mode 100644 index 0000000..c36e1c5 --- /dev/null +++ b/index-leap.html @@ -0,0 +1,119 @@ + + + + HexGL dev page + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index-old.html b/index-old.html new file mode 100644 index 0000000..bebb428 --- /dev/null +++ b/index-old.html @@ -0,0 +1,118 @@ + + + + HexGL dev page + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.html b/index.html index 1f0ac20..b75272f 100644 --- a/index.html +++ b/index.html @@ -1,23 +1,26 @@ - HexGL dev page + HexGL by BKcore + + + + + + + + + + + -
-
+
+
+
+
+ +
+ + + + + + + @@ -66,51 +109,7 @@ - + diff --git a/launch.coffee b/launch.coffee new file mode 100644 index 0000000..bd7ae5d --- /dev/null +++ b/launch.coffee @@ -0,0 +1,59 @@ +$ = (_) -> document.getElementById _ + +init = (controlType, quality, platform, godmode) -> + hexGL = new bkcore.hexgl.HexGL( + document: document + width: window.innerWidth + height: window.innerHeight + container: $ 'main' + overlay: $ 'overlay' + gameover: $ 'step-5' + quality: quality + difficulty: 0, + half: (platform is 1 and quality < 1) + mobile: platform is 1 + hud: platform is 0 + controlType: controlType + godmode: godmode + track: 'Cityscape' + ) + window.hexGL=hexGL + + progressbar = $ 'progressbar' + hexGL.load( + onLoad: -> + console.log 'LOADED.' + hexGL.init() + $('step-3').style.display = 'none' + $('step-4').style.display = 'block' + hexGL.start() + onError: (s) -> + console.error "Error loading #{ s }." + onProgress: (p, t, n) -> + console.log("LOADED "+t+" : "+n+" ( "+p.loaded+" / "+p.total+" ).") + progressbar.style.width = "#{ p.loaded / p.total * 100 }%" + ) + +u = bkcore.Utils.getURLParameter +s = [ + ['controlType', ['KEYBOARD', 'TOUCH', 'LEAP MOTION CONTROLLER'], 0, 0, 'Controls: '] + ['quality', ['LOW', 'MID', 'HIGH'], 2, 2, 'Quality: '] + ['platform', ['DESKTOP', 'MOBILE'], 0, 0, 'Platform: '] + ['godmode', ['OFF', 'ON'], 0, 1, 'Godmode: '] +] +for a in s + do(a)-> + a[3] = u(a[0]) ? a[2] + e = $ "s-#{a[0]}" + (f = -> e.innerHTML = a[4]+a[1][a[3]])() + e.onclick = -> f(a[3] = (a[3]+1)%a[1].length) +$('start').onclick = -> + $('step-1').style.display = 'none' + $('step-2').style.display = 'block' + $('step-2').style.backgroundImage = "url(css/help-#{s[0][3]}.png)" +$('step-2').onclick = -> + $('step-2').style.display = 'none' + $('step-3').style.display = 'block' + init s[0][3], s[1][3], s[2][3], s[3][3] +$('step-5').onclick = -> + window.location.reload() diff --git a/launch.js b/launch.js new file mode 100644 index 0000000..99be3e7 --- /dev/null +++ b/launch.js @@ -0,0 +1,83 @@ +// Generated by CoffeeScript 1.6.3 +(function() { + var $, a, init, s, u, _fn, _i, _len; + + $ = function(_) { + return document.getElementById(_); + }; + + init = function(controlType, quality, platform, godmode) { + var hexGL, progressbar; + hexGL = new bkcore.hexgl.HexGL({ + document: document, + width: window.innerWidth, + height: window.innerHeight, + container: $('main'), + overlay: $('overlay'), + gameover: $('step-5'), + quality: quality, + difficulty: 0, + half: platform === 1 && quality < 1, + mobile: platform === 1, + hud: platform === 0, + controlType: controlType, + godmode: godmode, + track: 'Cityscape' + }); + window.hexGL = hexGL; + progressbar = $('progressbar'); + return hexGL.load({ + onLoad: function() { + console.log('LOADED.'); + hexGL.init(); + $('step-3').style.display = 'none'; + $('step-4').style.display = 'block'; + return hexGL.start(); + }, + onError: function(s) { + return console.error("Error loading " + s + "."); + }, + onProgress: function(p, t, n) { + console.log("LOADED " + t + " : " + n + " ( " + p.loaded + " / " + p.total + " )."); + return progressbar.style.width = "" + (p.loaded / p.total * 100) + "%"; + } + }); + }; + + u = bkcore.Utils.getURLParameter; + + s = [['controlType', ['KEYBOARD', 'TOUCH', 'LEAP MOTION CONTROLLER'], 0, 0, 'Controls: '], ['quality', ['LOW', 'MID', 'HIGH'], 2, 2, 'Quality: '], ['platform', ['DESKTOP', 'MOBILE'], 0, 0, 'Platform: '], ['godmode', ['OFF', 'ON'], 0, 1, 'Godmode: ']]; + + _fn = function(a) { + var e, f, _ref; + a[3] = (_ref = u(a[0])) != null ? _ref : a[2]; + e = $("s-" + a[0]); + (f = function() { + return e.innerHTML = a[4] + a[1][a[3]]; + })(); + return e.onclick = function() { + return f(a[3] = (a[3] + 1) % a[1].length); + }; + }; + for (_i = 0, _len = s.length; _i < _len; _i++) { + a = s[_i]; + _fn(a); + } + + $('start').onclick = function() { + $('step-1').style.display = 'none'; + $('step-2').style.display = 'block'; + return $('step-2').style.backgroundImage = "url(css/help-" + s[0][3] + ".png)"; + }; + + $('step-2').onclick = function() { + $('step-2').style.display = 'none'; + $('step-3').style.display = 'block'; + return init(s[0][3], s[1][3], s[2][3], s[3][3]); + }; + + $('step-5').onclick = function() { + return window.location.reload(); + }; + +}).call(this); diff --git a/libs/leap-0.4.1.min.js b/libs/leap-0.4.1.min.js new file mode 100644 index 0000000..6de4100 --- /dev/null +++ b/libs/leap-0.4.1.min.js @@ -0,0 +1,3 @@ +!function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s=this.size)return undefined;if(i>=this._buf.length)return undefined;return this._buf[(this.pos-i-1)%this.size]};CircularBuffer.prototype.push=function(o){this._buf[this.pos%this.size]=o;return this.pos++}},{}],3:[function(require,module,exports){var chooseProtocol=require("../protocol").chooseProtocol,EventEmitter=require("events").EventEmitter,_=require("underscore");var BaseConnection=module.exports=function(opts){this.opts=_.defaults(opts||{},{host:"127.0.0.1",enableGestures:false,port:6437,background:false,requestProtocolVersion:4});this.host=this.opts.host;this.port=this.opts.port;this.protocolVersionVerified=false;this.on("ready",function(){this.enableGestures(this.opts.enableGestures);this.setBackground(this.opts.background)})};BaseConnection.prototype.getUrl=function(){return"ws://"+this.host+":"+this.port+"/v"+this.opts.requestProtocolVersion+".json"};BaseConnection.prototype.setBackground=function(state){this.opts.background=state;if(this.protocol&&this.protocol.sendBackground&&this.background!==this.opts.background){this.background=this.opts.background;this.protocol.sendBackground(this,this.opts.background)}};BaseConnection.prototype.handleOpen=function(){if(!this.connected){this.connected=true;this.emit("connect")}};BaseConnection.prototype.enableGestures=function(enabled){this.gesturesEnabled=enabled?true:false;this.send(this.protocol.encode({enableGestures:this.gesturesEnabled}))};BaseConnection.prototype.handleClose=function(code,reason){if(!this.connected)return;this.disconnect();if(code===1001&&this.opts.requestProtocolVersion>1){if(this.protocolVersionVerified){this.protocolVersionVerified=false}else{this.opts.requestProtocolVersion--}}this.startReconnection()};BaseConnection.prototype.startReconnection=function(){var connection=this;this.reconnectionTimer=setInterval(function(){connection.reconnect()},1e3)};BaseConnection.prototype.disconnect=function(){if(!this.socket)return;this.socket.close();delete this.socket;delete this.protocol;if(this.connected){this.connected=false;this.emit("disconnect")}return true};BaseConnection.prototype.reconnect=function(){if(this.connected){clearInterval(this.reconnectionTimer)}else{this.disconnect();this.connect()}};BaseConnection.prototype.handleData=function(data){var message=JSON.parse(data);var messageEvent;if(this.protocol===undefined){messageEvent=this.protocol=chooseProtocol(message);this.protocolVersionVerified=true;this.emit("ready")}else{messageEvent=this.protocol(message)}this.emit(messageEvent.type,messageEvent)};BaseConnection.prototype.connect=function(){if(this.socket)return;this.socket=this.setupSocket();return true};BaseConnection.prototype.send=function(data){this.socket.send(data)};BaseConnection.prototype.reportFocus=function(state){if(this.focusedState===state)return;this.focusedState=state;this.emit(this.focusedState?"focus":"blur");if(this.protocol&&this.protocol.sendFocused){this.protocol.sendFocused(this,this.focusedState)}};_.extend(BaseConnection.prototype,EventEmitter.prototype)},{"../protocol":14,events:19,underscore:22}],4:[function(require,module,exports){var BaseConnection=module.exports=require("./base"),_=require("underscore");var BrowserConnection=module.exports=function(opts){BaseConnection.call(this,opts);var connection=this;this.on("ready",function(){connection.startFocusLoop()});this.on("disconnect",function(){connection.stopFocusLoop()})};_.extend(BrowserConnection.prototype,BaseConnection.prototype);BrowserConnection.prototype.setupSocket=function(){var connection=this;var socket=new WebSocket(this.getUrl());socket.onopen=function(){connection.handleOpen()};socket.onclose=function(data){connection.handleClose(data["code"],data["reason"])};socket.onmessage=function(message){connection.handleData(message.data)};return socket};BrowserConnection.prototype.startFocusLoop=function(){if(this.focusDetectorTimer)return;var connection=this;var propertyName=null;if(typeof document.hidden!=="undefined"){propertyName="hidden"}else if(typeof document.mozHidden!=="undefined"){propertyName="mozHidden"}else if(typeof document.msHidden!=="undefined"){propertyName="msHidden"}else if(typeof document.webkitHidden!=="undefined"){propertyName="webkitHidden"}else{propertyName=undefined}if(connection.windowVisible===undefined){connection.windowVisible=propertyName===undefined?true:document[propertyName]===false}var focusListener=window.addEventListener("focus",function(e){connection.windowVisible=true;updateFocusState()});var blurListener=window.addEventListener("blur",function(e){connection.windowVisible=false;updateFocusState()});this.on("disconnect",function(){window.removeEventListener("focus",focusListener);window.removeEventListener("blur",blurListener)});var updateFocusState=function(){var isVisible=propertyName===undefined?true:document[propertyName]===false;connection.reportFocus(isVisible&&connection.windowVisible)};this.focusDetectorTimer=setInterval(updateFocusState,100)};BrowserConnection.prototype.stopFocusLoop=function(){if(!this.focusDetectorTimer)return;clearTimeout(this.focusDetectorTimer);delete this.focusDetectorTimer}},{"./base":3,underscore:22}],5:[function(require,module,exports){var WebSocket=require("ws"),BaseConnection=require("./base"),_=require("underscore");var NodeConnection=module.exports=function(opts){BaseConnection.call(this,opts);var connection=this;this.on("ready",function(){connection.reportFocus(true)})};_.extend(NodeConnection.prototype,BaseConnection.prototype);NodeConnection.prototype.setupSocket=function(){var connection=this;var socket=new WebSocket(this.getUrl());socket.on("open",function(){connection.handleOpen()});socket.on("message",function(m){connection.handleData(m)});socket.on("close",function(code,reason){connection.handleClose(code,reason)});socket.on("error",function(){connection.startReconnection()});return socket}},{"./base":3,underscore:22,ws:23}],6:[function(require,module,exports){var process=require("__browserify_process");var Frame=require("./frame"),Hand=require("./hand"),Pointable=require("./pointable"),CircularBuffer=require("./circular_buffer"),Pipeline=require("./pipeline"),EventEmitter=require("events").EventEmitter,gestureListener=require("./gesture").gestureListener,_=require("underscore");var Controller=module.exports=function(opts){var inNode=typeof process!=="undefined"&&process.versions&&process.versions.node;opts=_.defaults(opts||{},{inNode:inNode});this.inNode=opts.inNode;opts=_.defaults(opts||{},{frameEventName:this.useAnimationLoop()?"animationFrame":"deviceFrame",suppressAnimationLoop:false});this.suppressAnimationLoop=opts.suppressAnimationLoop;this.frameEventName=opts.frameEventName;this.useAllPlugins=opts.useAllPlugins||false;this.history=new CircularBuffer(200);this.lastFrame=Frame.Invalid;this.lastValidFrame=Frame.Invalid;this.lastConnectionFrame=Frame.Invalid;this.accumulatedGestures=[];if(opts.connectionType===undefined){this.connectionType=this.inBrowser()?require("./connection/browser"):require("./connection/node")}else{this.connectionType=opts.connectionType}this.connection=new this.connectionType(opts);this._pluginPipelineSteps={};this._pluginExtendedMethods={};if(opts.useAllPlugins)this.useRegisteredPlugins();this.setupConnectionEvents()};Controller.prototype.gesture=function(type,cb){var creator=gestureListener(this,type);if(cb!==undefined){creator.stop(cb)}return creator};Controller.prototype.setBackground=function(state){this.connection.setBackground(state);return this};Controller.prototype.inBrowser=function(){return!this.inNode};Controller.prototype.useAnimationLoop=function(){return this.inBrowser()&&typeof chrome==="undefined"};Controller.prototype.connect=function(){var controller=this;if(this.connection.connect()&&this.inBrowser()&&!controller.suppressAnimationLoop){var callback=function(){controller.emit("animationFrame",controller.lastConnectionFrame);window.requestAnimationFrame(callback)};window.requestAnimationFrame(callback)}return this};Controller.prototype.disconnect=function(){this.connection.disconnect();return this};Controller.prototype.frame=function(num){return this.history.get(num)||Frame.Invalid};Controller.prototype.loop=function(callback){switch(callback.length){case 1:this.on(this.frameEventName,callback);break;case 2:var controller=this;var scheduler=null;var immediateRunnerCallback=function(frame){callback(frame,function(){if(controller.lastFrame!=frame){immediateRunnerCallback(controller.lastFrame)}else{controller.once(controller.frameEventName,immediateRunnerCallback)}})};this.once(this.frameEventName,immediateRunnerCallback);break}return this.connect()};Controller.prototype.addStep=function(step){if(!this.pipeline)this.pipeline=new Pipeline(this);this.pipeline.addStep(step)};Controller.prototype.processFrame=function(frame){if(frame.gestures){this.accumulatedGestures=this.accumulatedGestures.concat(frame.gestures)}if(this.pipeline){frame=this.pipeline.run(frame);if(!frame)frame=Frame.Invalid}this.lastConnectionFrame=frame;this.emit("deviceFrame",frame)};Controller.prototype.processFinishedFrame=function(frame){this.lastFrame=frame;if(frame.valid){this.lastValidFrame=frame}frame.controller=this;frame.historyIdx=this.history.push(frame);if(frame.gestures){frame.gestures=this.accumulatedGestures;this.accumulatedGestures=[];for(var gestureIdx=0;gestureIdx!=frame.gestures.length;gestureIdx++){this.emit("gesture",frame.gestures[gestureIdx],frame)}}this.emit("frame",frame)};Controller.prototype.setupConnectionEvents=function(){var controller=this;this.connection.on("frame",function(frame){controller.processFrame(frame)});this.on(this.frameEventName,function(frame){controller.processFinishedFrame(frame)});this.connection.on("disconnect",function(){controller.emit("disconnect")});this.connection.on("ready",function(){controller.emit("ready")});this.connection.on("connect",function(){controller.emit("connect")});this.connection.on("focus",function(){controller.emit("focus")});this.connection.on("blur",function(){controller.emit("blur")});this.connection.on("protocol",function(protocol){controller.emit("protocol",protocol)});this.connection.on("deviceConnect",function(evt){controller.emit(evt.state?"deviceConnected":"deviceDisconnected")})};Controller._pluginFactories={};Controller.plugin=function(pluginName,factory){if(this._pluginFactories[pluginName]){throw'Plugin "'+pluginName+'" already registered'}return this._pluginFactories[pluginName]=factory};Controller.plugins=function(){return _.keys(this._pluginFactories)};Controller.prototype.use=function(pluginName,options){var functionOrHash,pluginFactory,key,pluginInstance,klass;pluginFactory=typeof pluginName=="function"?pluginName:Controller._pluginFactories[pluginName];if(!pluginFactory){throw"Leap Plugin "+pluginName+" not found."}options||(options={});pluginInstance=pluginFactory.call(this,options);for(key in pluginInstance){functionOrHash=pluginInstance[key];if(typeof functionOrHash==="function"){if(!this.pipeline)this.pipeline=new Pipeline(this);if(!this._pluginPipelineSteps[pluginName])this._pluginPipelineSteps[pluginName]=[];this._pluginPipelineSteps[pluginName].push(this.pipeline.addWrappedStep(key,functionOrHash))}else{if(!this._pluginExtendedMethods[pluginName])this._pluginExtendedMethods[pluginName]=[];switch(key){case"frame":klass=Frame;break;case"hand":klass=Hand;break;case"pointable":klass=Pointable;break;default:throw pluginName+' specifies invalid object type "'+key+'" for prototypical extension'}_.extend(klass.prototype,functionOrHash);_.extend(klass.Invalid,functionOrHash);this._pluginExtendedMethods[pluginName].push([klass,functionOrHash])}}return this};Controller.prototype.stopUsing=function(pluginName){var steps=this._pluginPipelineSteps[pluginName],extMethodHashes=this._pluginExtendedMethods[pluginName],i=0,klass,extMethodHash;if(steps){for(i=0;i
Hands:
";for(var handIdx=0,handCount=this.hands.length;handIdx!=handCount;handIdx++){out+=" "+this.hands[handIdx].toString()+"
"}out+="

Pointables:
";for(var pointableIdx=0,pointableCount=this.pointables.length;pointableIdx!=pointableCount;pointableIdx++){out+=" "+this.pointables[pointableIdx].toString()+"
"}if(this.gestures){out+="

Gestures:
";for(var gestureIdx=0,gestureCount=this.gestures.length;gestureIdx!=gestureCount;gestureIdx++){out+=" "+this.gestures[gestureIdx].toString()+"
"}}out+="

Raw JSON:
";out+=JSON.stringify(this.data);return out};Frame.Invalid={valid:false,hands:[],fingers:[],tools:[],gestures:[],pointables:[],pointable:function(){return Pointable.Invalid},finger:function(){return Pointable.Invalid},hand:function(){return Hand.Invalid},toString:function(){return"invalid frame"},dump:function(){return this.toString()},rotationAngle:function(){return 0},rotationMatrix:function(){return mat3.create()},rotationAxis:function(){return vec3.create()},scaleFactor:function(){return 1},translation:function(){return vec3.create()}}},{"./gesture":8,"./hand":9,"./interaction_box":11,"./pointable":13,"gl-matrix":21,underscore:22}],8:[function(require,module,exports){var glMatrix=require("gl-matrix"),vec3=glMatrix.vec3,EventEmitter=require("events").EventEmitter,_=require("underscore");var createGesture=exports.createGesture=function(data){var gesture;switch(data.type){case"circle":gesture=new CircleGesture(data);break;case"swipe":gesture=new SwipeGesture(data);break;case"screenTap":gesture=new ScreenTapGesture(data);break;case"keyTap":gesture=new KeyTapGesture(data);break;default:throw"unkown gesture type"}gesture.id=data.id;gesture.handIds=data.handIds;gesture.pointableIds=data.pointableIds;gesture.duration=data.duration;gesture.state=data.state;gesture.type=data.type;return gesture};var gestureListener=exports.gestureListener=function(controller,type){var handlers={};var gestureMap={};controller.on("gesture",function(gesture,frame){if(gesture.type==type){if(gesture.state=="start"||gesture.state=="stop"){if(gestureMap[gesture.id]===undefined){var gestureTracker=new Gesture(gesture,frame);gestureMap[gesture.id]=gestureTracker;_.each(handlers,function(cb,name){gestureTracker.on(name,cb)})}}gestureMap[gesture.id].update(gesture,frame);if(gesture.state=="stop"){delete gestureMap[gesture.id]}}});var builder={start:function(cb){handlers["start"]=cb;return builder},stop:function(cb){handlers["stop"]=cb;return builder},complete:function(cb){handlers["stop"]=cb;return builder},update:function(cb){handlers["update"]=cb;return builder}};return builder};var Gesture=exports.Gesture=function(gesture,frame){this.gestures=[gesture];this.frames=[frame]};Gesture.prototype.update=function(gesture,frame){this.lastGesture=gesture;this.lastFrame=frame;this.gestures.push(gesture);this.frames.push(frame);this.emit(gesture.state,this)};Gesture.prototype.translation=function(){return vec3.subtract(vec3.create(),this.lastGesture.startPosition,this.lastGesture.position)};_.extend(Gesture.prototype,EventEmitter.prototype);var CircleGesture=function(data){this.center=data.center;this.normal=data.normal;this.progress=data.progress;this.radius=data.radius};CircleGesture.prototype.toString=function(){return"CircleGesture ["+JSON.stringify(this)+"]"};var SwipeGesture=function(data){this.startPosition=data.startPosition;this.position=data.position;this.direction=data.direction;this.speed=data.speed};SwipeGesture.prototype.toString=function(){return"SwipeGesture ["+JSON.stringify(this)+"]"};var ScreenTapGesture=function(data){this.position=data.position;this.direction=data.direction;this.progress=data.progress};ScreenTapGesture.prototype.toString=function(){return"ScreenTapGesture ["+JSON.stringify(this)+"]"};var KeyTapGesture=function(data){this.position=data.position;this.direction=data.direction;this.progress=data.progress};KeyTapGesture.prototype.toString=function(){return"KeyTapGesture ["+JSON.stringify(this)+"]"}},{events:19,"gl-matrix":21,underscore:22}],9:[function(require,module,exports){var Pointable=require("./pointable"),glMatrix=require("gl-matrix"),mat3=glMatrix.mat3,vec3=glMatrix.vec3,_=require("underscore");var Hand=module.exports=function(data){this.id=data.id;this.palmPosition=data.palmPosition;this.direction=data.direction;this.palmVelocity=data.palmVelocity;this.palmNormal=data.palmNormal;this.sphereCenter=data.sphereCenter;this.sphereRadius=data.sphereRadius;this.valid=true;this.pointables=[];this.fingers=[];this.tools=[];this._translation=data.t;this._rotation=_.flatten(data.r);this._scaleFactor=data.s;this.timeVisible=data.timeVisible;this.stabilizedPalmPosition=data.stabilizedPalmPosition};Hand.prototype.finger=function(id){var finger=this.frame.finger(id);return finger&&finger.handId==this.id?finger:Pointable.Invalid};Hand.prototype.rotationAngle=function(sinceFrame,axis){if(!this.valid||!sinceFrame.valid)return 0;var sinceHand=sinceFrame.hand(this.id);if(!sinceHand.valid)return 0;var rot=this.rotationMatrix(sinceFrame);var cs=(rot[0]+rot[4]+rot[8]-1)*.5;var angle=Math.acos(cs);angle=isNaN(angle)?0:angle;if(axis!==undefined){var rotAxis=this.rotationAxis(sinceFrame);angle*=vec3.dot(rotAxis,vec3.normalize(vec3.create(),axis))}return angle};Hand.prototype.rotationAxis=function(sinceFrame){if(!this.valid||!sinceFrame.valid)return vec3.create();var sinceHand=sinceFrame.hand(this.id);if(!sinceHand.valid)return vec3.create();return vec3.normalize(vec3.create(),[this._rotation[7]-sinceHand._rotation[5],this._rotation[2]-sinceHand._rotation[6],this._rotation[3]-sinceHand._rotation[1]])};Hand.prototype.rotationMatrix=function(sinceFrame){if(!this.valid||!sinceFrame.valid)return mat3.create();var sinceHand=sinceFrame.hand(this.id);if(!sinceHand.valid)return mat3.create();var transpose=mat3.transpose(mat3.create(),this._rotation);var m=mat3.multiply(mat3.create(),sinceHand._rotation,transpose);return m};Hand.prototype.scaleFactor=function(sinceFrame){if(!this.valid||!sinceFrame.valid)return 1;var sinceHand=sinceFrame.hand(this.id);if(!sinceHand.valid)return 1;return Math.exp(this._scaleFactor-sinceHand._scaleFactor)};Hand.prototype.translation=function(sinceFrame){if(!this.valid||!sinceFrame.valid)return vec3.create();var sinceHand=sinceFrame.hand(this.id);if(!sinceHand.valid)return vec3.create();return[this._translation[0]-sinceHand._translation[0],this._translation[1]-sinceHand._translation[1],this._translation[2]-sinceHand._translation[2]]};Hand.prototype.toString=function(){return"Hand [ id: "+this.id+" | palm velocity:"+this.palmVelocity+" | sphere center:"+this.sphereCenter+" ] "};Hand.prototype.pitch=function(){return Math.atan2(this.direction[1],-this.direction[2])};Hand.prototype.yaw=function(){return Math.atan2(this.direction[0],-this.direction[2])};Hand.prototype.roll=function(){return Math.atan2(this.palmNormal[0],-this.palmNormal[1])};Hand.Invalid={valid:false,fingers:[],tools:[],pointables:[],pointable:function(){return Pointable.Invalid},finger:function(){return Pointable.Invalid},toString:function(){return"invalid frame"},dump:function(){return this.toString()},rotationAngle:function(){return 0},rotationMatrix:function(){return mat3.create()},rotationAxis:function(){return vec3.create()},scaleFactor:function(){return 1},translation:function(){return vec3.create()}}},{"./pointable":13,"gl-matrix":21,underscore:22}],10:[function(require,module,exports){require("./_header");module.exports={Controller:require("./controller"),Frame:require("./frame"),Gesture:require("./gesture"),Hand:require("./hand"),Pointable:require("./pointable"),InteractionBox:require("./interaction_box"),CircularBuffer:require("./circular_buffer"),UI:require("./ui"),glMatrix:require("gl-matrix"),mat3:require("gl-matrix").mat3,vec3:require("gl-matrix").vec3,loopController:undefined,version:require("./version.js"),loop:function(opts,callback){if(callback===undefined){callback=opts;opts={}}opts.useAllPlugins||(opts.useAllPlugins=true);if(!this.loopController)this.loopController=new this.Controller(opts);this.loopController.loop(callback);return this.loopController},plugin:function(name,options){this.Controller.plugin(name,options)}}},{"./_header":1,"./circular_buffer":2,"./controller":6,"./frame":7,"./gesture":8,"./hand":9,"./interaction_box":11,"./pointable":13,"./ui":15,"./version.js":18,"gl-matrix":21}],11:[function(require,module,exports){var glMatrix=require("gl-matrix"),vec3=glMatrix.vec3;var InteractionBox=module.exports=function(data){this.valid=true;this.center=data.center;this.size=data.size;this.width=data.size[0];this.height=data.size[1];this.depth=data.size[2]};InteractionBox.prototype.denormalizePoint=function(normalizedPosition){return vec3.fromValues((normalizedPosition[0]-.5)*this.size[0]+this.center[0],(normalizedPosition[1]-.5)*this.size[1]+this.center[1],(normalizedPosition[2]-.5)*this.size[2]+this.center[2])};InteractionBox.prototype.normalizePoint=function(position,clamp){var vec=vec3.fromValues((position[0]-this.center[0])/this.size[0]+.5,(position[1]-this.center[1])/this.size[1]+.5,(position[2]-this.center[2])/this.size[2]+.5);if(clamp){vec[0]=Math.min(Math.max(vec[0],0),1);vec[1]=Math.min(Math.max(vec[1],0),1);vec[2]=Math.min(Math.max(vec[2],0),1)}return vec};InteractionBox.prototype.toString=function(){return"InteractionBox [ width:"+this.width+" | height:"+this.height+" | depth:"+this.depth+" ]"};InteractionBox.Invalid={valid:false}},{"gl-matrix":21}],12:[function(require,module,exports){var Pipeline=module.exports=function(controller){this.steps=[];this.controller=controller};Pipeline.prototype.addStep=function(step){this.steps.push(step)};Pipeline.prototype.run=function(frame){var stepsLength=this.steps.length;for(var i=0;i!=stepsLength;i++){if(!frame)break;frame=this.steps[i](frame)}return frame};Pipeline.prototype.removeStep=function(step){var index=this.steps.indexOf(step);if(index===-1)throw"Step not found in pipeline";this.steps.splice(index,1)};Pipeline.prototype.addWrappedStep=function(type,callback){var controller=this.controller,step=function(frame){var dependencies,i,len;dependencies=type=="frame"?[frame]:frame[type+"s"]||[];for(i=0,len=dependencies.length;i=this.start.x&&position.x<=this.end.x&&position.y>=this.start.y&&position.y<=this.end.y&&position.z>=this.start.z&&position.z<=this.end.z){return true}}return false};Region.prototype.listener=function(opts){var region=this;if(opts&&opts.nearThreshold)this.setupNearRegion(opts.nearThreshold);return function(frame){return region.updatePosition(frame)}};Region.prototype.clipper=function(){var region=this;return function(frame){region.updatePosition(frame);return region.enteredFrame?frame:null}};Region.prototype.setupNearRegion=function(distance){var nearRegion=this.nearRegion=new Region([this.start.x-distance,this.start.y-distance,this.start.z-distance],[this.end.x+distance,this.end.y+distance,this.end.z+distance]);var region=this;nearRegion.on("enter",function(frame){region.emit("near",frame)});nearRegion.on("exit",function(frame){region.emit("far",frame)});region.on("exit",function(frame){region.emit("near",frame)})};Region.prototype.updatePosition=function(frame){if(this.nearRegion)this.nearRegion.updatePosition(frame);if(this.hasPointables(frame)&&this.enteredFrame==null){this.enteredFrame=frame;this.emit("enter",this.enteredFrame)}else if(!this.hasPointables(frame)&&this.enteredFrame!=null){this.enteredFrame=null;this.emit("exit",this.enteredFrame)}return frame};Region.prototype.normalize=function(position){return new Vector([(position.x-this.start.x)/(this.end.x-this.start.x),(position.y-this.start.y)/(this.end.y-this.start.y),(position.z-this.start.z)/(this.end.z-this.start.z)])};Region.prototype.mapToXY=function(position,width,height){var normalized=this.normalize(position);var x=normalized.x,y=normalized.y;if(x>1)x=1;else if(x<-1)x=-1;if(y>1)y=1;else if(y<-1)y=-1;return[(x+1)/2*width,(1-y)/2*height,normalized.z]};_.extend(Region.prototype,EventEmitter.prototype)},{events:19,underscore:22}],18:[function(require,module,exports){module.exports={full:"0.4.1",major:0,minor:4,dot:1}},{}],19:[function(require,module,exports){var process=require("__browserify_process");if(!process.EventEmitter)process.EventEmitter=function(){};var EventEmitter=exports.EventEmitter=process.EventEmitter;var isArray=typeof Array.isArray==="function"?Array.isArray:function(xs){return Object.prototype.toString.call(xs)==="[object Array]"};function indexOf(xs,x){if(xs.indexOf)return xs.indexOf(x);for(var i=0;i0&&this._events[type].length>m){this._events[type].warned=true;console.error("(node) warning: possible EventEmitter memory "+"leak detected. %d listeners added. "+"Use emitter.setMaxListeners() to increase limit.",this._events[type].length);console.trace()}}this._events[type].push(listener)}else{this._events[type]=[this._events[type],listener]}return this};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.once=function(type,listener){var self=this;self.on(type,function g(){self.removeListener(type,g);listener.apply(this,arguments)});return this};EventEmitter.prototype.removeListener=function(type,listener){if("function"!==typeof listener){throw new Error("removeListener only takes instances of Function")}if(!this._events||!this._events[type])return this;var list=this._events[type];if(isArray(list)){var i=indexOf(list,listener);if(i<0)return this;list.splice(i,1);if(list.length==0)delete this._events[type]}else if(this._events[type]===listener){delete this._events[type]}return this};EventEmitter.prototype.removeAllListeners=function(type){if(arguments.length===0){this._events={};return this}if(type&&this._events&&this._events[type])this._events[type]=null;return this};EventEmitter.prototype.listeners=function(type){if(!this._events)this._events={};if(!this._events[type])this._events[type]=[];if(!isArray(this._events[type])){this._events[type]=[this._events[type]]}return this._events[type]};EventEmitter.listenerCount=function(emitter,type){var ret;if(!emitter._events||!emitter._events[type])ret=0;else if(typeof emitter._events[type]==="function")ret=1;else ret=emitter._events[type].length;return ret}},{__browserify_process:20}],20:[function(require,module,exports){var process=module.exports={};process.nextTick=function(){var canSetImmediate=typeof window!=="undefined"&&window.setImmediate;var canPost=typeof window!=="undefined"&&window.postMessage&&window.addEventListener;if(canSetImmediate){return function(f){return window.setImmediate(f)}}if(canPost){var queue=[];window.addEventListener("message",function(ev){if(ev.source===window&&ev.data==="process-tick"){ev.stopPropagation();if(queue.length>0){var fn=queue.shift();fn()}}},true);return function nextTick(fn){queue.push(fn);window.postMessage("process-tick","*")}}return function nextTick(fn){setTimeout(fn,0)}}();process.title="browser";process.browser=true;process.env={};process.argv=[];process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")}},{}],21:[function(require,module,exports){!function(){"use strict";var shim={};if(typeof exports==="undefined"){if(typeof define=="function"&&typeof define.amd=="object"&&define.amd){shim.exports={};define(function(){return shim.exports})}else{shim.exports=window}}else{shim.exports=exports}!function(exports){var vec2={};if(!GLMAT_EPSILON){var GLMAT_EPSILON=1e-6}vec2.create=function(){return new Float32Array(2)};vec2.clone=function(a){var out=new Float32Array(2);out[0]=a[0];out[1]=a[1];return out};vec2.fromValues=function(x,y){var out=new Float32Array(2);out[0]=x;out[1]=y;return out};vec2.copy=function(out,a){out[0]=a[0];out[1]=a[1];return out};vec2.set=function(out,x,y){out[0]=x;out[1]=y;return out};vec2.add=function(out,a,b){out[0]=a[0]+b[0];out[1]=a[1]+b[1];return out};vec2.sub=vec2.subtract=function(out,a,b){out[0]=a[0]-b[0];out[1]=a[1]-b[1];return out};vec2.mul=vec2.multiply=function(out,a,b){out[0]=a[0]*b[0];out[1]=a[1]*b[1];return out};vec2.div=vec2.divide=function(out,a,b){out[0]=a[0]/b[0];out[1]=a[1]/b[1];return out};vec2.min=function(out,a,b){out[0]=Math.min(a[0],b[0]);out[1]=Math.min(a[1],b[1]);return out};vec2.max=function(out,a,b){out[0]=Math.max(a[0],b[0]);out[1]=Math.max(a[1],b[1]);return out};vec2.scale=function(out,a,b){out[0]=a[0]*b;out[1]=a[1]*b;return out};vec2.dist=vec2.distance=function(a,b){var x=b[0]-a[0],y=b[1]-a[1];return Math.sqrt(x*x+y*y)};vec2.sqrDist=vec2.squaredDistance=function(a,b){var x=b[0]-a[0],y=b[1]-a[1];return x*x+y*y};vec2.len=vec2.length=function(a){var x=a[0],y=a[1];return Math.sqrt(x*x+y*y)};vec2.sqrLen=vec2.squaredLength=function(a){var x=a[0],y=a[1];return x*x+y*y};vec2.negate=function(out,a){out[0]=-a[0];out[1]=-a[1];return out};vec2.normalize=function(out,a){var x=a[0],y=a[1];var len=x*x+y*y;if(len>0){len=1/Math.sqrt(len);out[0]=a[0]*len;out[1]=a[1]*len}return out};vec2.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]};vec2.cross=function(out,a,b){var z=a[0]*b[1]-a[1]*b[0];out[0]=out[1]=0;out[2]=z;return out};vec2.lerp=function(out,a,b,t){var ax=a[0],ay=a[1];out[0]=ax+t*(b[0]-ax);out[1]=ay+t*(b[1]-ay);return out};vec2.transformMat2=function(out,a,m){var x=a[0],y=a[1];out[0]=x*m[0]+y*m[1];out[1]=x*m[2]+y*m[3];return out};vec2.forEach=function(){var vec=new Float32Array(2);return function(a,stride,offset,count,fn,arg){var i,l;if(!stride){stride=2}if(!offset){offset=0}if(count){l=Math.min(count*stride+offset,a.length)}else{l=a.length}for(i=offset;i0){len=1/Math.sqrt(len);out[0]=a[0]*len;out[1]=a[1]*len;out[2]=a[2]*len}return out};vec3.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]};vec3.cross=function(out,a,b){var ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2];out[0]=ay*bz-az*by;out[1]=az*bx-ax*bz;out[2]=ax*by-ay*bx;return out};vec3.lerp=function(out,a,b,t){var ax=a[0],ay=a[1],az=a[2];out[0]=ax+t*(b[0]-ax);out[1]=ay+t*(b[1]-ay);out[2]=az+t*(b[2]-az);return out};vec3.transformMat4=function(out,a,m){var x=a[0],y=a[1],z=a[2];out[0]=m[0]*x+m[4]*y+m[8]*z+m[12];out[1]=m[1]*x+m[5]*y+m[9]*z+m[13];out[2]=m[2]*x+m[6]*y+m[10]*z+m[14];return out};vec3.transformQuat=function(out,a,q){var x=a[0],y=a[1],z=a[2],qx=q[0],qy=q[1],qz=q[2],qw=q[3],ix=qw*x+qy*z-qz*y,iy=qw*y+qz*x-qx*z,iz=qw*z+qx*y-qy*x,iw=-qx*x-qy*y-qz*z;out[0]=ix*qw+iw*-qx+iy*-qz-iz*-qy;out[1]=iy*qw+iw*-qy+iz*-qx-ix*-qz;out[2]=iz*qw+iw*-qz+ix*-qy-iy*-qx;return out};vec3.forEach=function(){var vec=new Float32Array(3);return function(a,stride,offset,count,fn,arg){var i,l;if(!stride){stride=3}if(!offset){offset=0}if(count){l=Math.min(count*stride+offset,a.length)}else{l=a.length}for(i=offset;i0){len=1/Math.sqrt(len);out[0]=a[0]*len;out[1]=a[1]*len;out[2]=a[2]*len;out[3]=a[3]*len}return out};vec4.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]};vec4.lerp=function(out,a,b,t){var ax=a[0],ay=a[1],az=a[2],aw=a[3];out[0]=ax+t*(b[0]-ax);out[1]=ay+t*(b[1]-ay);out[2]=az+t*(b[2]-az);out[3]=aw+t*(b[3]-aw);return out};vec4.transformMat4=function(out,a,m){var x=a[0],y=a[1],z=a[2],w=a[3];out[0]=m[0]*x+m[4]*y+m[8]*z+m[12]*w;out[1]=m[1]*x+m[5]*y+m[9]*z+m[13]*w;out[2]=m[2]*x+m[6]*y+m[10]*z+m[14]*w;out[3]=m[3]*x+m[7]*y+m[11]*z+m[15]*w;return out};vec4.transformQuat=function(out,a,q){var x=a[0],y=a[1],z=a[2],qx=q[0],qy=q[1],qz=q[2],qw=q[3],ix=qw*x+qy*z-qz*y,iy=qw*y+qz*x-qx*z,iz=qw*z+qx*y-qy*x,iw=-qx*x-qy*y-qz*z;out[0]=ix*qw+iw*-qx+iy*-qz-iz*-qy;out[1]=iy*qw+iw*-qy+iz*-qx-ix*-qz;out[2]=iz*qw+iw*-qz+ix*-qy-iy*-qx;return out};vec4.forEach=function(){var vec=new Float32Array(4);return function(a,stride,offset,count,fn,arg){var i,l;if(!stride){stride=4}if(!offset){offset=0}if(count){l=Math.min(count*stride+offset,a.length)}else{l=a.length}for(i=offset;i=1){if(out!==a){out[0]=ax;out[1]=ay;out[2]=az;out[3]=aw}return out}halfTheta=Math.acos(cosHalfTheta);sinHalfTheta=Math.sqrt(1-cosHalfTheta*cosHalfTheta);if(Math.abs(sinHalfTheta)<.001){out[0]=ax*.5+bx*.5;out[1]=ay*.5+by*.5;out[2]=az*.5+bz*.5;out[3]=aw*.5+bw*.5;return out}ratioA=Math.sin((1-t)*halfTheta)/sinHalfTheta;ratioB=Math.sin(t*halfTheta)/sinHalfTheta;out[0]=ax*ratioA+bx*ratioB;out[1]=ay*ratioA+by*ratioB;out[2]=az*ratioA+bz*ratioB;out[3]=aw*ratioA+bw*ratioB;return out};quat.invert=function(out,a){var a0=a[0],a1=a[1],a2=a[2],a3=a[3],dot=a0*a0+a1*a1+a2*a2+a3*a3,invDot=dot?1/dot:0;out[0]=-a0*invDot;out[1]=-a1*invDot;out[2]=-a2*invDot;out[3]=a3*invDot;return out};quat.conjugate=function(out,a){out[0]=-a[0];out[1]=-a[1];out[2]=-a[2];out[3]=a[3];return out};quat.len=quat.length=vec4.length;quat.sqrLen=quat.squaredLength=vec4.squaredLength;quat.normalize=vec4.normalize;quat.str=function(a){return"quat("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+")"};if(typeof exports!=="undefined"){exports.quat=quat}}(shim.exports)}()},{}],22:[function(require,module,exports){!function(){var root=this;var previousUnderscore=root._;var breaker={};var ArrayProto=Array.prototype,ObjProto=Object.prototype,FuncProto=Function.prototype;var push=ArrayProto.push,slice=ArrayProto.slice,concat=ArrayProto.concat,toString=ObjProto.toString,hasOwnProperty=ObjProto.hasOwnProperty;var nativeForEach=ArrayProto.forEach,nativeMap=ArrayProto.map,nativeReduce=ArrayProto.reduce,nativeReduceRight=ArrayProto.reduceRight,nativeFilter=ArrayProto.filter,nativeEvery=ArrayProto.every,nativeSome=ArrayProto.some,nativeIndexOf=ArrayProto.indexOf,nativeLastIndexOf=ArrayProto.lastIndexOf,nativeIsArray=Array.isArray,nativeKeys=Object.keys,nativeBind=FuncProto.bind;var _=function(obj){if(obj instanceof _)return obj;if(!(this instanceof _))return new _(obj);this._wrapped=obj};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports){exports=module.exports=_}exports._=_}else{root._=_}_.VERSION="1.4.4"; +var each=_.each=_.forEach=function(obj,iterator,context){if(obj==null)return;if(nativeForEach&&obj.forEach===nativeForEach){obj.forEach(iterator,context)}else if(obj.length===+obj.length){for(var i=0,l=obj.length;i2;if(obj==null)obj=[];if(nativeReduce&&obj.reduce===nativeReduce){if(context)iterator=_.bind(iterator,context);return initial?obj.reduce(iterator,memo):obj.reduce(iterator)}each(obj,function(value,index,list){if(!initial){memo=value;initial=true}else{memo=iterator.call(context,memo,value,index,list)}});if(!initial)throw new TypeError(reduceError);return memo};_.reduceRight=_.foldr=function(obj,iterator,memo,context){var initial=arguments.length>2;if(obj==null)obj=[];if(nativeReduceRight&&obj.reduceRight===nativeReduceRight){if(context)iterator=_.bind(iterator,context);return initial?obj.reduceRight(iterator,memo):obj.reduceRight(iterator)}var length=obj.length;if(length!==+length){var keys=_.keys(obj);length=keys.length}each(obj,function(value,index,list){index=keys?keys[--length]:--length;if(!initial){memo=obj[index];initial=true}else{memo=iterator.call(context,memo,obj[index],index,list)}});if(!initial)throw new TypeError(reduceError);return memo};_.find=_.detect=function(obj,iterator,context){var result;any(obj,function(value,index,list){if(iterator.call(context,value,index,list)){result=value;return true}});return result};_.filter=_.select=function(obj,iterator,context){var results=[];if(obj==null)return results;if(nativeFilter&&obj.filter===nativeFilter)return obj.filter(iterator,context);each(obj,function(value,index,list){if(iterator.call(context,value,index,list))results[results.length]=value});return results};_.reject=function(obj,iterator,context){return _.filter(obj,function(value,index,list){return!iterator.call(context,value,index,list)},context)};_.every=_.all=function(obj,iterator,context){iterator||(iterator=_.identity);var result=true;if(obj==null)return result;if(nativeEvery&&obj.every===nativeEvery)return obj.every(iterator,context);each(obj,function(value,index,list){if(!(result=result&&iterator.call(context,value,index,list)))return breaker});return!!result};var any=_.some=_.any=function(obj,iterator,context){iterator||(iterator=_.identity);var result=false;if(obj==null)return result;if(nativeSome&&obj.some===nativeSome)return obj.some(iterator,context);each(obj,function(value,index,list){if(result||(result=iterator.call(context,value,index,list)))return breaker});return!!result};_.contains=_.include=function(obj,target){if(obj==null)return false;if(nativeIndexOf&&obj.indexOf===nativeIndexOf)return obj.indexOf(target)!=-1;return any(obj,function(value){return value===target})};_.invoke=function(obj,method){var args=slice.call(arguments,2);var isFunc=_.isFunction(method);return _.map(obj,function(value){return(isFunc?method:value[method]).apply(value,args)})};_.pluck=function(obj,key){return _.map(obj,function(value){return value[key]})};_.where=function(obj,attrs,first){if(_.isEmpty(attrs))return first?null:[];return _[first?"find":"filter"](obj,function(value){for(var key in attrs){if(attrs[key]!==value[key])return false}return true})};_.findWhere=function(obj,attrs){return _.where(obj,attrs,true)};_.max=function(obj,iterator,context){if(!iterator&&_.isArray(obj)&&obj[0]===+obj[0]&&obj.length<65535){return Math.max.apply(Math,obj)}if(!iterator&&_.isEmpty(obj))return-Infinity;var result={computed:-Infinity,value:-Infinity};each(obj,function(value,index,list){var computed=iterator?iterator.call(context,value,index,list):value;computed>=result.computed&&(result={value:value,computed:computed})});return result.value};_.min=function(obj,iterator,context){if(!iterator&&_.isArray(obj)&&obj[0]===+obj[0]&&obj.length<65535){return Math.min.apply(Math,obj)}if(!iterator&&_.isEmpty(obj))return Infinity;var result={computed:Infinity,value:Infinity};each(obj,function(value,index,list){var computed=iterator?iterator.call(context,value,index,list):value;computedb||a===void 0)return 1;if(a>>1;iterator.call(context,array[mid])=0})})};_.difference=function(array){var rest=concat.apply(ArrayProto,slice.call(arguments,1));return _.filter(array,function(value){return!_.contains(rest,value)})};_.zip=function(){var args=slice.call(arguments);var length=_.max(_.pluck(args,"length"));var results=new Array(length);for(var i=0;i=0;i--){args=[funcs[i].apply(this,args)]}return args[0]}};_.after=function(times,func){if(times<=0)return func();return function(){if(--times<1){return func.apply(this,arguments)}}};_.keys=nativeKeys||function(obj){if(obj!==Object(obj))throw new TypeError("Invalid object");var keys=[];for(var key in obj)if(_.has(obj,key))keys[keys.length]=key;return keys};_.values=function(obj){var values=[];for(var key in obj)if(_.has(obj,key))values.push(obj[key]);return values};_.pairs=function(obj){var pairs=[];for(var key in obj)if(_.has(obj,key))pairs.push([key,obj[key]]);return pairs};_.invert=function(obj){var result={};for(var key in obj)if(_.has(obj,key))result[obj[key]]=key;return result};_.functions=_.methods=function(obj){var names=[];for(var key in obj){if(_.isFunction(obj[key]))names.push(key)}return names.sort()};_.extend=function(obj){each(slice.call(arguments,1),function(source){if(source){for(var prop in source){obj[prop]=source[prop]}}});return obj};_.pick=function(obj){var copy={};var keys=concat.apply(ArrayProto,slice.call(arguments,1));each(keys,function(key){if(key in obj)copy[key]=obj[key]});return copy};_.omit=function(obj){var copy={};var keys=concat.apply(ArrayProto,slice.call(arguments,1));for(var key in obj){if(!_.contains(keys,key))copy[key]=obj[key]}return copy};_.defaults=function(obj){each(slice.call(arguments,1),function(source){if(source){for(var prop in source){if(obj[prop]==null)obj[prop]=source[prop]}}});return obj};_.clone=function(obj){if(!_.isObject(obj))return obj;return _.isArray(obj)?obj.slice():_.extend({},obj)};_.tap=function(obj,interceptor){interceptor(obj);return obj};var eq=function(a,b,aStack,bStack){if(a===b)return a!==0||1/a==1/b;if(a==null||b==null)return a===b;if(a instanceof _)a=a._wrapped;if(b instanceof _)b=b._wrapped;var className=toString.call(a);if(className!=toString.call(b))return false;switch(className){case"[object String]":return a==String(b);case"[object Number]":return a!=+a?b!=+b:a==0?1/a==1/b:a==+b;case"[object Date]":case"[object Boolean]":return+a==+b;case"[object RegExp]":return a.source==b.source&&a.global==b.global&&a.multiline==b.multiline&&a.ignoreCase==b.ignoreCase}if(typeof a!="object"||typeof b!="object")return false;var length=aStack.length;while(length--){if(aStack[length]==a)return bStack[length]==b}aStack.push(a);bStack.push(b);var size=0,result=true;if(className=="[object Array]"){size=a.length;result=size==b.length;if(result){while(size--){if(!(result=eq(a[size],b[size],aStack,bStack)))break}}}else{var aCtor=a.constructor,bCtor=b.constructor;if(aCtor!==bCtor&&!(_.isFunction(aCtor)&&aCtor instanceof aCtor&&_.isFunction(bCtor)&&bCtor instanceof bCtor)){return false}for(var key in a){if(_.has(a,key)){size++;if(!(result=_.has(b,key)&&eq(a[key],b[key],aStack,bStack)))break}}if(result){for(key in b){if(_.has(b,key)&&!size--)break}result=!size}}aStack.pop();bStack.pop();return result};_.isEqual=function(a,b){return eq(a,b,[],[])};_.isEmpty=function(obj){if(obj==null)return true;if(_.isArray(obj)||_.isString(obj))return obj.length===0;for(var key in obj)if(_.has(obj,key))return false;return true};_.isElement=function(obj){return!!(obj&&obj.nodeType===1)};_.isArray=nativeIsArray||function(obj){return toString.call(obj)=="[object Array]"};_.isObject=function(obj){return obj===Object(obj)};each(["Arguments","Function","String","Number","Date","RegExp"],function(name){_["is"+name]=function(obj){return toString.call(obj)=="[object "+name+"]"}});if(!_.isArguments(arguments)){_.isArguments=function(obj){return!!(obj&&_.has(obj,"callee"))}}if(typeof/./!=="function"){_.isFunction=function(obj){return typeof obj==="function"}}_.isFinite=function(obj){return isFinite(obj)&&!isNaN(parseFloat(obj))};_.isNaN=function(obj){return _.isNumber(obj)&&obj!=+obj};_.isBoolean=function(obj){return obj===true||obj===false||toString.call(obj)=="[object Boolean]"};_.isNull=function(obj){return obj===null};_.isUndefined=function(obj){return obj===void 0};_.has=function(obj,key){return hasOwnProperty.call(obj,key)};_.noConflict=function(){root._=previousUnderscore;return this};_.identity=function(value){return value};_.times=function(n,iterator,context){var accum=Array(n);for(var i=0;i":">",'"':""","'":"'","/":"/"}};entityMap.unescape=_.invert(entityMap.escape);var entityRegexes={escape:new RegExp("["+_.keys(entityMap.escape).join("")+"]","g"),unescape:new RegExp("("+_.keys(entityMap.unescape).join("|")+")","g")};_.each(["escape","unescape"],function(method){_[method]=function(string){if(string==null)return"";return(""+string).replace(entityRegexes[method],function(match){return entityMap[method][match]})}});_.result=function(object,property){if(object==null)return null;var value=object[property];return _.isFunction(value)?value.call(object):value};_.mixin=function(obj){each(_.functions(obj),function(name){var func=_[name]=obj[name];_.prototype[name]=function(){var args=[this._wrapped];push.apply(args,arguments);return result.call(this,func.apply(_,args))}})};var idCounter=0;_.uniqueId=function(prefix){var id=++idCounter+"";return prefix?prefix+id:id};_.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var noMatch=/(.)^/;var escapes={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"};var escaper=/\\|'|\r|\n|\t|\u2028|\u2029/g;_.template=function(text,data,settings){var render;settings=_.defaults({},settings,_.templateSettings);var matcher=new RegExp([(settings.escape||noMatch).source,(settings.interpolate||noMatch).source,(settings.evaluate||noMatch).source].join("|")+"|$","g");var index=0;var source="__p+='";text.replace(matcher,function(match,escape,interpolate,evaluate,offset){source+=text.slice(index,offset).replace(escaper,function(match){return"\\"+escapes[match]});if(escape){source+="'+\n((__t=("+escape+"))==null?'':_.escape(__t))+\n'"}if(interpolate){source+="'+\n((__t=("+interpolate+"))==null?'':__t)+\n'"}if(evaluate){source+="';\n"+evaluate+"\n__p+='"}index=offset+match.length;return match});source+="';\n";if(!settings.variable)source="with(obj||{}){\n"+source+"}\n";source="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+source+"return __p;\n";try{render=new Function(settings.variable||"obj","_",source)}catch(e){e.source=source;throw e}if(data)return render(data,_);var template=function(data){return render.call(this,data,_)};template.source="function("+(settings.variable||"obj")+"){\n"+source+"}";return template};_.chain=function(obj){return _(obj).chain()};var result=function(obj){return this._chain?_(obj).chain():obj};_.mixin(_);each(["pop","push","reverse","shift","sort","splice","unshift"],function(name){var method=ArrayProto[name];_.prototype[name]=function(){var obj=this._wrapped;method.apply(obj,arguments);if((name=="shift"||name=="splice")&&obj.length===0)delete obj[0];return result.call(this,obj)}});each(["concat","join","slice"],function(name){var method=ArrayProto[name];_.prototype[name]=function(){return result.call(this,method.apply(this._wrapped,arguments))}});_.extend(_.prototype,{chain:function(){this._chain=true;return this},value:function(){return this._wrapped}})}.call(this)},{}],23:[function(require,module,exports){var global=self;module.exports=function(){return global.WebSocket||global.MozWebSocket}},{}],24:[function(require,module,exports){if(typeof window!=="undefined"&&typeof window.requestAnimationFrame!=="function"){window.requestAnimationFrame=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(callback){setTimeout(callback,1e3/60)}}Leap=require("../lib/index")},{"../lib/index":10}]},{},[24]); \ No newline at end of file