frontend/js/katamari.js
2023-05-23 15:26:59 -04:00

1 line
11 KiB
JavaScript

var BORDER_STYLE="1px solid #bbb",CSS_TRANSFORM=null,CSS_TRANSFORM_ORIGIN=null,POSSIBLE_TRANSFORM_PREFIXES=["-webkit-","-moz-","-o-","-ms-",""],khFirst=!1;function getCssTransform(){var t,e,o=document.createElement("div");for(t=0;t<POSSIBLE_TRANSFORM_PREFIXES.length;t++)if(e=POSSIBLE_TRANSFORM_PREFIXES[t],o.style.setProperty(e+"transform","rotate(1rad) scaleX(2)",null),o.style.getPropertyValue(e+"transform")){CSS_TRANSFORM=e+"transform",CSS_TRANSFORM_ORIGIN=e+"transform-origin";return}throw alert("Your browser doesn't support CSS tranforms!"),"Your browser doesn't support CSS tranforms!"}function circleGridObjInt(t,e,o,n,i){var l,r;return t<i.left?(l=i.left-t,e<i.top)?l*l+(r=i.top-e)*r<=n:e<=i.bottom?l<=o:l*l+(r=e-i.bottom)*r<=n:t<=i.right?e<i.top?i.top-e<=o:e<=i.bottom||e-i.bottom<=o:(l=t-i.right,e<i.top)?l*l+(r=i.top-e)*r<=n:e<=i.bottom?l<=o:l*l+(r=e-i.bottom)*r<=n}function getClosestPoint(t,e,o){var n;return t<o.left?(n=o.left-t,e<o.top)?[o.left,o.top]:e<=o.bottom?[o.left,e]:[o.left,o.bottom]:t<=o.right?e<o.top?[t,o.top]:e<=o.bottom?[t,e]:[t,o.bottom]:(n=t-o.right,e<o.top)?[o.right,o.top]:e<=o.bottom?[o.right,e]:[o.right,o.bottom]}function gridObjVol(t){return t.w*t.h*Math.min(t.w,t.h)}function StickyNodes(){var t=[],e=[],o={a:1,b:1,big:1,body:1,cite:1,code:1,dd:1,div:1,dt:1,em:1,font:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,i:1,label:1,legend:1,li:1,p:1,pre:1,small:1,span:1,strong:1,sub:1,sup:1,td:1,th:1,tt:1};function n(e){null!=e&&(e.khIgnore=!0,e.style.border=BORDER_STYLE,t.push(e))}function i(t){var e;for(e=0;e<t.arrs.length;e++)t.arrs[e][t.idxs[e]]=void 0;t.el.style.visibility="hidden",t.el.khPicked=!0,delete t.arrs,delete t.idxs}this.addDomNode=n,this.addWords=function(t){var e=[];function i(t){return t.tagName&&o[t.tagName.toLowerCase()]}(function t(o,n){var l,r;if(n&&o.nodeType===Node.TEXT_NODE&&o.nodeValue.trim().length>0){e.push(o);return}if(o.childNodes&&!o.khIgnore)for(l=0,n=i(o),r=o.childNodes.length;l<r;l++)t(o.childNodes[l],n)})(t,i(t)),e.map(function t(e){var o,i,l=e.parentNode,r=e.nodeValue.split(/\s+/),s=e.nodeValue.split(/\S+/),a=Math.max(r.length,s.length);for(s.length>0&&0===s[0].length&&s.shift(),o=0;o<a;o++)o<r.length&&r[o].length>0&&((i=document.createElement("span")).innerHTML=r[o],l.insertBefore(i,e),n(i)),o<s.length&&s[o].length>0&&(i=document.createTextNode(s[o]),l.insertBefore(i,e));l.removeChild(e)})},this.addTagNames=function(t,e){var o,i,l,r,s=t.tagName&&t.tagName.toLowerCase();if(!t.khIgnore){if(-1!==e.indexOf(s)&&n(t),t.getElementsByTagName)for(o=0;o<e.length;o++)for(i=0,r=(l=t.getElementsByTagName(e[o])).length;i<r;i++)l[i].khIgnore||n(l[i])}},this.finalize=function(o,n){var i,l,r,s,a,c,d,$,f,h,p,u=Math.floor(o/100)+1,g=Math.floor(n/100)+1;for(i=0,e=Array(u);i<u;i++)e[i]=Array(g);for(r=0,s=t.length;r<s;r++)if(!(d=t[r]).khPicked)for(f=jQuery(d).offset(),h=jQuery(d).width(),p=jQuery(d).height(),a=Math.floor(($={el:t[r],left:f.left,right:f.left+h,top:f.top,bottom:f.top+p,w:h,h:p,x:f.left+h/2,y:f.top+p/2,diag:Math.sqrt((h*h+p*p)/4),arrs:[],idxs:[]}).left/100),c=Math.floor($.top/100),u=Math.floor(($.left+$.w)/100)+1,g=Math.floor(($.top+$.h)/100)+1,i=a;i<u;i++)for(l=c;l<g;l++)void 0===e[i]&&(e[i]=[]),void 0===e[i][l]?e[i][l]=[$]:e[i][l].push($),$.arrs.push(e[i][l]),$.idxs.push(e[i][l].length-1)},this.removeIntersecting=function(t,o,n,l){var r,s,a,c,d,$=n*n,f=Math.floor((o-n)/100),h=Math.floor((t+n)/100)+1,p=Math.floor((o+n)/100)+1;for(r=Math.floor((t-n)/100);r<h;r++)if(void 0!==e[r]){for(s=f;s<p;s++)if(void 0!==(a=e[r][s]))for(c=0;c<a.length;c++)void 0!==(d=a[c])&&circleGridObjInt(t,o,n,$,d)&&l(d)&&i(d)}}}function PlayerBall(t,e,o,n){var i,l,r,s=300,a=300,c=0,d=0,$=20,f=0,h=1e4,p=1e4,u=[],g=o.color,_=0,b=0,m=!1,v=o.VOL_MULT,y=o.MAX_ATTACHED_VISIBLE,k=o.CHECK_VOLS,S=0,x=0;function T(){return 4*Math.PI*$*$*$/3}function E(t){var e,o,l,r,c,d,f,h,p,g,_,b,m,y,E;return!(k&&gridObjVol(t)>T())&&(l=(o=getClosestPoint(s,a,e=t))[0]-s,c=Math.sqrt(l*l+(r=o[1]-a)*r),d=0-S,f=o[0]-e.left,h=o[1]-e.top,g=c*Math.cos(p=Math.atan2(r,l)-S),_=c*Math.sin(p),b=e.el.cloneNode(!0),m=jQuery(e.el),y={el:b,attX:g,attY:_,attT:"translate("+Math.round(g)+"px,"+Math.round(_)+"px) rotate("+d+"rad)",r:c,offTh:p,offPhi:0-x,diag:e.diag,removeR:c+e.diag,visible:!1,display:m.css("display")},u.push(y),E=e,$=Math.pow(3*(T()+gridObjVol(E)*v)/(4*Math.PI),1/3),b.style.position="absolute",b.style.left=-f+"px",b.style.top=-h+"px",b.style.setProperty(CSS_TRANSFORM_ORIGIN,f+"px "+h+"px",null),b.style.display="none",b.style.color=m.css("color"),b.style.textDecoration=m.css("text-decoration"),b.style.fontSize=m.css("font-size"),b.style.fontWeight=m.css("font-weight"),b.khIgnore=!0,i.appendChild(b),n&&n.play_pop(),!0)}function I(t){var e=S+t.offTh,o=x+t.offPhi,n=t.r*Math.cos(e),i=t.r*Math.sin(e),l=t.r*Math.cos(S-t.offTh+Math.PI)-n,r=t.r*Math.sin(S-t.offTh+Math.PI)-i,c=(-Math.cos(o)+1)/2,d=n+c*l,f=i+c*r,h=t.r*Math.sin(o);return h<0&&Math.sqrt(d*d+f*f)+t.diag<$?(t.visible&&(t.visible=!1,t.el.style.display="none"),!1):(t.visible||(t.visible=!0,t.el.style.display=t.display),t.el.style.zIndex=h>0?501:499,t.el.style.setProperty(CSS_TRANSFORM,"translate("+s+"px,"+a+"px) rotate("+S+"rad) scaleX("+Math.cos(o)+") "+t.attT,null),!0)}function P(t){i.removeChild(t.el),delete t.el}this.init=function(){(l=document.createElement("canvas")).width=2*$,l.height=2*$,l.style.cssText="position: absolute; z-index: 500;",t.appendChild(l),r=l.getContext("2d"),i=document.createElement("div"),t.appendChild(i)},this.setRadius=function(t){$=t},this.getState=function(){return{x:s,y:a,vx:c,vy:d,radius:$,th:S,phi:x}},this.setState=function(t){s=t.x,a=t.y,c=t.vx,d=t.vy,$=t.radius,S=t.th,x=t.phi},this.setXY=function(t,e){s=t,a=e},this.setTh=function(t){S=t},this.setPhi=function(t){x=t},this.setColor=function(t){g=t},this.setDocSize=function(t,e){h=t,p=e},this.setAccel=function(t){m=t},this.setAccelTarget=function(t,e){_=t,b=e},this.updatePhysics=function(){var t,o,i,l=s,r=a,f=!1;m?(c+=.5*Math.cos(i=Math.atan2(b-a,_-s)),d+=.5*Math.sin(i)):(c*=.95,d*=.95),s+=c,a+=d,s-$<0?(f=!0,s=$+1,c=-c):s+$>h&&(f=!0,s=h-$-1,c=-c),a-$<0?(f=!0,a=$+1,d=-d):a+$>p&&(f=!0,a=p-$-1,d=-d),(0!==c||0!==d)&&(S=Math.atan2(d,c),x-=Math.sqrt((t=s-l)*t+(o=a-r)*o)/$),e.removeIntersecting(s,a,$,E),this.draw(),f&&n&&n.play_bounce()},this.draw=function(){var t,e,o=0;for(!function t(){var e,o,n,i,c,d,h,p,u,_,b;for(l.style.left=s-$+"px",l.style.top=a-$+"px",$!=f&&(l.width=2*$+1,l.height=2*$+1,f=$),r.clearRect(0,0,2*$,2*$),r.fillStyle="#fff",r.beginPath(),r.arc($,$,$-1,0,2*Math.PI,!0),r.fill(),r.strokeStyle=g,r.beginPath(),r.arc($,$,$-1,0,2*Math.PI,!0),r.stroke(),r.fillStyle=g,e=$+$*Math.cos(S+Math.PI/16),o=$+$*Math.sin(S+Math.PI/16),n=$+$*Math.cos(S-Math.PI/16),i=$+$*Math.sin(S-Math.PI/16),c=$+$*Math.cos(S+15*Math.PI/16)-e,d=$+$*Math.sin(S+15*Math.PI/16)-o,h=0;h<2*Math.PI;h+=Math.PI/7)p=(-Math.cos(x+h)+1)/2,u=(-Math.cos(x+h+Math.PI/32)+1)/2,_=Math.sin(x+h),b=Math.sin(x+h+Math.PI/32),_>0&&b>0&&(r.beginPath(),r.moveTo(e+p*c,o+p*d),r.lineTo(e+u*c,o+u*d),r.lineTo(n+u*c,i+u*d),r.lineTo(n+p*c,i+p*d),r.fill())}(),t=u.length;--t>=0;)if((e=u[t]).removeR<$)u.splice(t,1).map(P);else if(I(e)&&++o>y){u.splice(0,t).map(P);break}}}function preventDefault(t){return t.preventDefault(),t.returnValue=!1,!1}function Game(t,e,o){var e,n,i,l;function r(){n.setDocSize(jQuery(document).width()-5,jQuery(document).height()-5)}(n=new PlayerBall(t,e,o,!1)).init(),n.setXY(300,300),window.scrollTo(0,200),r(),document.addEventListener("touchstart",function(t){if(1===t.touches.length)return n.setAccel(!0),preventDefault(t)},!0),document.addEventListener("touchmove",function(t){n.setAccelTarget(t.touches[0].pageX,t.touches[0].pageY)},!0),document.addEventListener("touchend",function(t){if(0===t.touches.length)return n.setAccel(!1),preventDefault(t)},!0),-5!==o.MOUSEB&&(document.addEventListener("mousemove",function(t){n.setAccelTarget(t.pageX,t.pageY)},!0),document.addEventListener("mousedown",function(t){if(t.button===o.MOUSEB)return n.setAccel(!0),preventDefault(t)},!0),document.addEventListener("mouseup",function(t){if(t.button===o.MOUSEB)return n.setAccel(!1),preventDefault(t)},!0),0===o.MOUSEB?document.addEventListener("click",function(t){if(0===t.button)return preventDefault(t)},!0):2===o.MOUSEB&&document.addEventListener("contextmenu",preventDefault,!0)),i=setInterval(function(){n.updatePhysics()},25),l=setInterval(r,1e3)}function whenAllLoaded(t,e,o){o.finalize(jQuery(document).width(),jQuery(document).height()),jQuery("#loadingp").empty(),jQuery("<button>Start!</button>").click(function(){var n,i,l;jQuery("#bgmusicc").attr("checked")&&((i=document.getElementById("khbgmusic"))||((i=document.createElement("audio")).id="khbgmusic",i.loop="loop",i.src="http://kathack.com/js/katamari.mp3",t.appendChild(i)),i.play()),l={color:jQuery("#khcolor").val(),VOL_MULT:parseFloat(jQuery("#vol_mult").val()),MAX_ATTACHED_VISIBLE:parseInt(jQuery("#maxAtt").val(),10),CHECK_VOLS:!!jQuery("#checkv").attr("checked"),MOUSEB:parseInt(jQuery("#mouseb").val(),10)},t.removeChild(e),n=new Game(t,o,l)}).appendTo("#loadingp")}function buildPopup(t){var e=document.createElement("div");return e.style.cssText="position: fixed;left: 50%;top: 50%;width: 400px;margin-left:-200px;margin-top:-150px;border:1px solid black;background-color:white;color:black;padding:20px;font-size:13px;text-align:left;z-index:501;",e.innerHTML='<h1 style="font-size:16pt"><a href="http://kathack.com/" style="color:blue;text-decoration:none;">Katamari!</a></h1><button style="position:absolute;top:0;right:0;">X</button><p>Controls: Hold down <b><select id="mouseb"><option value="0">Left-Click</option><option value="2" selected="selected">Right-Click</option><option value="-5">Touch</option></select></b> to control the ball!</p><div><label>Background Music? <input id="bgmusicc" type="checkbox" checked="checked" /></label></div><div style="text-align:right; color:gray;"><label>Katamari Color: <select id="khcolor"><option value="#ff0000" style="background-color:#ff0000;color:#ff0000"> r </option><option value="#00ff00" style="background-color:#00ff00;color:#00ff00"> g </option><option value="#0000ff" style="background-color:#0000ff;color:#0000ff"> b </option><option selected="selected" value="#7D26CD" style="background-color:#7D26CD;color:#7D26CD"> p </option></select></label><br /> <label title="Lower this if the game gets slow.">Max Attached Objects: <select id="maxAtt"><option>25</option><option>50</option><option selected="selected">75</option><option>100</option><option>9000</option></select></label><br /><label title="How much to grow when an object is picked up.">Growth Speed: <input id="vol_mult" type="text" size="6" value="1.0" /></label><br /><label title="Bigger objects require a bigger katamari to pick up.">Realistic Pickups? <input id="checkv" type="checkbox" checked="checked" /></label></div><p id="loadingp">Loading!</p>',t.appendChild(e),e.getElementsByTagName("button")[0].addEventListener("click",function(){t.removeChild(e)},!0),e}function main(){var t,e,o;(t=document.createElement("div")).khIgnore=!0,document.body.appendChild(t),o=buildPopup(t),setTimeout(function(){var n,i,l;for(window.khNodes.addWords(document.body),n=0,i=document.body.childNodes.length;n<i;n++)l=document.body.childNodes[n],window.khNodes.addTagNames(l,["button","canvas","iframe","img","input","select","textarea"]);e=setInterval(function(){window.jQuery&&(clearInterval(e),whenAllLoaded(t,o,window.khNodes))},100)},0)}window.khNodes||(khFirst=!0,window.khNodes=new StickyNodes),getCssTransform(),window.noMain||main();