diff --git a/assets/audio/fire.wav b/assets/audio/fire.wav new file mode 100644 index 0000000..8221026 Binary files /dev/null and b/assets/audio/fire.wav differ diff --git a/assets/audio/impact-0.wav b/assets/audio/impact-0.wav new file mode 100644 index 0000000..7888247 Binary files /dev/null and b/assets/audio/impact-0.wav differ diff --git a/assets/audio/impact-1.wav b/assets/audio/impact-1.wav new file mode 100644 index 0000000..00fa66c Binary files /dev/null and b/assets/audio/impact-1.wav differ diff --git a/assets/audio/impact-2.wav b/assets/audio/impact-2.wav new file mode 100644 index 0000000..cd88f6d Binary files /dev/null and b/assets/audio/impact-2.wav differ diff --git a/assets/audio/music.mp3 b/assets/audio/music.mp3 new file mode 100644 index 0000000..7ebee0a Binary files /dev/null and b/assets/audio/music.mp3 differ diff --git a/assets/audio/rumble.wav b/assets/audio/rumble.wav new file mode 100644 index 0000000..6461359 Binary files /dev/null and b/assets/audio/rumble.wav differ diff --git a/index.html b/index.html index e9f65f8..9b6988e 100644 --- a/index.html +++ b/index.html @@ -31,7 +31,9 @@ + +
@@ -44,10 +46,14 @@

Score: 000

+

+ Hits: 00 +

+ diff --git a/lib/color-scheme.min.js b/lib/color-scheme.min.js new file mode 100644 index 0000000..00229b0 --- /dev/null +++ b/lib/color-scheme.min.js @@ -0,0 +1 @@ +(function(){var t,e=[].slice;t=function(){function t(){var e,n;for(e=[],n=1;n<=4;n++)e.push(new t.mutablecolor(60));this.col=e,this._scheme="mono",this._distance=.5,this._web_safe=!1,this._add_complement=!1}var n,r,o,a,i,u;for(i=Array.isArray||function(t){return"[object Array]"==={}.toString.call(t)},t.SCHEMES={},a="mono monochromatic contrast triade tetrade analogic".split(/\s+/),r=0,o=a.length;r=u;n=0<=u?++o:--o)for(r=a=0;a<=3;r=++a)i[4*n+r]=this.col[n].get_hex(this._web_safe,r);return i},t.prototype.colorset=function(){var t,e;for(t=n(this.colors()),e=[];t.length>0;)e.push(t.splice(0,4));return e},t.prototype.from_hue=function(t){if(null==t)throw"from_hue needs an argument";return this.col[0].set_hue(t),this},t.prototype.rgb2ryb=function(){var t,n,r,o,a,u,s,h,l;return s=1<=arguments.length?e.call(arguments,0):[],null!=s[0]&&i(s[0])&&(s=s[0]),u=s[0],n=s[1],t=s[2],h=Math.min(u,n,t),u-=h,n-=h,t-=h,o=Math.max(u,n,t),l=Math.min(u,n),u-=l,n-=l,t>0&&n>0&&(t/=2,n/=2),l+=n,t+=n,a=Math.max(u,l,t),a>0&&(r=o/a,u*=r,l*=r,t*=r),u+=h,l+=h,t+=h,[Math.floor(u),Math.floor(l),Math.floor(t)]},t.prototype.rgb2hsv=function(){var t,n,r,o,a,u,s,h,l,c;return h=1<=arguments.length?e.call(arguments,0):[],null!=h[0]&&i(h[0])&&(h=h[0]),s=h[0],r=h[1],t=h[2],s/=255,r/=255,t/=255,u=Math.min.apply(Math,[s,r,t]),a=Math.max.apply(Math,[s,r,t]),n=a-u,c=a,n>0?(l=n/a,o=s===a?(r-t)/n:r===a?2+(t-s)/n:4+(s-r)/n,o*=60,o%=360,[o,l,c]):[0,0,c]},t.prototype.rgbToHsv=function(){var t,n,r,o,a,u,s,h,l,c;if(h=1<=arguments.length?e.call(arguments,0):[],null!=h[0]&&i(h[0])&&(h=h[0]),s=h[0],r=h[1],t=h[2],s/=255,r/=255,t/=255,a=Math.max(s,r,t),u=Math.min(s,r,t),o=void 0,l=void 0,c=a,n=a-u,l=0===a?0:n/a,a===u)o=0;else{switch(a){case s:o=(r-t)/n+(r= 0";if(t>1)throw"distance("+t+") - argument must be <= 1";return this._distance=t,this},t.prototype.scheme=function(e){if(null==e)return this._scheme;if(null==t.SCHEMES[e])throw"'"+e+"' isn't a valid scheme name";return this._scheme=e,this},t.prototype.variation=function(e){if(null==e)throw"variation needs an argument";if(null==t.PRESETS[e])throw"'$v' isn't a valid variation name";return this._set_variant_preset(t.PRESETS[e]),this},t.prototype._set_variant_preset=function(t){var e,n,r;for(r=[],e=n=0;n<=3;e=++n)r.push(this.col[e].set_variant_preset(t));return r},n=function(t){var e,r,o;if(null==t||"object"!=typeof t)return t;if(t instanceof Date)return new Date(t.getTime());if(t instanceof RegExp)return e="",null!=t.global&&(e+="g"),null!=t.ignoreCase&&(e+="i"),null!=t.multiline&&(e+="m"),null!=t.sticky&&(e+="y"),new RegExp(t.source,e);o=new t.constructor;for(r in t)o[r]=n(t[r]);return o},t.mutablecolor=function(){function e(e){if(null==e)throw"No hue specified";this.saturation=[],this.value=[],this.base_red=0,this.base_green=0,this.base_blue=0,this.base_saturation=0,this.base_value=0,this.set_hue(e),this.set_variant_preset(t.PRESETS.default)}return e.prototype.hue=0,e.prototype.saturation=[],e.prototype.value=[],e.prototype.base_red=0,e.prototype.base_green=0,e.prototype.base_saturation=0,e.prototype.base_value=0,e.prototype.get_hue=function(){return this.hue},e.prototype.set_hue=function(e){var n,r,o,a,i,u,s,h,l,c;n=function(t,e,n){return t+Math.round((e-t)*n)},this.hue=Math.round(e%360),i=this.hue%15+(this.hue-Math.floor(this.hue)),c=i/15,u=this.hue-Math.floor(i),s=(u+15)%360,360===u&&(u=0),360===s&&(s=0),o=t.COLOR_WHEEL[u],a=t.COLOR_WHEEL[s],h={red:0,green:1,blue:2,value:3};for(r in h)l=h[r],this["base_"+r]=n(o[l],a[l],c);return this.base_saturation=n(100,100,c)/100,this.base_value/=100},e.prototype.rotate=function(t){var e;return e=(this.hue+t)%360,this.set_hue(e)},e.prototype.get_saturation=function(t){var e,n;return n=this.saturation[t],e=n<0?-n*this.base_saturation:n,e>1&&(e=1),e<0&&(e=0),e},e.prototype.get_value=function(t){var e,n;return n=this.value[t],e=n<0?-n*this.base_value:n,e>1&&(e=1),e<0&&(e=0),e},e.prototype.set_variant=function(t,e,n){return this.saturation[t]=e,this.value[t]=n},e.prototype.set_variant_preset=function(t){var e,n,r;for(r=[],e=n=0;n<=3;e=++n)r.push(this.set_variant(e,t[2*e],t[2*e+1]));return r},e.prototype.get_hex=function(t,e){var n,r,o,a,i,u,s,h,l,c,f,p,_,m,d,v;for(l=Math.max.apply(Math,function(){var t,e,n,o;for(n=["red","green","blue"],o=[],e=0,t=n.length;e0?v/l:0,p=[],f=["red","green","blue"],h=0,u=f.length;h=0&&e<=1){if(o._volume=e,o._muted)return o;o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e,n.ctx.currentTime);for(var t=0;t=0;o--)e._howls[o].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,_()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,"")]},_setup:function(){var e=this||n;if(e.state=e.ctx?e.ctx.state||"suspended":"suspended",e._autoSuspend(),!e.usingWebAudio)if("undefined"!=typeof Audio)try{var o=new Audio;void 0===o.oncanplaythrough&&(e._canPlayEvent="canplay")}catch(n){e.noAudio=!0}else e.noAudio=!0;try{var o=new Audio;o.muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,o=null;try{o="undefined"!=typeof Audio?new Audio:null}catch(n){return e}if(!o||"function"!=typeof o.canPlayType)return e;var t=o.canPlayType("audio/mpeg;").replace(/^no$/,""),r=e._navigator&&e._navigator.userAgent.match(/OPR\/([0-6].)/g),a=r&&parseInt(r[0].split("/")[1],10)<33;return e._codecs={mp3:!(a||!t&&!o.canPlayType("audio/mp3;").replace(/^no$/,"")),mpeg:!!t,opus:!!o.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!o.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),aac:!!o.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!o.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(o.canPlayType("audio/x-m4a;")||o.canPlayType("audio/m4a;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(o.canPlayType("audio/x-mp4;")||o.canPlayType("audio/mp4;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,""),webm:!!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,""),dolby:!!o.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(o.canPlayType("audio/x-flac;")||o.canPlayType("audio/flac;")).replace(/^no$/,"")},e},_unlockAudio:function(){var e=this||n,o=/iPhone|iPad|iPod|Android|BlackBerry|BB10|Silk|Mobi|Chrome|Safari/i.test(e._navigator&&e._navigator.userAgent);if(!e._audioUnlocked&&e.ctx&&o){e._audioUnlocked=!1,e.autoUnlock=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var t=function(n){for(var o=0;o0?i._seek:t._sprite[e][0]/1e3),s=Math.max(0,(t._sprite[e][0]+t._sprite[e][1])/1e3-_),l=1e3*s/Math.abs(i._rate),c=t._sprite[e][0]/1e3,f=(t._sprite[e][0]+t._sprite[e][1])/1e3,p=!(!i._loop&&!t._sprite[e][2]);i._sprite=e,i._ended=!1;var m=function(){i._paused=!1,i._seek=_,i._start=c,i._stop=f,i._loop=p};if(_>=f)return void t._ended(i);var v=i._node;if(t._webAudio){var h=function(){t._playLock=!1,m(),t._refreshBuffer(i);var e=i._muted||t._muted?0:i._volume;v.gain.setValueAtTime(e,n.ctx.currentTime),i._playStart=n.ctx.currentTime,void 0===v.bufferSource.start?i._loop?v.bufferSource.noteGrainOn(0,_,86400):v.bufferSource.noteGrainOn(0,_,s):i._loop?v.bufferSource.start(0,_,86400):v.bufferSource.start(0,_,s),l!==1/0&&(t._endTimers[i._id]=setTimeout(t._ended.bind(t,i),l)),o||setTimeout(function(){t._emit("play",i._id),t._loadQueue()},0)};"running"===n.state?h():(t._playLock=!0,t.once("resume",h),t._clearTimer(i._id))}else{var y=function(){v.currentTime=_,v.muted=i._muted||t._muted||n._muted||v.muted,v.volume=i._volume*n.volume(),v.playbackRate=i._rate;try{var r=v.play();if(r&&"undefined"!=typeof Promise&&(r instanceof Promise||"function"==typeof r.then)?(t._playLock=!0,m(),r.then(function(){t._playLock=!1,v._unlocked=!0,o||(t._emit("play",i._id),t._loadQueue())}).catch(function(){t._playLock=!1,t._emit("playerror",i._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction."),i._ended=!0,i._paused=!0})):o||(t._playLock=!1,m(),t._emit("play",i._id),t._loadQueue()),v.playbackRate=i._rate,v.paused)return void t._emit("playerror",i._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.");"__default"!==e||i._loop?t._endTimers[i._id]=setTimeout(t._ended.bind(t,i),l):(t._endTimers[i._id]=function(){t._ended(i),v.removeEventListener("ended",t._endTimers[i._id],!1)},v.addEventListener("ended",t._endTimers[i._id],!1))}catch(e){t._emit("playerror",i._id,e)}},g=window&&window.ejecta||!v.readyState&&n._navigator.isCocoonJS;if(v.readyState>=3||g)y();else{t._playLock=!0;var b=function(){y(),v.removeEventListener(n._canPlayEvent,b,!1)};v.addEventListener(n._canPlayEvent,b,!1),t._clearTimer(i._id)}}return i._id},pause:function(e){var n=this;if("loaded"!==n._state||n._playLock)return n._queue.push({event:"pause",action:function(){n.pause(e)}}),n;for(var o=n._getSoundIds(e),t=0;t=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else r.length>=2&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var a;if(!(void 0!==e&&e>=0&&e<=1))return a=o?t._soundById(o):t._sounds[0],a?a._volume:0;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"volume",action:function(){t.volume.apply(t,r)}}),t;void 0===o&&(t._volume=e),o=t._getSoundIds(o);for(var u=0;u0?t/_:t),l=Date.now();e._fadeTo=o,e._interval=setInterval(function(){var r=(Date.now()-l)/t;l=Date.now(),i+=d*r,i=Math.max(0,i),i=Math.min(1,i),i=Math.round(100*i)/100,u._webAudio?e._volume=i:u.volume(i,e._id,!0),a&&(u._volume=i),(on&&i>=o)&&(clearInterval(e._interval),e._interval=null,e._fadeTo=null,u.volume(o,e._id),u._emit("fade",e._id))},s)},_stopFade:function(e){var o=this,t=o._soundById(e);return t&&t._interval&&(o._webAudio&&t._node.gain.cancelScheduledValues(n.ctx.currentTime),clearInterval(t._interval),t._interval=null,o.volume(t._fadeTo,e),t._fadeTo=null,o._emit("fade",e)),o},loop:function(){var e,n,o,t=this,r=arguments;if(0===r.length)return t._loop;if(1===r.length){if("boolean"!=typeof r[0])return!!(o=t._soundById(parseInt(r[0],10)))&&o._loop;e=r[0],t._loop=e}else 2===r.length&&(e=r[0],n=parseInt(r[1],10));for(var a=t._getSoundIds(n),u=0;u=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var i;if("number"!=typeof e)return i=t._soundById(o),i?i._rate:t._rate;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"rate",action:function(){t.rate.apply(t,r)}}),t;void 0===o&&(t._rate=e),o=t._getSoundIds(o);for(var d=0;d=0?o=parseInt(r[0],10):t._sounds.length&&(o=t._sounds[0]._id,e=parseFloat(r[0]))}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));if(void 0===o)return t;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"seek",action:function(){t.seek.apply(t,r)}}),t;var i=t._soundById(o);if(i){if(!("number"==typeof e&&e>=0)){if(t._webAudio){var d=t.playing(o)?n.ctx.currentTime-i._playStart:0,_=i._rateSeek?i._rateSeek-i._seek:0;return i._seek+(_+d*Math.abs(i._rate))}return i._node.currentTime}var s=t.playing(o);s&&t.pause(o,!0),i._seek=e,i._ended=!1,t._clearTimer(o),t._webAudio||!i._node||isNaN(i._node.duration)||(i._node.currentTime=e);var l=function(){t._emit("seek",o),s&&t.play(o,!0)};if(s&&!t._webAudio){var c=function(){t._playLock?setTimeout(c,0):l()};setTimeout(c,0)}else l()}return t},playing:function(e){var n=this;if("number"==typeof e){var o=n._soundById(e);return!!o&&!o._paused}for(var t=0;t=0&&n._howls.splice(a,1);var u=!0;for(t=0;t=0){u=!1;break}return r&&u&&delete r[e._src],n.noAudio=!1,e._state="unloaded",e._sounds=[],e=null,null},on:function(e,n,o,t){var r=this,a=r["_on"+e];return"function"==typeof n&&a.push(t?{id:o,fn:n,once:t}:{id:o,fn:n}),r},off:function(e,n,o){var t=this,r=t["_on"+e],a=0;if("number"==typeof n&&(o=n,n=null),n||o)for(a=0;a=0;a--)r[a].id&&r[a].id!==n&&"load"!==e||(setTimeout(function(e){e.call(this,n,o)}.bind(t,r[a].fn),0),r[a].once&&t.off(e,r[a].fn,r[a].id));return t._loadQueue(e),t},_loadQueue:function(e){var n=this;if(n._queue.length>0){var o=n._queue[0];o.event===e&&(n._queue.shift(),n._loadQueue()),e||o.action()}return n},_ended:function(e){var o=this,t=e._sprite;if(!o._webAudio&&e._node&&!e._node.paused&&!e._node.ended&&e._node.currentTime=0;t--){if(o<=n)return;e._sounds[t]._ended&&(e._webAudio&&e._sounds[t]._node&&e._sounds[t]._node.disconnect(0),e._sounds.splice(t,1),o--)}}},_getSoundIds:function(e){var n=this;if(void 0===e){for(var o=[],t=0;t=0;if(n._scratchBuffer&&e.bufferSource&&(e.bufferSource.onended=null,e.bufferSource.disconnect(0),t))try{e.bufferSource.buffer=n._scratchBuffer}catch(e){}return e.bufferSource=null,o}};var t=function(e){this._parent=e,this.init()};t.prototype={init:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._rate=o._rate,e._seek=0,e._paused=!0,e._ended=!0,e._sprite="__default",e._id=++n._counter,o._sounds.push(e),e.create(),e},create:function(){var e=this,o=e._parent,t=n._muted||e._muted||e._parent._muted?0:e._volume;return o._webAudio?(e._node=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),e._node.gain.setValueAtTime(t,n.ctx.currentTime),e._node.paused=!0,e._node.connect(n.masterGain)):(e._node=n._obtainHtml5Audio(),e._errorFn=e._errorListener.bind(e),e._node.addEventListener("error",e._errorFn,!1),e._loadFn=e._loadListener.bind(e),e._node.addEventListener(n._canPlayEvent,e._loadFn,!1),e._node.src=o._src,e._node.preload="auto",e._node.volume=t*n.volume(),e._node.load()),e},reset:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._rate=o._rate,e._seek=0,e._rateSeek=0,e._paused=!0,e._ended=!0,e._sprite="__default",e._id=++n._counter,e},_errorListener:function(){var e=this;e._parent._emit("loaderror",e._id,e._node.error?e._node.error.code:0),e._node.removeEventListener("error",e._errorFn,!1)},_loadListener:function(){var e=this,o=e._parent;o._duration=Math.ceil(10*e._node.duration)/10,0===Object.keys(o._sprite).length&&(o._sprite={__default:[0,1e3*o._duration]}),"loaded"!==o._state&&(o._state="loaded",o._emit("load"),o._loadQueue()),e._node.removeEventListener(n._canPlayEvent,e._loadFn,!1)}};var r={},a=function(e){var n=e._src;if(r[n])return e._duration=r[n].duration,void d(e);if(/^data:[^;]+;base64,/.test(n)){for(var o=atob(n.split(",")[1]),t=new Uint8Array(o.length),a=0;a0?(r[o._src]=e,d(o,e)):t()};"undefined"!=typeof Promise&&1===n.ctx.decodeAudioData.length?n.ctx.decodeAudioData(e).then(a).catch(t):n.ctx.decodeAudioData(e,a,t)},d=function(e,n){n&&!e._duration&&(e._duration=n.duration),0===Object.keys(e._sprite).length&&(e._sprite={__default:[0,1e3*e._duration]}),"loaded"!==e._state&&(e._state="loaded",e._emit("load"),e._loadQueue())},_=function(){if(n.usingWebAudio){try{"undefined"!=typeof AudioContext?n.ctx=new AudioContext:"undefined"!=typeof webkitAudioContext?n.ctx=new webkitAudioContext:n.usingWebAudio=!1}catch(e){n.usingWebAudio=!1}n.ctx||(n.usingWebAudio=!1);var e=/iP(hone|od|ad)/.test(n._navigator&&n._navigator.platform),o=n._navigator&&n._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/),t=o?parseInt(o[1],10):null;if(e&&t&&t<9){var r=/safari/.test(n._navigator&&n._navigator.userAgent.toLowerCase());(n._navigator&&n._navigator.standalone&&!r||n._navigator&&!n._navigator.standalone&&!r)&&(n.usingWebAudio=!1)}n.usingWebAudio&&(n.masterGain=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),n.masterGain.gain.setValueAtTime(n._muted?0:1,n.ctx.currentTime),n.masterGain.connect(n.ctx.destination)),n._setup()}};"function"==typeof define&&define.amd&&define([],function(){return{Howler:n,Howl:o}}),"undefined"!=typeof exports&&(exports.Howler=n,exports.Howl=o),"undefined"!=typeof window?(window.HowlerGlobal=e,window.Howler=n,window.Howl=o,window.Sound=t):"undefined"!=typeof global&&(global.HowlerGlobal=e,global.Howler=n,global.Howl=o,global.Sound=t)}(); +/*! Spatial Plugin */ +!function(){"use strict";HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){var n=this;if(!n.ctx||!n.ctx.listener)return n;for(var t=n._howls.length-1;t>=0;t--)n._howls[t].stereo(e);return n},HowlerGlobal.prototype.pos=function(e,n,t){var r=this;return r.ctx&&r.ctx.listener?(n="number"!=typeof n?r._pos[1]:n,t="number"!=typeof t?r._pos[2]:t,"number"!=typeof e?r._pos:(r._pos=[e,n,t],void 0!==r.ctx.listener.positionX?(r.ctx.listener.positionX.setTargetAtTime(r._pos[0],Howler.ctx.currentTime,.1),r.ctx.listener.positionY.setTargetAtTime(r._pos[1],Howler.ctx.currentTime,.1),r.ctx.listener.positionZ.setTargetAtTime(r._pos[2],Howler.ctx.currentTime,.1)):r.ctx.listener.setPosition(r._pos[0],r._pos[1],r._pos[2]),r)):r},HowlerGlobal.prototype.orientation=function(e,n,t,r,o,i){var a=this;if(!a.ctx||!a.ctx.listener)return a;var s=a._orientation;return n="number"!=typeof n?s[1]:n,t="number"!=typeof t?s[2]:t,r="number"!=typeof r?s[3]:r,o="number"!=typeof o?s[4]:o,i="number"!=typeof i?s[5]:i,"number"!=typeof e?s:(a._orientation=[e,n,t,r,o,i],void 0!==a.ctx.listener.forwardX?(a.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),a.ctx.listener.forwardY.setTargetAtTime(n,Howler.ctx.currentTime,.1),a.ctx.listener.forwardZ.setTargetAtTime(t,Howler.ctx.currentTime,.1),a.ctx.listener.upX.setTargetAtTime(e,Howler.ctx.currentTime,.1),a.ctx.listener.upY.setTargetAtTime(n,Howler.ctx.currentTime,.1),a.ctx.listener.upZ.setTargetAtTime(t,Howler.ctx.currentTime,.1)):a.ctx.listener.setOrientation(e,n,t,r,o,i),a)},Howl.prototype.init=function(e){return function(n){var t=this;return t._orientation=n.orientation||[1,0,0],t._stereo=n.stereo||null,t._pos=n.pos||null,t._pannerAttr={coneInnerAngle:void 0!==n.coneInnerAngle?n.coneInnerAngle:360,coneOuterAngle:void 0!==n.coneOuterAngle?n.coneOuterAngle:360,coneOuterGain:void 0!==n.coneOuterGain?n.coneOuterGain:0,distanceModel:void 0!==n.distanceModel?n.distanceModel:"inverse",maxDistance:void 0!==n.maxDistance?n.maxDistance:1e4,panningModel:void 0!==n.panningModel?n.panningModel:"HRTF",refDistance:void 0!==n.refDistance?n.refDistance:1,rolloffFactor:void 0!==n.rolloffFactor?n.rolloffFactor:1},t._onstereo=n.onstereo?[{fn:n.onstereo}]:[],t._onpos=n.onpos?[{fn:n.onpos}]:[],t._onorientation=n.onorientation?[{fn:n.onorientation}]:[],e.call(this,n)}}(Howl.prototype.init),Howl.prototype.stereo=function(n,t){var r=this;if(!r._webAudio)return r;if("loaded"!==r._state)return r._queue.push({event:"stereo",action:function(){r.stereo(n,t)}}),r;var o=void 0===Howler.ctx.createStereoPanner?"spatial":"stereo";if(void 0===t){if("number"!=typeof n)return r._stereo;r._stereo=n,r._pos=[n,0,0]}for(var i=r._getSoundIds(t),a=0;a new Howl({ + src: [`assets/audio/impact-${i}.wav`], + volume: 0.5 + })), +} + +audio.fire.play(); +audio.music.play(); diff --git a/src/ball.js b/src/ball.js index d6ae3e2..e405694 100644 --- a/src/ball.js +++ b/src/ball.js @@ -1,10 +1,5 @@ const RADIUS = 10; const SEGMENTS = 40; -const material = new THREE.MeshLambertMaterial({ - color: 0xFFFFFF, - emissive: 0xFF0000, - emissiveIntensity: 0.4, -}); const ballPhysics = new PHYSICS.SphereModule({ mass: 2, friction: 0.5, @@ -20,7 +15,11 @@ const ball = new WHS.Sphere({ z: -30, y: 10 }, - material, + material: new THREE.MeshLambertMaterial({ + color: 0xFFFFFF, + emissive: 0xFF0000, + emissiveIntensity: 0.4, + }), modules: [ new WHS.TextureModule({ @@ -30,21 +29,16 @@ const ball = new WHS.Sphere({ ], }); -const fireLight = new WHS.PointLight({ - color: 0xff0000, - intensity: 5, -}); - ball.physics = ballPhysics; -ball.fireLight = fireLight; ball.addTo(app); -ball.add(fireLight); camera.native.target = ball.native; ball.checkLife = () => { - if (ball.position.x > ground.geometry.parameters.width / 2 || ball.position.x < -ground.geometry.parameters.width / 2) { + if (ball.position.x > ground.geometry.parameters.width / 2 + || ball.position.x < -ground.geometry.parameters.width / 2 + || ball.position.z > -ground.SIZE) { location.reload(); } } @@ -79,66 +73,37 @@ ball.checkLife = () => { color: 0xffffff, }); - new THREE.Geometry(); - var smokeCount = 2000, - smokes = new THREE.Geometry(), - smokeMaterial = new THREE.PointsMaterial({ - size: 1.5, - transparent: true, - color: 0x666666, - opacity: 0.5, - }); - const radius = ball.params.geometry.radius; const start = ball.position; for (var p = 0; p < particleCount; p++) { - - // create a particle with random - // position values, -250 -> 250 var pX = start.x + THREE.Math.randFloatSpread(radius), pY = start.y + THREE.Math.randFloatSpread(radius), pZ = start.z + THREE.Math.randFloatSpread(radius), particle = new THREE.Vector3(pX, pY, pZ) - particle.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT; - //particle.color.offsetHSL(Math.random(), 0, Math.random()); + particle.lifetime = Math.random() < 0.5 ? 0 : ball.params.geometry.radius + THREE.Math.randFloat(0.5, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT; - // add it to the geometry particles.vertices.push(particle); particles.colors.push(new THREE.Color(1, 0, 0)); } - particles.colorsNeedUpdate = true; - for (var i = 0; i < spriteCount; i++) { var pX = start.x + THREE.Math.randFloatSpread(radius), pY = start.y + THREE.Math.randFloatSpread(radius), pZ = start.z + THREE.Math.randFloatSpread(radius), particle = new THREE.Vector3(pX, pY, pZ) - particle.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT; + particle.lifetime = Math.random() < 0.5 ? 0 : ball.params.geometry.radius + THREE.Math.randFloat(0.5, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT; sprites.vertices.push(particle); } - for (var i = 0; i < smokeCount; i++) { - var pX = start.x + THREE.Math.randFloatSpread(radius), - pY = start.y + THREE.Math.randFloat(radius), - pZ = start.z + THREE.Math.randFloatSpread(radius), - particle = new THREE.Vector3(pX, pY, pZ); - - particle.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT * 1.5; - - smokes.vertices.push(particle); - } // create the particle system var points = WHS.MeshComponent.from(new THREE.Points(particles, pMaterial)); var spritesPoints = WHS.MeshComponent.from(new THREE.Points(sprites, spriteMaterial)); - var smokePoints = WHS.MeshComponent.from(new THREE.Points(smokes, smokeMaterial)); - smokePoints.isSmoke = true; - ball.fire = [points, spritesPoints, smokePoints]; + ball.fire = [points, spritesPoints]; ball.fire.forEach(fire => { fire.addTo(app); }) @@ -154,31 +119,39 @@ ball.checkLife = () => { ); fire.geometry.vertices.forEach((v, i) => { - v.y += THREE.Math.randFloat(0, SPREAD_SPEED / 4); - v.x += THREE.Math.randFloatSpread(SPREAD_SPEED) + velocity.x * -0.02; - v.z += THREE.Math.randFloatSpread(SPREAD_SPEED) + velocity.z * -0.01; + let x = v.x + THREE.Math.randFloatSpread(SPREAD_SPEED) + velocity.x * -0.02; + let y = v.y + THREE.Math.randFloat(0, SPREAD_SPEED / 4); + let z = v.z + THREE.Math.randFloatSpread(SPREAD_SPEED) + velocity.z * -0.01; - if (fire.material.vertexColors === THREE.VertexColors) { + v.set(x, y, z); + + if (!v.isSmoke && fire.material.vertexColors === THREE.VertexColors) { fire.geometry.colors[i].offsetHSL(7e-4, 0, 0); } if (v.y >= v.lifetime) { - if (fire.isSmoke) { - v.y = FIRE_HEIGHT/3 + THREE.Math.randFloat(0, FIRE_HEIGHT_RANDOMNESS); + if (!v.isSmoke && fire.material.vertexColors === THREE.VertexColors) { + v.isSmoke = true; + fire.geometry.colors[i].setHex(0x444444) + v.lifetime += FIRE_HEIGHT * 0.5; } else { - v.y = Math.min(radius, radius * velocity.z / -50); - } + y = Math.min(radius, radius * velocity.z / -50); - v.x = 0; - v.z = -ball.params.geometry.radius * 3; + x = 0; + z = -ball.params.geometry.radius * 3; - v.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT * (fire.isSmoke ? 1.5 : 1); + v.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT; - if (fire.material.vertexColors === THREE.VertexColors) { - const r = THREE.Math.randFloat(0.8, 1); - const g = THREE.Math.randFloat(0, 0.2); - const b = THREE.Math.randFloat(0, 0.2); - fire.geometry.colors[i].setRGB(r, g, b); + v.set(x, y, z); + + v.isSmoke = false; + + if (fire.material.vertexColors === THREE.VertexColors) { + const r = THREE.Math.randFloat(0.8, 1); + const g = THREE.Math.randFloat(0, 0.2); + const b = THREE.Math.randFloat(0, 0.2); + fire.geometry.colors[i].setRGB(r, g, b); + } } } }); @@ -189,5 +162,19 @@ ball.checkLife = () => { fire.geometry.verticesNeedUpdate = true; }); }); + + const fireLight = new WHS.PointLight({ + color: 0xff0000, + intensity: 5, + }); + ball.fireLight = fireLight; + ball.add(fireLight); }()); +let hits = 0; +ball.on('collision', (o, v, r, cn) => { + if (o.uuid === ground.native.uuid) return; + rand(audio.impacts).play(); + hits++; + GUI.setHits(hits); +}); diff --git a/src/controls.js b/src/controls.js index 735e95a..a1e5ac9 100644 --- a/src/controls.js +++ b/src/controls.js @@ -1,14 +1,18 @@ -const DFORCE = 3e3; +const DFORCE = 6e3; const AFORCE = 500; const VFORCE = 1e4; Mousetrap.bind('left', () => { if (!ball.started) return; + const v = ball.physics.getLinearVelocity(); + ball.physics.setLinearVelocity({ x: Math.min(0, v.x), y: v.y, z: v.z }); ball.physics.applyCentralForce({ x: -DFORCE, y: 0, z: 0 }); }); Mousetrap.bind('right', () => { if (!ball.started) return; + const v = ball.physics.getLinearVelocity(); + ball.physics.setLinearVelocity({ x: Math.max(0, v.x), y: v.y, z: v.z }); ball.physics.applyCentralForce({ x: DFORCE, y: 0, z: 0 }); }); @@ -19,20 +23,20 @@ Mousetrap.bind('up', () => { //ball.methods.updateVelocity(); }); -Mousetrap.bind('space', () => { - if (!ball.started) return; - if (ball.physics.data.touches.length) { - ball.physics.applyCentralForce({ x: 0, y: VFORCE, z: 0 }); - } - //ball.speed = Math.min(config.MAX_SPEED, Math.max(config.FINAL_SPEED, ball.speed + config.SPEED_INCREASE)); - //ball.methods.updateVelocity(); -}); +//Mousetrap.bind('space', () => { + //if (!ball.started) return; + //if (ball.physics.data.touches.length) { + //ball.physics.applyCentralForce({ x: 0, y: VFORCE, z: 0 }); + //} + ////ball.speed = Math.min(config.MAX_SPEED, Math.max(config.FINAL_SPEED, ball.speed + config.SPEED_INCREASE)); + ////ball.methods.updateVelocity(); +//}); -Mousetrap.bind('down', () => { - if (!ball.started) return; - ball.physics.applyCentralForce({ x: 0, y: 0, z: AFORCE * 3 }); - //ball.speed = Math.min(config.MAX_SPEED, Math.max(config.FINAL_SPEED, ball.speed - config.SPEED_INCREASE)); - //ball.methods.updateVelocity(); -}); +//Mousetrap.bind('down', () => { + //if (!ball.started) return; + //ball.physics.applyCentralForce({ x: 0, y: 0, z: AFORCE * 3 }); + ////ball.speed = Math.min(config.MAX_SPEED, Math.max(config.FINAL_SPEED, ball.speed - config.SPEED_INCREASE)); + ////ball.methods.updateVelocity(); +//}); diff --git a/src/gui.js b/src/gui.js index 1f3196f..3cc4e21 100644 --- a/src/gui.js +++ b/src/gui.js @@ -3,6 +3,7 @@ const GUI = { score: document.getElementById('score'), speed: document.getElementById('speed'), time: document.getElementById('time'), + hits: document.getElementById('hits'), }, setScore(s) { GUI.elements.score.textContent = Math.floor(s).toString().padStart(3, '0'); @@ -13,6 +14,9 @@ const GUI = { setStartingTime() { GUI.startingTime = moment(); }, + setHits(s) { + GUI.elements.hits.textContent = Math.floor(s).toString().padStart(2, '0'); + }, tickTime() { const now = moment(); const diff = moment.duration(now.diff(GUI.startingTime)); diff --git a/src/levels/0-basic.js b/src/levels/0-basic.js index 476ea81..c73c153 100644 --- a/src/levels/0-basic.js +++ b/src/levels/0-basic.js @@ -1,36 +1,127 @@ function level0() { - function jumpBoard(x, z) { - const cylinder = new WHS.Cylinder({ + const step = rad(10); + const tan = Math.tan(step); + const BOX_SIZE = 100; + + function add({ x, y, z } = {}, { width, depth, height } = {}, rotation = {}) { + y = y || (tan * z) + BOX_SIZE/2; + width = width || BOX_SIZE; + height = height || BOX_SIZE; + depth = depth || BOX_SIZE; + + rotation.x = rotation.x || -step; + const box = new WHS.Box({ geometry: { - radiusTop: 50, - radiusBottom: 1, - radiusSegments: 3, - heightSegments: 1, - height: 2, + width, + depth, + height, }, material: new THREE.MeshPhongMaterial({ - color: 0xffff00, + color: 0xffffff, }), - position: [x, 0, z], - rotation: [Math.PI, rad(-35), 0], + position: [x, y, z], + + rotation, modules: [ - new PHYSICS.CylinderModule({ + new PHYSICS.BoxModule({ mass: 0, + friction: 1, + restitution: 0, }) ] }); - //cylinder.addTo(app); - ground.add(cylinder); + box.addTo(app); + return box; } - //jumpBoard(5, -50); - //jumpBoard(5, -100); - // - //ring({ x: 0, y: 10, z: -150 }); + const SPACE_UNIT = 250; + + const patterns = [{ + items: [3,4,5], + randoms: { + startX() { + return Math.random() > 0.5 ? 200 : -200; + }, + }, + x(i, props) { + return props.startX + i * 50 * (props.startX === 200 ? -1 : 1); + }, + z(i) { + return i * -BOX_SIZE; + }, + }, { + items: [3,4,6], + props: { + side: 150, + }, + rot: { + y(i, props) { + if (i % 3 == 0) { + return THREE.Math.randFloatSpread(Math.PI); + } + return 0; + } + }, + size(i, props) { + return THREE.Math.randInt(BOX_SIZE * 0.8, BOX_SIZE * 1.2); + }, + x(i, props) { + if (i % 3 == 0) { + return 0; + } else { + return i % 3 == 1 ? props.side : -props.side; + } + }, + z(i) { + if (i % 3 == 0) { + return i * -SPACE_UNIT; + } else { + return i % 3 == 1 ? i * -SPACE_UNIT : (i - 1) * -SPACE_UNIT; + } + } + }]; + + + const applyPattern = (sz, { items, x, z, rot, props, randoms, space, size } = {}) => { + props = props || {}; + randoms = randoms || {}; + space = space || SPACE_UNIT; + rot = rot || {}; + const count = rand(items); + + const rs = {}; + Object.entries(randoms).forEach(([key, value]) => { + rs[key] = value(); + }); + + Object.assign(props, rs); + + let zz; + + for (let i = 0; i < count; i++) { + zz = sz + z(i, props); + const rotation = {}; + Object.entries(rot).forEach(([key, value]) => { + rotation[key] = value(i, props); + }); + let boxSize = BOX_SIZE; + if (size) { + boxSize = size(i, props); + } + add({ x: x(i, props), z: zz }, { width: boxSize, height: boxSize, depth: boxSize }, rotation); + } + + return zz - space; + } + + let sz = -300; + while (-sz < ground.SIZE) { + const pattern = rand(patterns); + sz = applyPattern(sz, pattern); + } } -level0(); diff --git a/src/scenes.js b/src/scenes.js index ca68b92..1d47f9f 100644 --- a/src/scenes.js +++ b/src/scenes.js @@ -40,9 +40,13 @@ const entrance = () => { GUI.setStartingTime(); const diff = camera.position.y - ball.position.y; ball.started = true; + level0(); + + audio.rumble.play(); app.physics.addEventListener('update', function() { - camera.position.set(camera.position.x, ball.position.y + diff, ball.position.z + 130); + //camera.position.set(camera.position.x, ball.position.y + diff, ball.position.z + 130); + camera.position.set(ball.position.x, ball.position.y + diff, ball.position.z + 130); camera.native.lookAt(ball.position); directionalLight.position.set(directionalLight.position.x, directionalLight.position.y, ball.position.z - 300); GUI.setScore(-ball.position.z / 100); diff --git a/src/utils.js b/src/utils.js index cf60bd2..c7f225b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,2 +1,4 @@ const rad = (deg) => deg * Math.PI / 180; +const rand = (items) => items[Math.floor(Math.random() * items.length)]; + diff --git a/src/world.js b/src/world.js index 336d68a..25784dc 100644 --- a/src/world.js +++ b/src/world.js @@ -34,7 +34,7 @@ let ground; (function groundinit() { const WIDTH = 500; const SIZE = 1e5; - const mesh = new WHS.Plane({ + ground = new WHS.Plane({ geometry: { width: WIDTH, height: SIZE, @@ -51,12 +51,14 @@ let ground; }), new PHYSICS.PlaneModule({ mass: 0, + restitution: 0, }), ], material: new THREE.MeshPhongMaterial({ color: 0xffffff }) }); - ground = mesh; + ground.SIZE = SIZE; + ground.addTo(app); }());