From 14bf47f11a1560a1b33df46ca7f29407d08bbfe7 Mon Sep 17 00:00:00 2001 From: Nicky Case Date: Tue, 27 Jun 2017 13:49:58 -0400 Subject: [PATCH] hhhhhh --- TODO.md | 3 +- assets/all_c.png | Bin 2955 -> 0 bytes assets/all_d.png | Bin 3935 -> 0 bytes assets/grim.png | Bin 3395 -> 0 bytes assets/pavlov.png | Bin 5752 -> 0 bytes assets/prober.png | Bin 3905 -> 0 bytes assets/random.png | Bin 5761 -> 0 bytes assets/tf2t.png | Bin 5340 -> 0 bytes assets/tft.png | Bin 4099 -> 0 bytes assets/tournament_peep.json | 75 + assets/tournament_peep.png | Bin 0 -> 32094 bytes css/paper@2x.png | Bin 13793 -> 0 bytes index.html | 6 +- js/core/Loader.js | 113 ++ js/lib/helpers.js | 66 +- js/lib/howler.js | 2740 +++++++++++++++++++++++++++++++++++ js/sims/PD.js | 4 +- js/sims/Tournament.js | 41 +- 18 files changed, 3032 insertions(+), 16 deletions(-) delete mode 100644 assets/all_c.png delete mode 100644 assets/all_d.png delete mode 100644 assets/grim.png delete mode 100644 assets/pavlov.png delete mode 100644 assets/prober.png delete mode 100644 assets/random.png delete mode 100644 assets/tf2t.png delete mode 100644 assets/tft.png create mode 100644 assets/tournament_peep.json create mode 100644 assets/tournament_peep.png delete mode 100644 css/paper@2x.png create mode 100644 js/core/Loader.js create mode 100755 js/lib/howler.js diff --git a/TODO.md b/TODO.md index ffa1855..001e76a 100644 --- a/TODO.md +++ b/TODO.md @@ -12,4 +12,5 @@ MINOR SHTUFF - Word box class less annoying - Refactoring, ugh -- Draw: Pavlov, TF2T, Random \ No newline at end of file +- Draw: Pavlov, TF2T, Random +- a better handwritten font, with REAL bold & italics??? \ No newline at end of file diff --git a/assets/all_c.png b/assets/all_c.png deleted file mode 100644 index b23161fd3c04cc71a6fbfb107d52f817b0870b35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2955 zcmV;63v~2}P)+LT2000Y8Nkl zKWrSw6^Fk$Mgj>55UEBI0Y`+WMxg;Qu-rs8%oI*33keV-jm327M2ozrG*cS-1ExzV zpHjstl5TM}VZ?|LBSwrEF=E7s5hF&77%^hRh@n9heF3Sg%HK%NK3^cz3!GTL?>o&_;R_Fz7Ve#-4T-IPXx%4)6f@()qG2YAmRa)pyR{@QlAIyvwRl zyeZto12_o03H%f-`hmo6%+q1L$|~)}0_BRFWsH{b;jd@FQ?vy>EAjez z=r|92p1l+4=d`zy_Sj)BPPiGo{#(FxvQX2(lWYPiLmTp1zWeDBs4TG#0f+mJ9Y!|? zM}e<^e-MoX32R~GC$)gGEGL7WD?2;DztPn$O(Z%i$B4RDQ`kL*uh6~vH`Wr@!#~nn zV2z7laG>M-zo+z8#Udm5o50_K_qfP$T4vF0t54@V zte#nFL5Icu`Ds4_`f9@tpv5{CydU&bu6y;g(GF$-KkGl?)D;9XZcD-VcP7&7px-OWJA~j)({%LtWgUXmzFk&oI?K~d480baDN*7#RH4r z1TcYabH{`C>AufAW>3rwbo217L)nT|smoUP{6-cAL%>j+Q)q$GOpTg8`w;jmE*82b zby>`lW7yq^G@v)qP#E2UnXJke_klaO2$?xibI*;j&9vp=4fcBNQ^ETb{+;Y3?xKZ! z5&Nlzx~6`aw&-3*I@%kz(b3md@ap<7lR(4jH~t)*;x;I31NYEk+Jx+yu5=|b7M2xx z513Et>ZLCK#5TV=XySGA5cosPdEsJr#5sv<6YFtq&mfBzau?mnn9wT#=3V{7)X7Cb zuwm7B@?8dBJb<^^Ym@s?Oj=Wx4WtrKuF4U{Xc$kPKnpl5TteTonTv8ooU$C#Szz2M zr1w*mR6P^Guds{gXob!K%CcO-<|n>OalTxUOrR}s+;C2@AS?1wQW5SJs4Tz8uvOiD zj$*%mQx0SwP6A3@E?fP*VXL|(?6qemSTJrSQNW-vHCx}XR^5JPvA2a1pLCgQfwsnU z*sE?oZ(GmAPH)5t82Ee(#*-HuZfck~haRU#S&aKyyam=Qz3y9-n~h%irBSdn6Y(?rrH=_7f=}{+4p15+mAWSW!}z!_%?7R_szTlq-z6T1)dm>E(VLs zBg9qVXuY=wAomY%7>@0&Op0KfSP!N+qonPDAERf&w!4m4EavUnfuo^;Q?oj_+%xUp_K zVeW;6M(&K&aLVu&(MG)Nh|V-_lV97Uwm_qR>W2DS>SDe?8jb=V(z{Hdiu5*DOl}tt zteY{CE<-hI&lxW98gy(fjKzu8rwmwk{YmK~?Gu`DnX5(tgVZjw>VEvH!NXp=Vsm8T zdf|rg=p*CN;pZ>r!=~+?y0HsbqhWL)O~apIXM@bmlU2Z=-bbr(xE^CaVXsw1*ODq^13f=tUo+QI*VGTw6zLuh+>J5o z+vp`!gG`cm!WNzMt5ux^R5#TF#4;{?fnI<1Y1+$|#AA{y4`4CNHUO#C$~kRLF^7)+ z4oa1dTNf9SVU=b`>cxi6yBbZQ#e9qMV}aq))`ui7|IZ;F5!~@?O@AU8RI|VGE9oa7^D~?#|V|M)t*xv?Dp*w)r zgV#1%#IUFA&IH)T&GqPJoMOy z@^?2$DRd<;T40#=MS0fVif%E!E1A~C1M7yc~Jw5q#|wIHVDX9+uP_{5)pro}n-&20QJjh=U@ zh+^BovbKe)a36ZUo8z|bXd>)9+Z}vgCZp;RL z!~<=?cVo`ml0!XHu7JMt3B$mwX{QavWEo@P{ozQ5+sgN|Tf9G5eLz)MCuTKd59w$8 z7J%H3yojTE0b$+sxgJuNRqM%VDp`tFekW2C6>Z5^t_Awe?BAyHd68lT{I$bpY)R}c zd`soCa#i=jEnm-ftBPs`jM)vt3##Dq@hM=on_c&I{c6hh8V_8ARP9-tG55z#1X!2e z8_Rdipv{5T^tPgTnTOa*3)li$D7NU(E+eTZ diff --git a/assets/all_d.png b/assets/all_d.png deleted file mode 100644 index 9443377d70f7ef4e5a7f728c1bf2d568b4fe28c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3935 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 diff --git a/assets/grim.png b/assets/grim.png deleted file mode 100644 index 063dba981153f3b5550bb1ae8fa960661c590f51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3395 zcmV-J4ZQM+P)+LT2000dNNklr3^WxD&vD;UA5VT#D&*RLPP*tV5HtdkBpePtjaBDQv{?xzj-+uuw z@B(py#61B3SXn|5K$TKd28K;S(7JRLU&S;nCB#bL$`Xo{q6VNUxvW75YL~8JBbr(1 zAvOZP`2v@FJv0E6+^(e*Z2*-IuHkOj^U_5u1m3xY+k{|F=RK67Z5SvgZ6z8}KX7>w z-|3PE0ED1miF=|D=?Yv~!WBx<6uq8F1Cx37_rss~*HDUbl09}U9!$TDf*^=aVjnWM4&17K^Ld#f6Nzq(F1A}FoEaQh zxN{4$grEt|fsq>l{_uNX$o5el9s=e+8Ig`j6O@v&7rO3&ZsY;a_owE{5*EJw68XW` z?%cvGfEF~!1K8N>)BNZ4dir~4SdfbF$`TeRm6JCJN>O{dkNM?AGzdZ48mj^**ssl` z#pLyI_6+c!2SB%beB3ac_lpZc5nfqBvDbr1NH~+7y#S1jx?lJ2AGrrg>-~@L=Mbi) z4WS5AiW-l+Od5D;jQyli-X8k;v>JH;kRRs`S7e7;l#q#V$v(i_vwnC8{PRF81HTAJ%%p)cdHI2%i(U^^AbwAc)_-a5iTw351@;pKyqJSwK&A(-+XoK2 zoU0zOxkzzt$~hL6m81hHfrjDq-96q4Z!$6nERs^R zvv9&qgxBq3-7eGj5`t3PCY_W(>mX^^$KyIkawE<$TPQSgxcUPrg=rs)ON^(^xL*@B zTnRJ`H0`HxTw=^yfpNo?z)M%L!8?uP662&nDXiJ|E)OCuF-{tk2<-Ko1SaJ)j$4^l zBJhK2_zZ9!CJ7Pa^2!pf#Px8U%!ImqK;}RV13Y`!LOH@|9D_1}?|+2P?PGgSqc!ca z85WC45`5*xbi2_XCOngl()dg|EdqIYEeY8Nt8w`TwOsnC6zcY@fbCtNv+pffz=3bFxP5>gPrG2*JF|+e)^7SAv*}7J=`5h;5!(=N7Gt2qmAddxEwI^US)f zZD2P-67!m>%*qlL5E6mfq3&J}Og2MO&M|53b?v z@*+&wwExY={J2F};3YOKFXB_{&x#vqyhY#zUXv|auo1X_z?=(FWhMyVc98U8Ub>1; zf_R`O0<&q;f0z3OmT(@`F@8A5XO=dP7To}M}mOd}_H#Y*5-}N`4!$XU# z-6O*68LB>DX49y=_aOpHmh+r1Wf*8!8B)*DcP{8;Vf9Js{|;KGw9Ly2D``DYWi4T+ACzc3WWQE}l%Z*qb8-n@sf5B(LKjAq166g@)R0=3xV1Ea=ZwZk~ zF}-lIz<%3o@)ihcsGXUkr1jKz^c#tP#-GMbU@2et!Lc91o%;iP|o|uUnz^jgEX!O{s13%S(o`fHY2Dylj zb#Lui52W8Cj}BTO0+Oe10)?vA+Xs(sn-RHH7ZXWP)m3%86L=5bofz^4vC{+|Nb0pI z=Ez0$0v=C6CAx-%6G~Q}?`39zw<6WS{h`}tB#Ly#6w2fs_vRLQBD{}=P;}2Vv~CqUQU##c zVjnyYU1u^C56T46HCzV-xp*%xM57=FjZ^`6tqB<1tdI&_!-Cr_ltq}{!>`~KwwyH4 zM+&F#Y0l*mNze`Y%?StaJG50YGUb{IXf4W3>5aaq46XF%v6UhGfT=aguxWTDf z?L&`1BhQ?p|8F4TlUPik!7jw$~|y} zwyKyw5`RB}lK?S+A*RJ98ayW}MU{TfFXWM}K&RZF2D{e{`RmRxf&vcs3yMpih;0~} zC-7bi_;HSTe)~V|hTc7bK)222u}0X>{Q|IAW#e|_tNeSU`THP06;i;q)(Y&lfd_NW z5aN@sS^7m()(p>e-`fVZKW7UWmiy6dSiIy#^%{`&JLM~OmVW3wubd;H2ti+R%0 zx;>x3C=QUQ2z<8g{~nyyFMaR{6nUQyG$!NrNe-9P@8t)&x+`yA znKPlm9p4STt|lHl;>U&Es+`0GX3zkq!34HWVN9fBdfuMIjkwQa8@!s4XB*L(VNqd6 zAXN&jQRIrWD6Jt5msD8TYcb~r4_Wt84>wDs#vMH^`(U>XJgo9xqiCqqjmR5uvuyQs z#|zIkPRA_h@3A&0RC~CrkrH|nvOPQUV zkKPy9FKyjvx|jd^AdkJ>Bj_5gtJsPFSp1<-WrT)JX2+Drf(PM~Ja!8op!aaobtT#{ zc7=&|Kdk9DxOA}2Ov}9%^O&pkNoZpT6_sK_H~9XFaJq^cmPq?cT^%kSk=l>tX3H%7 z!rlg@V>0oSWj~0~1nbrjeBT(autES01k~6yBm_!aAAx>JJzc{Bw=^Pt)X5B7j$&^J zHn5(wq)c|mmBJzq2tG66_&zvX1m6CYnR>i5iZDQ7S_fN+T*Svgi>w{NitwtfpWx_a zRu$eyx6L;HevrM}K8iJW+d3_q7>vC05DBO!mMQ}L#$N@b3hEs__F6}O^D@20=NRcf z#QRn2(GsYGLH$sqD-Mzz6J8YB_{8ZWkXIlSB2FKHL|oGm22M7C*)qRnNhdms=wuU^ zD)9Y|yh_uMaIy&mqDxj6;N%k+GXf*fY7G@Vcq_1{*S^#bf?I*Ss_rPni&uW;(rF_| z1S!H!hpMQVO_0czSsRv^5bhorRe5ZTeH`Mkg}3Vd5|f5Y%U>K+^n)vQ@=3s z%vB~@lML}3%34n;aw;kPT{ zd~sILNPWgh^ZxCv@0;^ z%>HgW_P9v61g~ Z@jobn6Be{b%kBUG002ovPDHLkV1oPTUkv~N diff --git a/assets/pavlov.png b/assets/pavlov.png deleted file mode 100644 index 0a00e6e0de80b8a564394b6055a9f827fed419dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5752 zcmY*-bzIcX+V+=NKpGL2E(yt{W2vPDmIi47rE@9il8_eZ6hykaB}GbLX$g^#ZdO|0 z;djn?&-*;{`OM5c*If5?%{~9kL}{uk5#Unc0sugu{9Io9Vb*-;u{c-{Jj8}}x&|HwYH;Xl7bhMIOP5zxJl;--2NnQGctamTCo2yN25%=vXLqQ# zB-6hb(1-XR7{bKxFN%kQB$I)fCWD-dn-zl)k01{(lN2rk1A~N{r8QJrUhzNa4=YI~ zTMrKe6aw+`^5XFl;Bj%Yf$)imi9vYzA^iN@4-9U1A7>8>Z*FJzr~elDe>(D3?yueK z5FU0e&J6$PTD)@c^pIp?`p4+M?ceA0u(SUEPR{QCDeIv?$Ui#}J|14kf3+V{CH_I7 z8g6!056=JSOYuqki}`=B|M*Bi{xSbwhxvD<|3V*1mBN*P{P)_VaN)gdh5+znR9Rj| z*BkA?G$7&0fM<}TAKM|G=nBlA27!b5Om=Oh=2hgd(Wkmt)oA}WT!oeclckQ79}3oz zxb=sEt`c<%lX2a0QdHPmbPJQ1*xgKcZoyYM8j@Y>EVroB z->LYppyRrgNXz^)QXtX zD!Zh5QBuwHa$@WyoVJoFsSx5|VVu;NksJp>Pt9&h=1R0NYOhT5$>=lN+py$Y?MSr1 zS^Gr8M}Iq5vq2gZJtJ>)1y!)F&1S2wX}qaL8YIg=kv*jR^K?%qGPsR1*v){xkYa#1 zt~Y;FI8s|=?bMc9bHjP zgv9^21fN8!$n!=XTGYra+jK4qXJFV0uMR8n5(U3BVAi^5&i!>#fO_Oli!rhOduP(5 z>1Z)4unRO^hUvNelGtG*xXQ8h)IT7vY9f_c16!vadnoua>3LfC`3D8lV&vb>)pF*hO>ZoTbPufMMSm zVr6(k87=dtC{dr}sOOpkLb)a?4@?+qbCV^%2BJ#U#5=1~#Kz!efQ3D)(@;Z}xb35I zHuv!;%pvET2r*Qcy1=ExvPa6|t58Vrwj~3x+-EI$v_Ol`%Dev8*y3YgMwYsKA2fM2 zpq4}NmM)0GP@oq#5rfH)uE(1JnD`PGRR2nf<&~tP;z`ZV(X=4n*96>|0(?nM$7^~} zghxV^iJGJH|11{H@HmeJh~442J_`dZO|3;(*jelke8xl@oT}* zsifUBto10R&GQNSL4Su0~vba>}j zy0+@xVR|2+UclWYw$DD^*jyKMxQd;7A;E>#x8#>QjEei-+$6}4n2IafdAe{x(s0t{ zdqdEv^(Iy+lGK;u9o-9K^rFSGy#pI5zQtLJB(tfMN5eV`IA*wOGGW%HiGmv(zYtvZ z*eB;nlebCw7#lg9f$G{-?!tD=tlPGsc~14*Q2m^M({P_D+a3)KVs1wUUq_4c9=srC zDrMr^vo$V_!gGY^g|GC)dQ7DK{B-V(S$?(KJcz3gw)jg-an$AGr&cgCgu4!GDVw#N z%T(f3`wH735r}_Ysj;pUCa(H+t58u;kZ2jZXT~ zDcwyC`b)k!XX6uC`boISEM+n(vyYiJ+JpPf>^?o~Sd5M&xOpzlN? z+c6Be7xvkrT^31$-+{KoR2=BH&&qjz)tdt_;N3c}lpR7|N`fmThkdhh+{@ zK;#@dF;9(2Tg`ZV7WX!AhUT*mII+Ql;e_U|V0FfALSLoU}_q|dy4847-{igJdQ_u&=FM~7ROYmHk*T{a+lM~sDsf8pjdcR7kpX! z%1S^-whWXXF1W(``m)QgLQ3Eg9H#zK8Ljh~kV8*iB1V3)M@dgUyNS??b|-FT;n(?O zZcfzVvw~=vZ&dRyeoFOo{K*7&uTrQvwW!q7?Q1*^4D#WX32GOSQ5`>dlqN2wYqw&E zdBd_06k;oO14TZ@BJM=meN$y6nc;0YDsD{BSGO~Jj*=V)-cr>IfJGwZW)huOLJBjR zY4XAa`xko632Hrm7(H7*p;}IFeV;ZMJu4;10twz?L*{cX9ewtcI6XZ=d{J;2uiG9B ztuM7W;2Jc~Gq~ZUdTH(M|9QHc`=4^_ooXEyh?b6nFm~2k0 z5Y^A_9CREQnlcJd1%xRbagb+EtX+!^9)dTrG>%~MZkp>b+^84+TJI^KUee_%D z(b)pd&-0gBz?c{Lx8#^6}F>Y4X3dj z^}LHO#xC%zj~X*!^j(FiWL4K7F3khkosRIe@0nxHg{<5A^_l`*c0;TraPAU3SH+vI zgyEMTsupCuJE;aGtuft%5Cr3{0+{A+YOk2$N1DV?Kd_Ezh4(NVt73eJ(R#MNc=CgI zu*hg{FZduAGd1`0Y>l2H7HT-<0+3w%Ftk?6z4(ED-VuXoIv$v?$)4p*! z6*v?+0loDd8LXE$*!x`e+xo)dnNlrGc{}Wbu(Lr*=yE}uz3<<<{%?O-f_T4YdPO(Z zemn#2KKP-&i7VN;NIL{*_P&fMIF#*~-ifQV=L$?Eo8d#GqYD>y%Pq<_Yeka#f%z!+ z1}quL#IcU7o&ljTmB?&akAgXJ46hYvFkOkfpZ&tFPo9;D4)C!{R95@~mA8>kwH##k zJ0LBC1|cFcGrz+zGH_eZ+9prof{N|^=4N#Pl+PHP&K>+7%{Efy77(-bn%F_5mEKiG~AAYfb&8vNsh>@o&`9NA{E(5OjR! zT>5eTH9qH86WjM$7oGBGuw-WOoX-8Df#fMP%}&dHG#u#*<7LjV=9Bn%jE+JSetnMr zAg2FIKHyNydkkyLvgq(G6=p@b!yyhB>bUZ1_L=}fN&RFp z2!@V8wkTG_f??Q1Qc1RZcCrXWrKTPrhojcSAoy#QjT6l)_QZ(J} zQ@0FZ_ntT+_3}sUW9n;r%mkKxwMkywwjD6dyOg(it`vr!5l{UH2`RdhFrGe|2Ny^i z0aLj}O_(H_WfBxLfC(SfmLq3x-bj_F+?ffh!oZaDr6h!FlWjbVIM?=3pT6Q%f1Fyp ze-9$vNQqP#I@<2XdhCrRHqBT_1K`~V^T1If;zzOUq`q`l#lIxTi&DhgEw}=TQ%~F# zU>Iv7Hj`{F8S1KA>P`BBRQ3(CxyChb4~fwOHl|{rzh{-Cz(w}G)5!~33a;if%zawX%v-SPfFo8yO5U}?C2sw6Ima4o5M24_|3XoWI~ z5;&-a2wbNR(-)#59aWXw+_UdLX{K`s8v!1(y zo9Cs+`${N2ORVqsDH7#N(jk9dmGLjKra6|xIfDsx8lM(l8oY}s5`h#cjI8rGM>&@p z$fVxVLP~APSa_NxPk;JzpMZGHR(Z!sT6P;;Mg!izBOwh~&SaJ1nRHIzgyIwN?7FKPnDU{iY;6gd<`FlViMVEepMKCGhb$g3!6#a&9HIXK*6F86B`bQq z=*J7D=UKR9XNsSE*)B2)rVZziilU54qhfzCwQJShOOYaT zcPew6!F$`5!Lj*;aDN>lc>gXfpO%rBs>G$B*nDW3dd zyvxOGc1y)ss4u-OY_a9lY9$Y7;p3KDkDOGnZ$?)kX9_2>5*mt~05HSwVNjF;pET)t zG{NT(=TUc+yn3ng+1QKv+Zl}FXcx1OPgWNy1{M=3Ep`*hFOyQ2r3XGy zk3T;?^iLbsMUut!r!p$Ox-cdXJtfnvuF}-3G4DKV+Wjr&Z3MXTgxN5~JMI)LOM9c( z3I8sY1w9Yv9u9h|&v9S8K=P*yuU+#+#0*R)obi{sB3vvq)sC4Bj*-h4si;*+l-zYa z>0i7AU(l6d?GwuQ;fR|*Vay%8^V#(Jhf>B`V?@eOn`PZ%b-59s1G0SIl$WVtPyd1! z)$OqGEvE7Qr085G(+&&qN1JHt1S=su-_!x~fD{bnPr;dZDGACzZGmfEIWK117C zSBr&1?CRYU{tVv&}ju2l9w192y5-{@KQj- zajl5@wQ_;%A5vTb!+~i64nc61&Lv|d4h&5&y;O`@tM%vHsKmk>a(?p`&}yeG!1#3; zy{61hlyb|gRlA_OR9z80?{VsN+r+G5KS!E_2=<^xyu#}W+wjyCxLOO=MNMl{ESa}$ z^cyo#6KZ$2t!tS}!F{~Gp4aGRne(^aCpXiU{!fI0zeVq3ZzGU$N=PGxv4*wPLO=pO@$G{O zo_TsabY0G7fn5%}0_F2)l7xtf#nv@L&y@iEnUPA=i4YEhCq)-O1%@RjHB4y69fPzy zuHEppr`bGEMm!W3kGyYAIds%o(iaYf!MI`aA&O}H9Q57jP+F@Gg8-bnMsdC&xUPZf z85ARx2Wo5yoDLhb7Yi+n`M8k{AgV~MS+4F1;~bmTbV$%k3^j%B__EfhKYjoJRV|I8 z-X-~DU{mE=&P(x*tLP1LK{__7+*X8z>WN|G3Kg$3Pk7AWY?)dL9c({c!BvpZXzsef za72e5-dTF!8TP$a$ihpm_8biIPKYVwvaS1|Qs1a)1W3l@ep|-&%Okfw8!?S5Oeakv z?>4Uq8wUZN3@>KleIyKg>9@m+(=K=)UUt2ig|`Ew_fnC+Wl_m!!F3NPx@Y3}vp1CD z(Ft}mFG^G$dhIcWB4tU4RL+#ROw_n4u@r^S%hk;_sjw?`X4aui!0tV6LVe(ypa{AB z*495>$Zgl<6wb;=eiqv?YhlUyjyt031S{PXUY->jdtG3j8Xb_Juhe{x=5PN8$IZv5 diff --git a/assets/prober.png b/assets/prober.png deleted file mode 100644 index 4e1f41b3f1cf7beaec7cdec2be4a4df44b275ca4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3905 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 P00000NkvXXu0mjf^b=?{ diff --git a/assets/random.png b/assets/random.png deleted file mode 100644 index 40911c66c2de7f3e108134423f14f7f5233c9140..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5761 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 ve4bab4HoSnb-PB|hrXl|VwE*Yu diff --git a/assets/tf2t.png b/assets/tf2t.png deleted file mode 100644 index 2d0ccf51d5bbc15f30482d7c58355c9420068f0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5340 zcmY*-byyV6+V;|20#X9|BLq=8R$>8>?hsr7ft8S5*rk^4P^6_{=|*Znq(xe~Ly&F| z>0A(a@tpIW?|tXGX6BiD?z!)I=DOyOnJ`^#6$(;jQUCxzp{A;+f7k2Y)ktE(yLM++ z0DITrxag}W04jzaY~RJNU@ssjh?b_5r2|3$YUS|8TEGM0c*g<&WIUwqLWDI63iLqO zBVD9Cz#RW#NZrMMVL=YyzbGg>Fb70S7x>)4*%~M=ASNKhAxjDb0%e@7Y^3xRmH)H+ zZUpAAMWGy}1O?sQ-38o51st5;3JOa~N(u^z2#SdC-!b@IJdr4<2S3t<^WP%>Pe;+( z#nKt(h=MsFfq!+OZya1vU=EJIM*l7U-X{uX^Z%WYF8@jEE|krDiB{=YW!?@a%N-lZx_DkJ#cW0NJ-Z0C6e0MH7n zDL#AQfwTMC+tGB=^LFU|T2d zel69FJJsiz)!zH_P44cKexhUG&8E%6j74zFzRzZr;;jz-KR~{4R*|D$!?)MD8&S;%L{4s^%bO*)mh?)y0`VXgwo^kw%~&-V1t`w#|KS7y6A9?PjOp_ThL- zc-)-kd_v<%OW3h0#`}QpI_JfBkA0X?z&J7Z5P27+*gA2x{^uX=J)6 zG0txxs4Ky~CBf#Q_V`6uM`m`^6#FH--8R=qft=QQHcYxc+iFllUt?BjVy-q4&G004 z)MW;SmbwzKW>QVOh;VxtFB&{>71W1$>E6rCYe*G4|2@!aw2t7BqQ(_B`A-qJdaYh= zgCPq&F#6j~78|wo(u33Hi|cYK80QqtIPp?q8vEDyNva9_#fh(uOgUk>wW;zhJV_bM zMehFB`$&na-OEtZur9ZfjWP931l#Q=xr*gC*cw^zm3iQ|!` zPNd?F^BXPKCDdmDS&^ef{E#W`E3wDI!#W9Z(1+d8W78}hXrVLSnXnh&;bd!ygqk4% zDl@xoYbCtE!padUBRe4azYO5WmN4$HPvb1{p9pXwlYqlQ|DAL0;AHBP{Q;g8HM zXb<%SWywV+LAp)7cZOo%i<3Cx<3uGQIiGO9R9>f{jU?R->{y`GXer+T+JqKobZWA< z*#yq>Dfwq^ef(stCUd8;kXDx?v-&r9B>h)f4S9PB)oeT#tYGedvg?>e>-H_iF2J&O zT>?86N0GHnJ}~v;-fMnOtn5f%f!(7JG^mm6qyeeGuUWfR+kmY(+q7FEr)VNbWfIJM z)3Eq*+`sLp=I2_DjT%ed83K{w37|D9lJ=Gcac-6%{T}#{^Xl56tX>%zcVp;va6fdh zW&k9H4egW|uU+v-ZB%tH?YNVr%}Ib_zL1c4L7wifeD9<+YyL3mZU~y>X|ZWBy{Fvm zPe~0Q0xCb*b!Dt_CQ5t)Kd z=2guv4_n^}wN)RO12Qv=zT?R58s3^K~n!|yE za#A^?w>a|9acWSEnOwu|Quy##oZ*k&>|KMRZL+Ht4V{V`uI9M~ZcoX79@nB;Y8<)2 zPFNmr@3--v|9CzgZhn3)cg!G$7|ctSo*E5Z@Jo_C`>wOSuz2Hg8AApd0fFX}SG&#P zp`eT_ih`l9%Ki;sLY);x`ckX>XPtjFIC$TSiPZxL+0jhF!D3EF{=5wrV;nc%3O4Q5 z!w*;QwL%5{>_x~y=qNK+%Qd#EhIYU{p-#s=NVNKw5e7_i%y+c$CvK3|;=DHq;kmBY zXWA5dV|^Nhs@Mgi&U#9}a7hc`_@JN+)>u2y`O4<&Ul>}1Yh1+jt71Nk%vV>8!1?c! z`e;_B{bnAjk>O;2-JnoKo`#2eO>4}?;%*=AxoK~R-nMJ67N-Nfi<3y*aO73t@fk_? z9^dk@s-iu)TC7$=HivsTn$OO+t0qB`X4tPsYnW}T&%vM7UygkDt(r`DLYjR3;mk@y zqTG{)taK#A8d)o@FvnD~W>&4ch;_n%4{?2Oi_A~(o0kn@Mk7^61nak@#fFE*5SYE( z(giI2e2Y_Bhk%TUlo1UpzXuuR9;G+*nLjpm))MsXJ`S%cxfA#Suj>84)ye47lb0+G z=lS>tFD`oyuTOZcT2#mihev++mu6*}-Qb+opvYc65D(xcF4203T(zSK=<&HOmo{wR zbJIBjIC*@Vnaip~T#jGE8V?VUmz$4~g`thIN^fZ!3%$(fAmN|K<2RYc3|Us~^w_uJ zikG^MENg80+t{mr9?|)RsVrygU;Df|0Cp=xA^Fxz0}pG83DNRs8$iaXsXb#gu{7c3s`%X9$?oBwSF~l zJs)00gH2vB-YU#oyrO}&!B*BxLSmje9l0`bQRPqI&Ff{e)_SKHT6yG;ln=Fu;EHol zwo3`ir^$Nj2N9O)Qm+WOZWXB1`aM)lS8s>Ivq6&M>C-GC4^)uH79CwPmP9?U!e#x> zDxMLh=JoZWX9v^=@2{CWgD@Cb-CCYm6e6w zC0ILkq+#kC1lp7Jr5QsnGs(u(rpHU80#Yd(t#)nl@8#!`>_eVj@a*IEYsEHU9*XD1 z2vJ%~)W+`1c9340h(wsC_H^o}uujK0@xd2JssL=5B#4-S0QP2U9N;k>2+XPh_YGPU zv%yoz!Z|RXNEU~4!XM@#N*nttXr!;1TFG$h`Dm2&Rt(#fX9|9O3gnGMMCeJRm9BG$ zJqIa?P&+3Qxo{<>m_&%OLUIDhOqH zEBA$k_M!&x+0(X@mC+(Y+HGX;Y+pqS&k4bjrA|KC4+L75EM?tqHI)F_a(l#EcX1WH z+dd5Ilz-IfRm;9YFEQFHeR3?mSg5UxzBT1i{Jwmke7+36PL^A~usfZgf-8X>L3%YdSv`> zE0YA_d>4~qLz-6GtyPbDf1dw*bypkI1J{`wHrT{tg!Xy>2}>lOcGeAPqQuA;i;;xn z7Rxiu>i$7$w39u|ewOLc>F69zQw^#I841I|)$%Nyl7iEJvbN2S16C=HBk|?smU15X z?TRv}9kdfOb5X*#qKkAc%5yrjBnmQrnY-|*vT09;<2)f+KwA%@x?Nc(x`xT(y6oDb zsVBW;vF$K*IhQf2k2%lEiWS#eo3Pi2lbT_HO+N&iI0$R}EQ(G8MW1!m$}v;)?PQ8e z>um%Dm%2^AC&SQDY|+ibgMo)AiaYIOxo-)`MtBZ~B_e|{#0?BmZo1i_%g7jTFg{YZ zIwvr6Rd^YZdJj*zIgluO#P{TNb;_k&)kK6zAm^CwA2KucXk9?zp7e#Gwu$u5DNYYQ z%CriIe4R^{J%@yCKIUrYd2;GP6E+ZMz(m`&HG}$($pzUDgX+m%Vzx`Att>)#sCeJO zPzNPG@DeORnh*XYgqO#UR?VY+!Pis9Gb(MOcY>iu0s(K2mSAZ}IV$ET#VuMQhlXk5 zT(N))-j5D|w^4Y_jbfvy91$^Q9K{L6fsZnsHgz-K7LL`eZQqn&4C`)gLX_Z&js!$G`6re!Bb<)#Z}`+%33##u-q^MD*TgwYZ@FTcAhE z1_3u`fX{J$?e6O1F2oNqvu%veOE$WwyofiiO!2dFC4vSQ5^qSp-JZ7BXwf zkn?1_b4nHUFa=98W$N|{oU)({J)<_{&q^V;YB{5|+S@f&uZ>p8N3s*bTh+R~b5i_k zv(2}WMJZwFeoa~T<-^W?`x3y_pTU74H+`!rV2uy99MkVNT5AP_ zkUDjD3%rQ1MWwk3;Fsv{VXOzD%q=LUzT8|=@855gO?pZ!u0xVP+!`=0Y4LaB<`s{%i7yVXMs5>1>@6dLE6JV^=k$8_ ze7Erg!|bwUc}L^XLz8s(Gn~NGmrvtsuxJ4cme01I7~g_gUZ^h>znhnFvy5;@LRaS_ z=K06+6A3CFF1f^2deWCtHM_(n7A`Y=6>?5V|`YSFrYKEBc-ksmltdp9Uu0m2mj)fk`^80^Q&!wN9M zWJ`*yz*4@)s)Z@1A7|kDR9pSbumJs&jWFCxh^LX?doZ4!s}dOEWKlr_H=o|?CC;`#M@PV% z;5{$qS?H&ItBsgr{=7FTelLp4i$`)jwh@1&QwkIN!eXG!2tsw1JElcrj?{5`LeWGM ztE>Am@@#G+rYd@F2X+v7_I;joE-Kj zCtOv#hJ$!J){r)fEl9EW3i%~?@a~SuV!`>n@_v$*r$3a6IoXVdg9&R0-W<&|;IynH z5eWI)FYJwTe-Nx+-Ck{c>DnJm2pz-Pykk2UKbIsp@tueOrOFMB|1#srz5JRCf``t` z++DB_V4F=_)etG!;jw<%#^U%aiE%;+*uzP9$%c%?IeNSF*om;?AQN%!%~rSc*Z!2ySes&BtZL3brB2E1AkU9(W__Q zN|}!?jPkFo_nNU|=6A28H}Q0jyE7(nsr0J{g%sLt>%&)W;3qn|RQd*NM{S7cRL^p{q!$zYZCh(%DarkaIkL zh7owAEuJE14Cr5@5V|%~&)M4>+nt&1{6#I_5)p-0lMlfm*Vi?adod4Z=Ih~;({}F+ zR!z_Sp4G71MF=9!jlFdEh&I?ue#(OT#kjg^=tUrd||0H z%$Og@!Ym)4k2r=%F0rt+Iun$gUG)G4SRkeR6(HZaKczVcW-~)bEKbkZX(Ko4w>Q!+ z!LQ@6Iu3+TO!Y?r;M%Uq^#cz-i&zlJRzN?|D-mTE;ycZ6y&tVN%HNeQ;V0KT{6#aJ zjm=ryF-t7N5|cMr5;zSE&CyhthkhBcYJp zuS{$DmHZJWWJJj6^_%6S$5YIVr`UVs>NREzpZEg6i%-{XEZACLv`swO?*pwzj4^#( zKSRVB4=}Vww{?qRSmo~}`~lp^jt}`E?cNZPI8>ryE}l?iCAWZ!t`+(IT2>@E`;7TO z55WGj68pXy(@`>i=nAKmPqy`l`-M*{ba6S>@200>pBIYDXA;=17z5IVvge`^H_nO+ pPH>82?3JD=BTIK7hf2sTfu>1`gk99A)8BtcH6?Au3I&Ux{{i(>7Ulo| diff --git a/assets/tft.png b/assets/tft.png deleted file mode 100644 index d43126cbfc61c5b46ff4cda3526ac80cd3b68c06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4099 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 JWs25s{|6BFyIcSO literal 0 HcmV?d00001 diff --git a/css/paper@2x.png b/css/paper@2x.png deleted file mode 100644 index 68f4d6574a18a11f600a75680161592dd69ad313..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13793 zcmWk#2RK_@7>*sYF_YdB2m``^I-T*#y`C008G*13d)o-249lWT5%X z=x1fL6RW#{r56Ce&insC2gu9@0|0C$PP)4H?>oAAyLmafxr^M@)fI8~bhCGIu>%17 zCvzS+m_1m%piZ6H)iFeeVGZ37=Yb*!ows3pNs?C~tROfVl0R|Yw1fNhZAQV~JTyam zd>H1usSL*(wx2AEkb?M#LiC%yqq(3$6seiIJa|eN*H|f|Ug?<5sNU>F}jD==QC7@(z37nYMQ`2di|2(aq6wOIh%mjzf|30)oogykG$ z1knK=V+M0Amoqs#i?R9}t-V;M3nRSKF2@2d!MCjZ{XpT7$Ui?eNDySq~O-^J~IV zLwEV5`IN2ctuwW*bp~WyydJK2?l)xs0LV)^PwOq^#D9pZd}v5HzK-j;?B6!#Gf^9x zh0~?sQgT_BIK;G)4ImP||vALa} z*f24%w7B>a-mUZ4y3aiL)S>fvyZMRBVTjr>b?d3!0C=V+ ze$A|}MzaS90O;j~U#-*@-0c9%v@;8JF#YOaKekei)DiFQ)B)+Ry$BQXw1Sqs){%-H zth{v9O76SXCB=4A$LM$NT-Q1ue&$klKljfXnA;)M9L~z9-3#QkhD@UAY~EOi#RK^> zq7EP(28=v!#YMiN`AkI(lavf#h&N^;4-GEusC&|@#yrt)OuE$zxc>S$y7>+a8(wXy z{+)xM+wkFrK%{;F`^XD#SZ2b7ysQz=S^;&8a{kIlspGlH1P$FD`Sw3x7KLsX`D?^3 zohlU>)_1o3Rib4ar9^?sM`a96v3s_|Rep>-;kVmal^OkXM689i4J__i82>c*AR;8L z$UVt=gOwrDwDXGSyAOu7l8xMl-C&#Ruow#i88H%102(8ARzYc>*NbmHH#`%Mnt+dYB6WAYf)iQa1pZem@UUf%cJPv z!Mqfr&l!Gk3ACiR#B7&-UHf5SCSv+Sz8SYt0#XN`Ux%nLjrqW<=#!~B7;)jQAr4=V zGA7{2??`p3_~YHkJ)I(KoHk@kzS0b5I7$vBtc_R!*L-PKp;lls_F;3<+Rf>-6tK7K0xH1mo5A?0DeS;EI> z4}#0}A1XXp_{jP_we;bqocn7J1Rpqjy!9dGlfwr$GtHt9%ad4U%dUG}Cb~tYc~#FB znu#Lpwij#sWgsZd(rBM>rEbZp!HHMCSDVsLE;YSX|MW3mRaXJ7U|xfuVC^+o7ScTq zvb~L2SENePC?RiV_{h+Cs9>?;y#|=w6V#{Fv{Z{ygHqGdJ8Lb<)x$D&a0^ zFn(uTnoDx%s@$&oTKBR3V&&3L=Be^J*ScV92OEBe`Y+{Oo9|lQ1vduAov5>L#!PUP zUP4|9@v8OYyZPwmOy*Gbre^S$-PBb%2a93Q@K1$>I^KS0w^Po8tg$-|{0> zSi{%-*U~huWeF0eds`Oa-g_QT=K{a&NRxZgLKVDgn^ZP`#Ci83TYk0n2&{$BrF>`&! z^7+7x_WIuXev>Y@+~-lVx}jocFU|tbMgb*Z5_Ap>vEka`kLiyN0$)Me;x%th+3i

8)FfWBw;cFkkz;Y! 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 N?%p=mE7!4l{U4be=c)hz diff --git a/index.html b/index.html index 476ed6e..d226924 100644 --- a/index.html +++ b/index.html @@ -25,6 +25,7 @@ + @@ -44,7 +45,10 @@ var slideshow, slideSelect; window.onload = function(){ - Words.convert("lang/en.html").then(function(){ + Q.all([ + Loader.loadAssets(Loader.manifest), + Words.convert("lang/en.html") + ]).then(function(){ // Slideshow slideshow = new Slideshow({ diff --git a/js/core/Loader.js b/js/core/Loader.js new file mode 100644 index 0000000..5e6bf66 --- /dev/null +++ b/js/core/Loader.js @@ -0,0 +1,113 @@ +window.Loader = {}; + +Loader.manifest = {}; +Loader.manifestPreload = {}; // For Preloader +Loader.sounds = {}; + +/*************** + +Actually LOAD all the assets in a manifest. Like so: + +Loader.loadAssets(Loader.manifest, function(){ + Loader.sceneManager.gotoScene(Loader.START_SCENE); + Loader.startUpdateAndDraw(); +}); + +***************/ +Loader.loadAssets = function(manifest, completeCallback, progressCallback){ + + var deferred = Q.defer(); + completeCallback = completeCallback || function(){}; + progressCallback = progressCallback || function(){}; + + // ABSOLUTE NUMBER OF ASSETS! + var _isLoadingImages = 0; + var _isLoadingSounds = 0; + var _totalAssetsLoaded = 0; + var _totalAssetsToLoad = 0; + for(var key in manifest){ + var src = manifest[key]; + + // Loading sounds or images? + if(src.slice(-4)==".mp3") _isLoadingSounds=1; + else _isLoadingImages=1; + + // Loading sprite or image? + if(src.slice(-5)==".json") _totalAssetsToLoad+=2; // Is Sprite. Actually TWO assets. + else _totalAssetsToLoad+=1; + + } + + // When you load an asset + var _onAssetLoad = function(){ + _totalAssetsLoaded++; + if(progressCallback){ + progressCallback(_totalAssetsLoaded/_totalAssetsToLoad); // Callback PROGRESS + } + }; + + // When you load a group + var _groupsToLoad = _isLoadingImages + _isLoadingSounds; + var _onGroupLoaded = function(){ + _groupsToLoad--; + if(_groupsToLoad==0){ + completeCallback(); // DONE. + deferred.resolve(); + } + }; + + // HOWLER - Loading Sounds + var _soundsToLoad = 0; + var _onSoundLoad = function(){ + _soundsToLoad--; + _onAssetLoad(); + if(_soundsToLoad==0) _onGroupLoaded(); + }; + + // PIXI - Loading Images & Sprites (or pass it to Howler) + var loader = PIXI.loader; + var resources = PIXI.loader.resources; + for(var key in manifest){ + + var src = manifest[key]; + + // Is MP3. Leave it to Howler. + if(src.slice(-4)==".mp3"){ + var sound = new Howl({ src:[src] }); + _soundsToLoad++; + sound.once('load', _onSoundLoad); + Loader.sounds[key] = sound; + continue; + } + + // Otherwise, is an image (or json). Leave it to PIXI. + loader.add(key, src); + + } + loader.on('progress', _onAssetLoad); + loader.once('complete', _onGroupLoaded); + loader.load(); + + // Promise! + return deferred.promise; + +}; + +/*************** + +Add assets to manifest! Like so: + +Loader.addToManifest(Loader.manifest,{ + bg: "sprites/bg.png", + button: "sprites/button/button.json", + [key]: [filepath], + [key]: [filepath], + etc... +}); + +***************/ +Loader.addToManifest = function(manifest, keyValues){ + for(var key in keyValues){ + manifest[key] = keyValues[key]; + } +}; diff --git a/js/lib/helpers.js b/js/lib/helpers.js index f93c95b..784d231 100644 --- a/js/lib/helpers.js +++ b/js/lib/helpers.js @@ -1,3 +1,8 @@ +/********************************** + +RANDOM CRAP TO MAKE MY LIFE EASIER + +**********************************/ // Pi is for unwashed plebians Math.TAU = 2*Math.PI; @@ -39,4 +44,63 @@ var _removeFade = function(self, INSTANT){ },300); return deferred.promise; } -}; \ No newline at end of file +}; + +/******* + +Make a Sprite. e.g: + +_makeSprite("bg", {width:960}); + +*******/ +function _makeSprite(textureName, options){ + options = options || {}; + + // Make Sprite + var sprite = new PIXI.Sprite(PIXI.loader.resources[textureName].texture); + + // Options + if(options.width!==undefined) _scaleToWidth(sprite, options.width); + if(options.anchorX!==undefined) sprite.anchor.x=options.anchorX; + if(options.anchorY!==undefined) sprite.anchor.y=options.anchorY; + + // Gimme + return sprite; +} + +/******* + +Make a MovieClip. e.g: + +_makeSprite("button", {width:960}); + +*******/ +function _makeMovieClip(resourceName, options){ + options = options || {}; + + // Make that MovieClip! + var resources = PIXI.loader.resources; + var resource = resources[resourceName]; + if(!resource) throw Error("There's no MovieClip named '"+resourceName+"'!"); + var numFrames = Object.keys(resource.data.frames).length; + var frames = []; + for(var i=0; i= 0 && vol <= 1) { + self._volume = vol; + + // Don't update any of the nodes if we are muted. + if (self._muted) { + return self; + } + + // When using Web Audio, we just need to adjust the master gain. + if (self.usingWebAudio) { + self.masterGain.gain.value = vol; + } + + // Loop through and change volume for all HTML5 audio nodes. + for (var i=0; i=0; i--) { + self._howls[i].unload(); + } + + // Create a new AudioContext to make sure it is fully reset. + if (self.usingWebAudio && typeof self.ctx.close !== 'undefined') { + self.ctx.close(); + self.ctx = null; + setupAudioContext(); + } + + return self; + }, + + /** + * Check for codec support of specific extension. + * @param {String} ext Audio file extention. + * @return {Boolean} + */ + codecs: function(ext) { + return (this || Howler)._codecs[ext]; + }, + + /** + * Setup various state values for global tracking. + * @return {Howler} + */ + _setup: function() { + var self = this || Howler; + + // Keeps track of the suspend/resume state of the AudioContext. + self.state = self.ctx ? self.ctx.state || 'running' : 'running'; + + // Automatically begin the 30-second suspend process + self._autoSuspend(); + + // Check for supported codecs. + if (!self.noAudio) { + self._setupCodecs(); + } + + return self; + }, + + /** + * Check for browser support for various codecs and cache the results. + * @return {Howler} + */ + _setupCodecs: function() { + var self = this || Howler; + var audioTest = (typeof Audio !== 'undefined') ? new Audio() : null; + + if (!audioTest || typeof audioTest.canPlayType !== 'function') { + return self; + } + + var mpegTest = audioTest.canPlayType('audio/mpeg;').replace(/^no$/, ''); + + // Opera version <33 has mixed MP3 support, so we need to check for and block it. + var checkOpera = self._navigator && self._navigator.userAgent.match(/OPR\/([0-6].)/g); + var isOldOpera = (checkOpera && parseInt(checkOpera[0].split('/')[1], 10) < 33); + + self._codecs = { + mp3: !!(!isOldOpera && (mpegTest || audioTest.canPlayType('audio/mp3;').replace(/^no$/, ''))), + mpeg: !!mpegTest, + opus: !!audioTest.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/, ''), + ogg: !!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ''), + oga: !!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ''), + wav: !!audioTest.canPlayType('audio/wav; codecs="1"').replace(/^no$/, ''), + aac: !!audioTest.canPlayType('audio/aac;').replace(/^no$/, ''), + caf: !!audioTest.canPlayType('audio/x-caf;').replace(/^no$/, ''), + m4a: !!(audioTest.canPlayType('audio/x-m4a;') || audioTest.canPlayType('audio/m4a;') || audioTest.canPlayType('audio/aac;')).replace(/^no$/, ''), + mp4: !!(audioTest.canPlayType('audio/x-mp4;') || audioTest.canPlayType('audio/mp4;') || audioTest.canPlayType('audio/aac;')).replace(/^no$/, ''), + weba: !!audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, ''), + webm: !!audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, ''), + dolby: !!audioTest.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/, '') + }; + + return self; + }, + + /** + * Mobile browsers will only allow audio to be played after a user interaction. + * Attempt to automatically unlock audio on the first user interaction. + * Concept from: http://paulbakaus.com/tutorials/html5/web-audio-on-ios/ + * @return {Howler} + */ + _enableMobileAudio: function() { + var self = this || Howler; + + // Only run this on mobile devices if audio isn't already eanbled. + var isMobile = /iPhone|iPad|iPod|Android|BlackBerry|BB10|Silk|Mobi/i.test(self._navigator && self._navigator.userAgent); + var isTouch = !!(('ontouchend' in window) || (self._navigator && self._navigator.maxTouchPoints > 0) || (self._navigator && self._navigator.msMaxTouchPoints > 0)); + if (self._mobileEnabled || !self.ctx || (!isMobile && !isTouch)) { + return; + } + + self._mobileEnabled = false; + + // Some mobile devices/platforms have distortion issues when opening/closing tabs and/or web views. + // Bugs in the browser (especially Mobile Safari) can cause the sampleRate to change from 44100 to 48000. + // By calling Howler.unload(), we create a new AudioContext with the correct sampleRate. + if (!self._mobileUnloaded && self.ctx.sampleRate !== 44100) { + self._mobileUnloaded = true; + self.unload(); + } + + // Scratch buffer for enabling iOS to dispose of web audio buffers correctly, as per: + // http://stackoverflow.com/questions/24119684 + self._scratchBuffer = self.ctx.createBuffer(1, 1, 22050); + + // Call this method on touch start to create and play a buffer, + // then check if the audio actually played to determine if + // audio has now been unlocked on iOS, Android, etc. + var unlock = function() { + // Create an empty buffer. + var source = self.ctx.createBufferSource(); + source.buffer = self._scratchBuffer; + source.connect(self.ctx.destination); + + // Play the empty buffer. + if (typeof source.start === 'undefined') { + source.noteOn(0); + } else { + source.start(0); + } + + // Setup a timeout to check that we are unlocked on the next event loop. + source.onended = function() { + source.disconnect(0); + + // Update the unlocked state and prevent this check from happening again. + self._mobileEnabled = true; + self.mobileAutoEnable = false; + + // Remove the touch start listener. + document.removeEventListener('touchend', unlock, true); + }; + }; + + // Setup a touch start listener to attempt an unlock in. + document.addEventListener('touchend', unlock, true); + + return self; + }, + + /** + * Automatically suspend the Web Audio AudioContext after no sound has played for 30 seconds. + * This saves processing/energy and fixes various browser-specific bugs with audio getting stuck. + * @return {Howler} + */ + _autoSuspend: function() { + var self = this; + + if (!self.autoSuspend || !self.ctx || typeof self.ctx.suspend === 'undefined' || !Howler.usingWebAudio) { + return; + } + + // Check if any sounds are playing. + for (var i=0; i 0 ? sound._seek : self._sprite[sprite][0] / 1000; + var duration = ((self._sprite[sprite][0] + self._sprite[sprite][1]) / 1000) - seek; + var timeout = (duration * 1000) / Math.abs(sound._rate); + + // Update the parameters of the sound + sound._paused = false; + sound._ended = false; + sound._sprite = sprite; + sound._seek = seek; + sound._start = self._sprite[sprite][0] / 1000; + sound._stop = (self._sprite[sprite][0] + self._sprite[sprite][1]) / 1000; + sound._loop = !!(sound._loop || self._sprite[sprite][2]); + + // Begin the actual playback. + var node = sound._node; + if (self._webAudio) { + // Fire this when the sound is ready to play to begin Web Audio playback. + var playWebAudio = function() { + self._refreshBuffer(sound); + + // Setup the playback params. + var vol = (sound._muted || self._muted) ? 0 : sound._volume; + node.gain.setValueAtTime(vol, Howler.ctx.currentTime); + sound._playStart = Howler.ctx.currentTime; + + // Play the sound using the supported method. + if (typeof node.bufferSource.start === 'undefined') { + sound._loop ? node.bufferSource.noteGrainOn(0, seek, 86400) : node.bufferSource.noteGrainOn(0, seek, duration); + } else { + sound._loop ? node.bufferSource.start(0, seek, 86400) : node.bufferSource.start(0, seek, duration); + } + + // Start a new timer if none is present. + if (timeout !== Infinity) { + self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout); + } + + if (!internal) { + setTimeout(function() { + self._emit('play', sound._id); + }, 0); + } + }; + + if (self._state === 'loaded') { + playWebAudio(); + } else { + // Wait for the audio to load and then begin playback. + self.once('load', playWebAudio, sound._id); + + // Cancel the end timer. + self._clearTimer(sound._id); + } + } else { + // Fire this when the sound is ready to play to begin HTML5 Audio playback. + var playHtml5 = function() { + node.currentTime = seek; + node.muted = sound._muted || self._muted || Howler._muted || node.muted; + node.volume = sound._volume * Howler.volume(); + node.playbackRate = sound._rate; + + setTimeout(function() { + node.play(); + + // Setup the new end timer. + if (timeout !== Infinity) { + self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout); + } + + if (!internal) { + self._emit('play', sound._id); + } + }, 0); + }; + + // Play immediately if ready, or wait for the 'canplaythrough'e vent. + var loadedNoReadyState = (self._state === 'loaded' && (window && window.ejecta || !node.readyState && Howler._navigator.isCocoonJS)); + if (node.readyState === 4 || loadedNoReadyState) { + playHtml5(); + } else { + var listener = function() { + // Begin playback. + playHtml5(); + + // Clear this listener. + node.removeEventListener(Howler._canPlayEvent, listener, false); + }; + node.addEventListener(Howler._canPlayEvent, listener, false); + + // Cancel the end timer. + self._clearTimer(sound._id); + } + } + + return sound._id; + }, + + /** + * Pause playback and save current position. + * @param {Number} id The sound ID (empty to pause all in group). + * @return {Howl} + */ + pause: function(id) { + var self = this; + + // If the sound hasn't loaded, add it to the load queue to pause when capable. + if (self._state !== 'loaded') { + self._queue.push({ + event: 'pause', + action: function() { + self.pause(id); + } + }); + + return self; + } + + // If no id is passed, get all ID's to be paused. + var ids = self._getSoundIds(id); + + for (var i=0; i Returns the group's volume value. + * volume(id) -> Returns the sound id's current volume. + * volume(vol) -> Sets the volume of all sounds in this Howl group. + * volume(vol, id) -> Sets the volume of passed sound id. + * @return {Howl/Number} Returns self or current volume. + */ + volume: function() { + var self = this; + var args = arguments; + var vol, id; + + // Determine the values based on arguments. + if (args.length === 0) { + // Return the value of the groups' volume. + return self._volume; + } else if (args.length === 1) { + // First check if this is an ID, and if not, assume it is a new volume. + var ids = self._getSoundIds(); + var index = ids.indexOf(args[0]); + if (index >= 0) { + id = parseInt(args[0], 10); + } else { + vol = parseFloat(args[0]); + } + } else if (args.length >= 2) { + vol = parseFloat(args[0]); + id = parseInt(args[1], 10); + } + + // Update the volume or return the current volume. + var sound; + if (typeof vol !== 'undefined' && vol >= 0 && vol <= 1) { + // If the sound hasn't loaded, add it to the load queue to change volume when capable. + if (self._state !== 'loaded') { + self._queue.push({ + event: 'volume', + action: function() { + self.volume.apply(self, args); + } + }); + + return self; + } + + // Set the group volume. + if (typeof id === 'undefined') { + self._volume = vol; + } + + // Update one or all volumes. + id = self._getSoundIds(id); + for (var i=0; i to ? 'out' : 'in'; + var steps = diff / 0.01; + var stepLen = len / steps; + + // If the sound hasn't loaded, add it to the load queue to fade when capable. + if (self._state !== 'loaded') { + self._queue.push({ + event: 'fade', + action: function() { + self.fade(from, to, len, id); + } + }); + + return self; + } + + // Set the volume to the start position. + self.volume(from, id); + + // Fade the volume of one or all sounds. + var ids = self._getSoundIds(id); + for (var i=0; i Returns the group's loop value. + * loop(id) -> Returns the sound id's loop value. + * loop(loop) -> Sets the loop value for all sounds in this Howl group. + * loop(loop, id) -> Sets the loop value of passed sound id. + * @return {Howl/Boolean} Returns self or current loop value. + */ + loop: function() { + var self = this; + var args = arguments; + var loop, id, sound; + + // Determine the values for loop and id. + if (args.length === 0) { + // Return the grou's loop value. + return self._loop; + } else if (args.length === 1) { + if (typeof args[0] === 'boolean') { + loop = args[0]; + self._loop = loop; + } else { + // Return this sound's loop value. + sound = self._soundById(parseInt(args[0], 10)); + return sound ? sound._loop : false; + } + } else if (args.length === 2) { + loop = args[0]; + id = parseInt(args[1], 10); + } + + // If no id is passed, get all ID's to be looped. + var ids = self._getSoundIds(id); + for (var i=0; i Returns the first sound node's current playback rate. + * rate(id) -> Returns the sound id's current playback rate. + * rate(rate) -> Sets the playback rate of all sounds in this Howl group. + * rate(rate, id) -> Sets the playback rate of passed sound id. + * @return {Howl/Number} Returns self or the current playback rate. + */ + rate: function() { + var self = this; + var args = arguments; + var rate, id; + + // Determine the values based on arguments. + if (args.length === 0) { + // We will simply return the current rate of the first node. + id = self._sounds[0]._id; + } else if (args.length === 1) { + // First check if this is an ID, and if not, assume it is a new rate value. + var ids = self._getSoundIds(); + var index = ids.indexOf(args[0]); + if (index >= 0) { + id = parseInt(args[0], 10); + } else { + rate = parseFloat(args[0]); + } + } else if (args.length === 2) { + rate = parseFloat(args[0]); + id = parseInt(args[1], 10); + } + + // Update the playback rate or return the current value. + var sound; + if (typeof rate === 'number') { + // If the sound hasn't loaded, add it to the load queue to change playback rate when capable. + if (self._state !== 'loaded') { + self._queue.push({ + event: 'rate', + action: function() { + self.rate.apply(self, args); + } + }); + + return self; + } + + // Set the group rate. + if (typeof id === 'undefined') { + self._rate = rate; + } + + // Update one or all volumes. + id = self._getSoundIds(id); + for (var i=0; i Returns the first sound node's current seek position. + * seek(id) -> Returns the sound id's current seek position. + * seek(seek) -> Sets the seek position of the first sound node. + * seek(seek, id) -> Sets the seek position of passed sound id. + * @return {Howl/Number} Returns self or the current seek position. + */ + seek: function() { + var self = this; + var args = arguments; + var seek, id; + + // Determine the values based on arguments. + if (args.length === 0) { + // We will simply return the current position of the first node. + id = self._sounds[0]._id; + } else if (args.length === 1) { + // First check if this is an ID, and if not, assume it is a new seek position. + var ids = self._getSoundIds(); + var index = ids.indexOf(args[0]); + if (index >= 0) { + id = parseInt(args[0], 10); + } else { + id = self._sounds[0]._id; + seek = parseFloat(args[0]); + } + } else if (args.length === 2) { + seek = parseFloat(args[0]); + id = parseInt(args[1], 10); + } + + // If there is no ID, bail out. + if (typeof id === 'undefined') { + return self; + } + + // If the sound hasn't loaded, add it to the load queue to seek when capable. + if (self._state !== 'loaded') { + self._queue.push({ + event: 'seek', + action: function() { + self.seek.apply(self, args); + } + }); + + return self; + } + + // Get the sound. + var sound = self._soundById(id); + + if (sound) { + if (typeof seek === 'number' && seek >= 0) { + // Pause the sound and update position for restarting playback. + var playing = self.playing(id); + if (playing) { + self.pause(id, true); + } + + // Move the position of the track and cancel timer. + sound._seek = seek; + sound._ended = false; + self._clearTimer(id); + + // Restart the playback if the sound was playing. + if (playing) { + self.play(id, true); + } + + // Update the seek position for HTML5 Audio. + if (!self._webAudio && sound._node) { + sound._node.currentTime = seek; + } + + self._emit('seek', id); + } else { + if (self._webAudio) { + var realTime = self.playing(id) ? Howler.ctx.currentTime - sound._playStart : 0; + var rateSeek = sound._rateSeek ? sound._rateSeek - sound._seek : 0; + return sound._seek + (rateSeek + realTime * Math.abs(sound._rate)); + } else { + return sound._node.currentTime; + } + } + } + + return self; + }, + + /** + * Check if a specific sound is currently playing or not (if id is provided), or check if at least one of the sounds in the group is playing or not. + * @param {Number} id The sound id to check. If none is passed, the whole sound group is checked. + * @return {Boolean} True if playing and false if not. + */ + playing: function(id) { + var self = this; + + // Check the passed sound ID (if any). + if (typeof id === 'number') { + var sound = self._soundById(id); + return sound ? !sound._paused : false; + } + + // Otherwise, loop through all sounds and check if any are playing. + for (var i=0; i= 0) { + Howler._howls.splice(index, 1); + } + } + + // Delete this sound from the cache (if no other Howl is using it). + var remCache = true; + for (i=0; i=0; i--) { + if (!events[i].id || events[i].id === id || event === 'load') { + setTimeout(function(fn) { + fn.call(this, id, msg); + }.bind(self, events[i].fn), 0); + + // If this event was setup with `once`, remove it. + if (events[i].once) { + self.off(event, events[i].fn, events[i].id); + } + } + } + + return self; + }, + + /** + * Queue of actions initiated before the sound has loaded. + * These will be called in sequence, with the next only firing + * after the previous has finished executing (even if async like play). + * @return {Howl} + */ + _loadQueue: function() { + var self = this; + + if (self._queue.length > 0) { + var task = self._queue[0]; + + // don't move onto the next task until this one is done + self.once(task.event, function() { + self._queue.shift(); + self._loadQueue(); + }); + + task.action(); + } + + return self; + }, + + /** + * Fired when playback ends at the end of the duration. + * @param {Sound} sound The sound object to work with. + * @return {Howl} + */ + _ended: function(sound) { + var self = this; + var sprite = sound._sprite; + + // Should this sound loop? + var loop = !!(sound._loop || self._sprite[sprite][2]); + + // Fire the ended event. + self._emit('end', sound._id); + + // Restart the playback for HTML5 Audio loop. + if (!self._webAudio && loop) { + self.stop(sound._id, true).play(sound._id); + } + + // Restart this timer if on a Web Audio loop. + if (self._webAudio && loop) { + self._emit('play', sound._id); + sound._seek = sound._start || 0; + sound._rateSeek = 0; + sound._playStart = Howler.ctx.currentTime; + + var timeout = ((sound._stop - sound._start) * 1000) / Math.abs(sound._rate); + self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout); + } + + // Mark the node as paused. + if (self._webAudio && !loop) { + sound._paused = true; + sound._ended = true; + sound._seek = sound._start || 0; + sound._rateSeek = 0; + self._clearTimer(sound._id); + + // Clean up the buffer source. + self._cleanBuffer(sound._node); + + // Attempt to auto-suspend AudioContext if no sounds are still playing. + Howler._autoSuspend(); + } + + // When using a sprite, end the track. + if (!self._webAudio && !loop) { + self.stop(sound._id); + } + + return self; + }, + + /** + * Clear the end timer for a sound playback. + * @param {Number} id The sound ID. + * @return {Howl} + */ + _clearTimer: function(id) { + var self = this; + + if (self._endTimers[id]) { + clearTimeout(self._endTimers[id]); + delete self._endTimers[id]; + } + + return self; + }, + + /** + * Return the sound identified by this ID, or return null. + * @param {Number} id Sound ID + * @return {Object} Sound object or null. + */ + _soundById: function(id) { + var self = this; + + // Loop through all sounds and find the one with this ID. + for (var i=0; i=0; i--) { + if (cnt <= limit) { + return; + } + + if (self._sounds[i]._ended) { + // Disconnect the audio source when using Web Audio. + if (self._webAudio && self._sounds[i]._node) { + self._sounds[i]._node.disconnect(0); + } + + // Remove sounds until we have the pool size. + self._sounds.splice(i, 1); + cnt--; + } + } + }, + + /** + * Get all ID's from the sounds pool. + * @param {Number} id Only return one ID if one is passed. + * @return {Array} Array of IDs. + */ + _getSoundIds: function(id) { + var self = this; + + if (typeof id === 'undefined') { + var ids = []; + for (var i=0; i 0) { + cache[self._src] = buffer; + loadSound(self, buffer); + } + }, function() { + self._emit('loaderror', null, 'Decoding audio data failed.'); + }); + }; + + /** + * Sound is now loaded, so finish setting everything up and fire the loaded event. + * @param {Howl} self + * @param {Object} buffer The decoded buffer sound source. + */ + var loadSound = function(self, buffer) { + // Set the duration. + if (buffer && !self._duration) { + self._duration = buffer.duration; + } + + // Setup a sprite if none is defined. + if (Object.keys(self._sprite).length === 0) { + self._sprite = {__default: [0, self._duration * 1000]}; + } + + // Fire the loaded event. + if (self._state !== 'loaded') { + self._state = 'loaded'; + self._emit('load'); + self._loadQueue(); + } + + // Begin playback if specified. + if (self._autoplay) { + self.play(); + } + }; + + /** + * Setup the audio context when available, or switch to HTML5 Audio mode. + */ + var setupAudioContext = function() { + Howler.noAudio = false; + + // Check if we are using Web Audio and setup the AudioContext if we are. + try { + if (typeof AudioContext !== 'undefined') { + Howler.ctx = new AudioContext(); + } else if (typeof webkitAudioContext !== 'undefined') { + Howler.ctx = new webkitAudioContext(); + } else { + Howler.usingWebAudio = false; + } + } catch(e) { + Howler.usingWebAudio = false; + } + + if (!Howler.usingWebAudio) { + // No audio is available on this system if noAudio is set to true. + if (typeof Audio !== 'undefined') { + try { + var test = new Audio(); + + // Check if the canplaythrough event is available. + if (typeof test.oncanplaythrough === 'undefined') { + Howler._canPlayEvent = 'canplay'; + } + } catch(e) { + Howler.noAudio = true; + } + } else { + Howler.noAudio = true; + } + } + + // Test to make sure audio isn't disabled in Internet Explorer + try { + var test = new Audio(); + if (test.muted) { + Howler.noAudio = true; + } + } catch (e) {} + + // Check if a webview is being used on iOS8 or earlier (rather than the browser). + // If it is, disable Web Audio as it causes crashing. + var iOS = (/iP(hone|od|ad)/.test(Howler._navigator && Howler._navigator.platform)); + var appVersion = Howler._navigator && Howler._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/); + var version = appVersion ? parseInt(appVersion[1], 10) : null; + if (iOS && version && version < 9) { + var safari = /safari/.test(Howler._navigator && Howler._navigator.userAgent.toLowerCase()); + if (Howler._navigator && Howler._navigator.standalone && !safari || Howler._navigator && !Howler._navigator.standalone && !safari) { + Howler.usingWebAudio = false; + } + } + + // Create and expose the master GainNode when using Web Audio (useful for plugins or advanced usage). + if (Howler.usingWebAudio) { + Howler.masterGain = (typeof Howler.ctx.createGain === 'undefined') ? Howler.ctx.createGainNode() : Howler.ctx.createGain(); + Howler.masterGain.gain.value = 1; + Howler.masterGain.connect(Howler.ctx.destination); + } + + // Re-run the setup on Howler. + Howler._setup(); + }; + + // Add support for AMD (Asynchronous Module Definition) libraries such as require.js. + if (typeof define === 'function' && define.amd) { + define([], function() { + return { + Howler: Howler, + Howl: Howl + }; + }); + } + + // Add support for CommonJS libraries such as browserify. + if (typeof exports !== 'undefined') { + exports.Howler = Howler; + exports.Howl = Howl; + } + + // Define globally in case AMD is not available or unused. + if (typeof window !== 'undefined') { + window.HowlerGlobal = HowlerGlobal; + window.Howler = Howler; + window.Howl = Howl; + window.Sound = Sound; + } else if (typeof global !== 'undefined') { // Add to global in Node.js (for testing, etc). + global.HowlerGlobal = HowlerGlobal; + global.Howler = Howler; + global.Howl = Howl; + global.Sound = Sound; + } +})(); + + +/*! + * Spatial Plugin - Adds support for stereo and 3D audio where Web Audio is supported. + * + * howler.js v2.0.0 + * howlerjs.com + * + * (c) 2013-2016, James Simpson of GoldFire Studios + * goldfirestudios.com + * + * MIT License + */ + +(function() { + + 'use strict'; + + // Setup default properties. + HowlerGlobal.prototype._pos = [0, 0, 0]; + HowlerGlobal.prototype._orientation = [0, 0, -1, 0, 1, 0]; + + /** Global Methods **/ + /***************************************************************************/ + + /** + * Helper method to update the stereo panning position of all current Howls. + * Future Howls will not use this value unless explicitly set. + * @param {Number} pan A value of -1.0 is all the way left and 1.0 is all the way right. + * @return {Howler/Number} Self or current stereo panning value. + */ + HowlerGlobal.prototype.stereo = function(pan) { + var self = this; + + // Stop right here if not using Web Audio. + if (!self.ctx || !self.ctx.listener) { + return self; + } + + // Loop through all Howls and update their stereo panning. + for (var i=self._howls.length-1; i>=0; i--) { + self._howls[i].stereo(pan); + } + + return self; + }; + + /** + * Get/set the position of the listener in 3D cartesian space. Sounds using + * 3D position will be relative to the listener's position. + * @param {Number} x The x-position of the listener. + * @param {Number} y The y-position of the listener. + * @param {Number} z The z-position of the listener. + * @return {Howler/Array} Self or current listener position. + */ + HowlerGlobal.prototype.pos = function(x, y, z) { + var self = this; + + // Stop right here if not using Web Audio. + if (!self.ctx || !self.ctx.listener) { + return self; + } + + // Set the defaults for optional 'y' & 'z'. + y = (typeof y !== 'number') ? self._pos[1] : y; + z = (typeof z !== 'number') ? self._pos[2] : z; + + if (typeof x === 'number') { + self._pos = [x, y, z]; + self.ctx.listener.setPosition(self._pos[0], self._pos[1], self._pos[2]); + } else { + return self._pos; + } + + return self; + }; + + /** + * Get/set the direction the listener is pointing in the 3D cartesian space. + * A front and up vector must be provided. The front is the direction the + * face of the listener is pointing, and up is the direction the top of the + * listener is pointing. Thus, these values are expected to be at right angles + * from each other. + * @param {Number} x The x-orientation of the listener. + * @param {Number} y The y-orientation of the listener. + * @param {Number} z The z-orientation of the listener. + * @param {Number} xUp The x-orientation of the top of the listener. + * @param {Number} yUp The y-orientation of the top of the listener. + * @param {Number} zUp The z-orientation of the top of the listener. + * @return {Howler/Array} Returns self or the current orientation vectors. + */ + HowlerGlobal.prototype.orientation = function(x, y, z, xUp, yUp, zUp) { + var self = this; + + // Stop right here if not using Web Audio. + if (!self.ctx || !self.ctx.listener) { + return self; + } + + // Set the defaults for optional 'y' & 'z'. + var or = self._orientation; + y = (typeof y !== 'number') ? or[1] : y; + z = (typeof z !== 'number') ? or[2] : z; + xUp = (typeof xUp !== 'number') ? or[3] : xUp; + yUp = (typeof yUp !== 'number') ? or[4] : yUp; + zUp = (typeof zUp !== 'number') ? or[5] : zUp; + + if (typeof x === 'number') { + self._orientation = [x, y, z, xUp, yUp, zUp]; + self.ctx.listener.setOrientation(x, y, z, xUp, yUp, zUp); + } else { + return or; + } + + return self; + }; + + /** Group Methods **/ + /***************************************************************************/ + + /** + * Add new properties to the core init. + * @param {Function} _super Core init method. + * @return {Howl} + */ + Howl.prototype.init = (function(_super) { + return function(o) { + var self = this; + + // Setup user-defined default properties. + self._orientation = o.orientation || [1, 0, 0]; + self._stereo = o.stereo || null; + self._pos = o.pos || null; + self._pannerAttr = { + coneInnerAngle: typeof o.coneInnerAngle !== 'undefined' ? o.coneInnerAngle : 360, + coneOuterAngle: typeof o.coneOuterAngle !== 'undefined' ? o.coneOuterAngle : 360, + coneOuterGain: typeof o.coneOuterGain !== 'undefined' ? o.coneOuterGain : 0, + distanceModel: typeof o.distanceModel !== 'undefined' ? o.distanceModel : 'inverse', + maxDistance: typeof o.maxDistance !== 'undefined' ? o.maxDistance : 10000, + panningModel: typeof o.panningModel !== 'undefined' ? o.panningModel : 'HRTF', + refDistance: typeof o.refDistance !== 'undefined' ? o.refDistance : 1, + rolloffFactor: typeof o.rolloffFactor !== 'undefined' ? o.rolloffFactor : 1 + }; + + // Setup event listeners. + self._onstereo = o.onstereo ? [{fn: o.onstereo}] : []; + self._onpos = o.onpos ? [{fn: o.onpos}] : []; + self._onorientation = o.onorientation ? [{fn: o.onorientation}] : []; + + // Complete initilization with howler.js core's init function. + return _super.call(this, o); + }; + })(Howl.prototype.init); + + /** + * Get/set the stereo panning of the audio source for this sound or all in the group. + * @param {Number} pan A value of -1.0 is all the way left and 1.0 is all the way right. + * @param {Number} id (optional) The sound ID. If none is passed, all in group will be updated. + * @return {Howl/Number} Returns self or the current stereo panning value. + */ + Howl.prototype.stereo = function(pan, id) { + var self = this; + + // Stop right here if not using Web Audio. + if (!self._webAudio) { + return self; + } + + // If the sound hasn't loaded, add it to the load queue to change stereo pan when capable. + if (self._state !== 'loaded') { + self._queue.push({ + event: 'stereo', + action: function() { + self.stereo(pan, id); + } + }); + + return self; + } + + // Check for PannerStereoNode support and fallback to PannerNode if it doesn't exist. + var pannerType = (typeof Howler.ctx.createStereoPanner === 'undefined') ? 'spatial' : 'stereo'; + + // Setup the group's stereo panning if no ID is passed. + if (typeof id === 'undefined') { + // Return the group's stereo panning if no parameters are passed. + if (typeof pan === 'number') { + self._stereo = pan; + self._pos = [pan, 0, 0]; + } else { + return self._stereo; + } + } + + // Change the streo panning of one or all sounds in group. + var ids = self._getSoundIds(id); + for (var i=0; i Returns the group's values. + * pannerAttr(id) -> Returns the sound id's values. + * pannerAttr(o) -> Set's the values of all sounds in this Howl group. + * pannerAttr(o, id) -> Set's the values of passed sound id. + * + * Attributes: + * coneInnerAngle - (360 by default) There will be no volume reduction inside this angle. + * coneOuterAngle - (360 by default) The volume will be reduced to a constant value of + * `coneOuterGain` outside this angle. + * coneOuterGain - (0 by default) The amount of volume reduction outside of `coneOuterAngle`. + * distanceModel - ('inverse' by default) Determines algorithm to use to reduce volume as audio moves + * away from listener. Can be `linear`, `inverse` or `exponential`. + * maxDistance - (10000 by default) Volume won't reduce between source/listener beyond this distance. + * panningModel - ('HRTF' by default) Determines which spatialization algorithm is used to position audio. + * Can be `HRTF` or `equalpower`. + * refDistance - (1 by default) A reference distance for reducing volume as the source + * moves away from the listener. + * rolloffFactor - (1 by default) How quickly the volume reduces as source moves from listener. + * + * @return {Howl/Object} Returns self or current panner attributes. + */ + Howl.prototype.pannerAttr = function() { + var self = this; + var args = arguments; + var o, id, sound; + + // Stop right here if not using Web Audio. + if (!self._webAudio) { + return self; + } + + // Determine the values based on arguments. + if (args.length === 0) { + // Return the group's panner attribute values. + return self._pannerAttr; + } else if (args.length === 1) { + if (typeof args[0] === 'object') { + o = args[0]; + + // Set the grou's panner attribute values. + if (typeof id === 'undefined') { + self._pannerAttr = { + coneInnerAngle: typeof o.coneInnerAngle !== 'undefined' ? o.coneInnerAngle : self._coneInnerAngle, + coneOuterAngle: typeof o.coneOuterAngle !== 'undefined' ? o.coneOuterAngle : self._coneOuterAngle, + coneOuterGain: typeof o.coneOuterGain !== 'undefined' ? o.coneOuterGain : self._coneOuterGain, + distanceModel: typeof o.distanceModel !== 'undefined' ? o.distanceModel : self._distanceModel, + maxDistance: typeof o.maxDistance !== 'undefined' ? o.maxDistance : self._maxDistance, + panningModel: typeof o.panningModel !== 'undefined' ? o.panningModel : self._panningModel, + refDistance: typeof o.refDistance !== 'undefined' ? o.refDistance : self._refDistance, + rolloffFactor: typeof o.rolloffFactor !== 'undefined' ? o.rolloffFactor : self._rolloffFactor + }; + } + } else { + // Return this sound's panner attribute values. + sound = self._soundById(parseInt(args[0], 10)); + return sound ? sound._pannerAttr : self._pannerAttr; + } + } else if (args.length === 2) { + o = args[0]; + id = parseInt(args[1], 10); + } + + // Update the values of the specified sounds. + var ids = self._getSoundIds(id); + for (var i=0; i