-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasketball.html
More file actions
1 lines (1 loc) · 26.3 KB
/
Copy pathbasketball.html
File metadata and controls
1 lines (1 loc) · 26.3 KB
1
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Retro Games: Basketball by ideaMarcos</title><style>*{margin:0;padding:0;box-sizing:border-box}body{background:#050010;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;font-family:'Courier New',monospace}#wrapper{position:fixed;inset:0}canvas{display:block;image-rendering:pixelated;image-rendering:crisp-edges;width:100vw;height:100vh}#wrapper::after{content:'';position:absolute;inset:0;background:repeating-linear-gradient(to bottom,transparent 0,transparent 3px,rgba(0,0,0,.15) 3px,rgba(0,0,0,.15) 4px);pointer-events:none}#controls{position:absolute;bottom:8px;width:100%;color:#555;font-size:11px;letter-spacing:1px;text-align:center}#controls b{color:#888}</style></head><body><div id="wrapper"><canvas id="c"></canvas></div><script>!function(){"use strict";const t=document.getElementById("c"),e=t.getContext("2d");e.imageSmoothingEnabled=!1;const n=380,l=420;let o=1,i=1;function a(){t.width=window.innerWidth,t.height=window.innerHeight,o=t.width/n,i=t.height/l}a(),window.addEventListener("resize",a);const s={bg:"#06000f",crowd:["#1a0040","#220055","#2a006a","#15002e"],crowdHead:"#3d0080",courtBase:"#5a2e08",courtMid:"#6b380c",courtHi:"#7a4210",courtSide:"#3e1e04",lane:"#8a5218",laneLine:"#d4881c",threeArc:"#d4881c",ftLine:"#d4881c",center:"#d4881c",backboard:"#ccccbb",bbEdge:"#666655",rim:"#ff3300",rimShad:"#991100",net:"#cccccc",p1Skin:"#6a2808",p1Jersey:"#cc0000",p1Shorts:"#880000",p1Shoe:"#1122bb",p2Skin:"#c07842",p2Jersey:"#006633",p2Shorts:"#004422",p2Shoe:"#eeeeee",headband:"#ffffff",ball:"#e05515",ballHi:"#f07030",ballSeam:"#701a00",ballShadow:"rgba(0,0,0,0.55)",score:"#ffee00",scoreBdr:"#ff8800",scoreBg:"#0a0018",white:"#ffffff",mGood:"#00ee44",mMid:"#ffcc00",mHot:"#ff1100"},r=["#ffd5a8","#f0b87a","#c07842","#8b5e2e","#6a3e1a","#3d1e0a"],c=["#cc0000","#006633","#0033cc","#cc6600","#660099","#007777","#aa0044","#2244aa","#888800"],f=["#111111","#1122bb","#eeeeee","#cc2200","#225500","#884400"];function h(t,e){const n=parseInt(t.slice(1,3),16),l=parseInt(t.slice(3,5),16),o=parseInt(t.slice(5,7),16),i=t=>Math.round(t*e).toString(16).padStart(2,"0");return"#"+i(n)+i(l)+i(o)}!function(){const t=t=>t[Math.floor(Math.random()*t.length)];s.p1Skin=t(r),s.p1Shoe=t(f),s.p2Skin=t(r),s.p2Shoe=t(f);const e=Math.floor(Math.random()*c.length);let n;s.p1Jersey=c[e],s.p1Shorts=h(s.p1Jersey,.6);do{n=Math.floor(Math.random()*c.length)}while(n===e);s.p2Jersey=c[n],s.p2Shorts=h(s.p2Jersey,.6)}();const y=190,d=130,u=440,x=n,p=y,g=14,m=140,b=d,T=280,M=210,S=280,v=.45;function P(t,e){const n=Math.max(0,Math.min(1,(e-d)/310));return y+(t-y)*(1+n*v)}function w(t){return 1+Math.max(0,Math.min(1,(t-d)/310))*v*.5}const k=16.667,A={},E={};addEventListener("keydown",t=>{B||(A[t.key]=!0,t.preventDefault())}),addEventListener("keyup",t=>{A[t.key]=!1});const I=t=>A[t]&&!E[t];let R={up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight",shoot:"Shift",fullscreen:"f"},j={up:null,down:null,left:null,right:null,shoot:null,fullscreen:null},L={up:"w",down:"s",left:"a",right:"d",shoot:"z",fullscreen:"f"},H={up:null,down:null,left:null,right:null,shoot:null,fullscreen:null},W=!1,B=null,D=null,O=1,C=null;const Y=["up","down","left","right","shoot","fullscreen"],X={up:"UP",down:"DOWN",left:"LEFT",right:"RIGHT",shoot:"SHOOT",fullscreen:"FULLSCR"},F=210,G=240,J=302,q=158,$=208;function U(t){return{ArrowUp:"UP ARROW",ArrowDown:"DOWN ARROW",ArrowLeft:"LEFT ARROW",ArrowRight:"RIGHT ARROW"," ":"SPACE",Escape:"ESC",Enter:"ENTER",Shift:"SHIFT",Control:"CTRL",Alt:"ALT",Tab:"TAB",Backspace:"BKSP",CapsLock:"CAPS"}[t]||(1===t.length?t.toUpperCase():t)}function N(t){return t?"btn"===t.type?"BTN "+t.i:"AX"+t.i+":"+t.value.toFixed(2):"—"}document.addEventListener("keydown",t=>{B&&"kb"===D&&(t.preventDefault(),t.stopPropagation(),"Escape"!==t.key&&(2===O?L[B]=t.key:(R[B]=t.key,"fullscreen"===B&&(L.fullscreen=t.key))),B=null,D=null)},!0);t.addEventListener("click",e=>{if(!Kt)return;const o=t.getBoundingClientRect(),i=(e.clientX-o.left)*(n/o.width),a=(e.clientY-o.top)*(l/o.height);if(a>=156&&a<=172){if(i>=92&&i<=172)return W=!1,void(B=null);if(i>=$&&i<=288)return W=!0,void(B=null)}const s=t=>{C=null;for(const e of navigator.getGamepads())if(e&&e.connected&&(t<0||e.index===t))return void(C=Array.from(e.axes));for(const t of navigator.getGamepads())if(t&&t.connected)return void(C=Array.from(t.axes))};Y.forEach((t,e)=>{const n=F+20*e;if(a<n-12||a>n+6)return;const l=W?52:95,o=W?114:218;i>=l&&i<=l+(W?58:114)?B===t&&"kb"===D&&1===O?(B=null,D=null):(B=t,D="kb",O=1):"fullscreen"!==t&&i>=o&&i<=o+(W?58:114)&&(B===t&&"gp"===D&&1===O?(B=null,D=null,C=null):(B=t,D="gp",O=1,s(K))),W&&"fullscreen"!==t&&(i>=G&&i<=298?B===t&&"kb"===D&&2===O?(B=null,D=null):(B=t,D="kb",O=2):i>=J&&i<=362&&(B===t&&"gp"===D&&2===O?(B=null,D=null,C=null):(B=t,D="gp",O=2,s(z))))})});let K=-1,z=-1,V=!1,_=!1;function Q(t){if(t<0)return null;const e=navigator.getGamepads()[t];return e&&e.connected?e:null}window.addEventListener("gamepadconnected",t=>{K<0?K=t.gamepad.index:W&&z<0&&t.gamepad.index!==K&&(z=t.gamepad.index)}),window.addEventListener("gamepaddisconnected",t=>{t.gamepad.index===K&&(K=-1),t.gamepad.index===z&&(z=-1)});let Z=!1;document.addEventListener("visibilitychange",()=>{Z=document.hidden}),window.addEventListener("blur",()=>{Z=!0}),window.addEventListener("focus",()=>{Z=!1});class tt{constructor(t,e,n,l){this.id=t,this.isAI=l,this.reset(e,n)}reset(t,e){this.x=t,this.y=e,this.vx=0,this.vy=0,this.facing=0,this.hasBall=!1,this.jumpT=0,this.jumpH=0,this.state="idle",this.anim=0,this.aiT=0,this.aiMode="defend",this.aiShouldShoot=!1,this.aiOpenDrive=!1,this.aiOpenLane=!1,this.aiDecideT=0,this.aiTargetX=0,this.aiTargetY=0,this.aiHesitateT=0,this.debugProbes=[]}}let et,nt,lt,ot,it,at,st,rt,ct,ft={x:y,y:300,h:0,vx:0,vy:0,vh:0,state:"held",rot:0,trail:[],shooterId:0},ht=-1,yt=-1,dt=!1,ut=null;const xt=14;let pt,gt;function mt(t){const e=y+(Math.random()<.5?-1:1),n=0===t?pt:gt,l=0===t?gt:pt;n.reset(e,400),l.reset(y,345),n.hasBall=!0,ft.x=n.x,ft.y=n.y,ft.h=0,ft.state="held",ft.trail=[],nt=5,lt=0}function bt(){et=[0,0],ot=0,it="playing",at=0,st=0,rt="",ct=0,pt=new tt(0,0,0,!1),gt=new tt(1,0,0,!W),mt(0)}const Tt=6.4;function Mt(t,e,n=2.2,l=7){const o=105-1.85*t,i=Math.min(e,2.2)-n,a=Math.sign(i)*Math.pow(Math.abs(i),2)*l;return Math.max(5,o+a)}function St(t){const e=0===t?pt:gt,n=0===t?gt:pt,l=Math.hypot(e.x-p,e.y-m)/Tt,o=Math.hypot(n.x-p,n.y-m),i=Math.max(0,Math.hypot(e.x-n.x,e.y-n.y)-2*It),a=o<l*Tt?i/Tt:8,s=Math.max(5,Mt(l,a));ut={pct:Math.round(s)},ft.willScore=Math.random()<s/100;const r=Math.hypot(p-e.x,90-e.y)||1,c=e.x+(p-e.x)/r*14,f=e.y+(90-e.y)/r*14;ft.x=c,ft.y=f,ft.h=0,ft.tx=190,ft.ty=90,ft.t=0,ft.flightT=52,ft.sx=c,ft.sy=f,ft.screenSX=P(c,f),ft.screenSY=f-e.jumpH-10,ft.screenEX=y,ft.screenEY=Ot+4+Ct/2;const h=Math.abs(ft.screenSY-ft.screenEY);ft.arcHeight=.6*h+80,ft.shooterId=t,ft.state="fly",ft.trail=[],ft.dribbleT=0,e.hasBall=!1,e.state="idle",ot=-1}function vt(t){ot=t,it="playing",st=0,ut=null,mt(t)}function Pt(t,e,n,l,o,i){if("playing"!==it)return;let a=0,s=0;A[l.left]&&(a-=1),A[l.right]&&(a+=1),A[l.up]&&(s-=1),A[l.down]&&(s+=1);const r=Q(i);let c=0,f=0;if(r){const t=.2,e=r.axes[0],n=r.axes[1];Math.abs(e)>t&&(c+=e),Math.abs(n)>t&&(f+=n);const l=t=>!!t&&("btn"===t.type?!!r.buttons[t.i]?.pressed:void 0!==r.axes[t.i]&&Math.abs(r.axes[t.i]-t.value)<.35);l(o.left)&&(c-=1),l(o.right)&&(c+=1),l(o.up)&&(f-=1),l(o.down)&&(f+=1),a+=c,s+=f}0===n&&(window._dbgGP={mx:c,my:f});const h=r&&null!==o.shoot&&(()=>{const t=o.shoot;return"btn"===t.type?!!r.buttons[t.i]?.pressed:void 0!==r.axes[t.i]&&Math.abs(r.axes[t.i]-t.value)<.35})();0===n?V&&!h&&(V=!1):_&&!h&&(_=!1);const y=0===n?V:_;if(0!==a||0!==s){const t=Math.sqrt(a*a+s*s);e.vx=a/t*1,e.vy=s/t*1,e.facing=Math.atan2(s,a),e.state="run"}else e.vx*=.65,e.vy*=.65,Math.abs(e.vx)<.1&&Math.abs(e.vy)<.1&&(e.vx=e.vy=0,e.state="idle");if(e.jumpT>0&&(e.vx=0,e.vy=0,e.jumpT+=t,e.jumpH=12*Math.sin(Math.PI*Math.min(e.jumpT,xt)/xt),e.jumpT>=7&&e.jumpT-t<7&&St(n),e.jumpT>=xt&&(e.jumpT=0,e.jumpH=0)),e.hasBall&&0===e.jumpT){const t=!y&&h;(I(l.shoot)||t)&&(e.jumpT=.01,e.state="shoot")}}function wt(t,e,n,l){return Mt(Math.hypot(t-p,e-m)/Tt,Math.max(0,Math.hypot(t-n,e-l)-2*It)/Tt)}const kt=[[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1]].map(([t,e])=>{const n=Math.hypot(t,e);return[t/n,e/n]});function At(t){if("playing"!==it)return;const e=gt,n=pt;if(e.aiT+=t,e.jumpT>0)return e.vx=0,e.vy=0,e.jumpT+=t,e.jumpH=12*Math.sin(Math.PI*Math.min(e.jumpT,xt)/xt),e.jumpT>=7&&e.jumpT-t<7&&St(1),void(e.jumpT>=xt&&(e.jumpT=0,e.jumpH=0));if(1===ot)if(e.hasBall=!0,nt<=1&&0===e.jumpT)e.vx=0,e.vy=0,e.jumpT=.01,e.state="shoot";else if(e.aiOpenLane=!function(t=55){const e=p-gt.x,n=m-gt.y,l=pt.x-gt.x,o=pt.y-gt.y,i=e*e+n*n,a=i>0?(l*e+o*n)/i:0,s=l-a*e,r=o-a*n;return a>.05&&a<1.1&&Math.hypot(s,r)<t}(e.aiOpenLane?35:55)){const t=p-e.x,n=m-e.y,l=Math.hypot(t,n);l<g&&0===e.jumpT?(e.vx=0,e.vy=0,e.jumpT=.01,e.state="shoot"):(e.vx=t/l*1,e.vy=n/l*1,e.facing=Math.atan2(n,t),e.state="run")}else{if(function(t,e,n,l){const o=Math.hypot(t-p,e-m)/Tt,i=Math.hypot(n-p,l-m),a=Math.max(0,Math.hypot(t-n,e-l)-2*It);return Mt(o,i<o*Tt?a/Tt:8)}(e.x,e.y,pt.x,pt.y)>=(Math.hypot(e.x-p,e.y-m)>M?42:70)&&0===e.jumpT)e.vx=0,e.vy=0,e.jumpT=.01,e.state="shoot",e.aiDecideT=0;else{e.aiDecideT-=t;const n=Math.hypot(e.aiTargetX-e.x,e.aiTargetY-e.y)<12;if(e.aiDecideT<=0&&(n||e.aiDecideT<-30)){e.aiDecideT=30;let t=0,n=0,l=1/0,o=-1,i=0,a=0,s=-1,r=0,c=0;const f=Math.sign(e.x-pt.x),h=Math.sign(e.y-pt.y),y=0!==f&&0!==h?[[f,0],[0,h],[2*f,0],[0,2*h],[f,h]]:0!==f?[[0,-1],[0,1],[0,-2],[0,2],[f,0]]:0!==h?[[-1,0],[1,0],[-2,0],[2,0],[0,h]]:[],d=dt?[]:null;for(const[f,h]of[...kt,...y]){const y=e.x+50*f,g=e.y+50*h;if(g<138||g>u||y<0||y>x){d?.push({ddx:f,ddy:h,skip:!0});continue}const b=Math.hypot(y-pt.x,g-pt.y);if(b<2*It){d?.push({ddx:f,ddy:h,skip:!0});continue}const T=wt(y,g,pt.x,pt.y);if(b>=Rt){const e=Math.hypot(y-p,g-m),s=e>M;s&&T>=42?e<l&&(l=e,t=f,n=h):!s&&T>o&&(o=T,i=f,a=h)}T>s&&(s=T,r=f,c=h),d?.push({fg:T,ddx:f,ddy:h})}let g,b;if(l<1/0)g=t,b=n;else if(o>-1)g=i,b=a;else if(s>-1)g=r,b=c;else{const t=p-e.x,n=m-e.y,l=Math.hypot(t,n)||1;g=t/l,b=n/l}if(e.aiTargetX=e.x+50*g,e.aiTargetY=e.y+50*b,d){for(const t of d)t.skip||t.ddx!==g||t.ddy!==b||(t.chosen=!0);e.debugProbes=d}e.aiHesitateT=Math.random()<.01?10:0}const l=e.aiTargetX-e.x,o=e.aiTargetY-e.y,i=Math.hypot(l,o);e.aiHesitateT>0?(e.vx=i>0?-l/i*1:0,e.vy=i>0?-o/i*1:0,e.aiHesitateT-=Math.hypot(e.vx,e.vy),e.facing=Math.atan2(-o,-l),e.state="run"):i>1?(e.vx=l/i*1,e.vy=o/i*1,e.facing=Math.atan2(o,l),e.state="run"):(e.vx=0,e.vy=0,e.state="idle")}}else if(0===ot){const t=n.x+.5*(p-n.x),l=n.y+.5*(m-n.y),o=t-e.x,i=l-e.y,a=Math.hypot(o,i);a>18?(e.vx=o/a*1,e.vy=i/a*1,e.facing=Math.atan2(i,o),e.state="run"):(e.vx=0,e.vy=0,e.state="idle")}else{const t=ft.x-e.x,n=ft.y-e.y,l=Math.hypot(t,n);l>20?(e.vx=t/l*1,e.vy=n/l*1,e.state="run"):(e.vx=0,e.vy=0)}}function Et(t,e){if(e){const n=e.x-t.x,l=e.y-t.y,o=Math.hypot(n,l);if(o<2*It&&o>0){const e=n/o,i=l/o,a=t.vx*e+t.vy*i;a>0&&(t.vx-=a*e,t.vy-=a*i)}}t.x+=t.vx,t.y+=t.vy;const l=Math.max(0,Math.min(1,(t.y-d)/310)),o=1+v*l,i=It+2,a=y+(i-y)/o,s=y+(n-i-y)/o;t.x=Math.max(a,Math.min(s,t.x)),t.y=Math.max(138,Math.min(400,t.y)),t.anim++}const It=14,Rt=2.2*Tt+2*It;function jt(){const t=0===ot?pt:1===ot?gt:null;if("held"===ft.state&&t){const e=(0===t.id?gt:pt).x<t.x?1:-1;if(ft.x=t.x+12*e,ft.y=t.y,t.jumpT>0){const e=Math.hypot(p-t.x,90-t.y)||1;ft.x=t.x+(p-t.x)/e*14,ft.y=t.y+(90-t.y)/e*14,ft.h=t.jumpH+10,ft.dribbleT=0}else ft.dribbleT=(ft.dribbleT||0)+.12,ft.h=8*Math.abs(Math.sin(ft.dribbleT));return}if("held"!==ft.state){if("fly"===ft.state){ft.trail.push({x:ft.screenX,y:ft.screenY,isScreen:!0}),ft.trail.length>10&&ft.trail.shift(),ft.t+=1/ft.flightT;const t=Math.min(ft.t,1);ft.x=ft.sx+(ft.tx-ft.sx)*t,ft.y=ft.sy+(ft.ty-ft.sy)*t,ft.screenX=ft.screenSX+(ft.screenEX-ft.screenSX)*t;const e=ft.screenSY+(ft.screenEY-ft.screenSY)*t;if(ft.screenY=e-4*ft.arcHeight*t*(1-t),ft.h=0,ft.rot+=.15,ft.ascending=t<.45,t>=.96){if(ft.willScore)return void function(t){const e=0===t?pt:gt,n=e.x-p,l=e.y-m,o=n*n+l*l>44100?3:2;et[t]+=o,ct=t,rt=(0===t?"P1":"P2")+` +${o}!`,st=90,nt=5,lt=0,ft.state="net",ft.netT=0,ft.screenX=y,ft.screenY=Ot+4+Ct/2,ht=0,ft.vx=0,ft.vy=0,ft.h=0,et[t]>=21?(it="gameover",at=0):(it="scored",at=12)}(ft.shooterId);{ft.state="oob",yt=0,ht=0,ft.oobStart={x:p,y:Ot};const t=(0===ft.shooterId?pt:gt).x>=p?0:x,e=(p+t)/2,o=(Ot+d)/2;ft.oobMid={x:e,y:o};const i=t-p,a=d-Ot,s=Math.hypot(i,a),r=Math.max(n,l)/s;ft.oobEnd={x:t+i/s*(s*r),y:d+a/s*(s*r)},ft.oobT=0,ft.oobDur=ft.flightT,ft.screenX=y,ft.screenY=Ot,ft.h=0,ft.trail=[]}}return}if("net"===ft.state){ft.netT++;const t=Ot+4+Ct,e=12;if(ft.screenX=y,ft.netT<=e)ft.screenY=t;else{const n=ft.netT-e;if(ft.screenY=t+1.5*n,n>30)return}return}if("oob"===ft.state){ft.oobT++;const t=Math.min(ft.oobT/ft.oobDur,1),e=ft.oobMid.x-ft.oobStart.x,n=ft.oobMid.y-ft.oobStart.y;let l=0,o=.5,i=1,a=.4*Math.hypot(e,n),s=0;for(;l+o<t&&o>.01;)s+=i,l+=o,o*=.5,i*=.5,a*=.5;const r=(t-l)/o;s+=i*r,ft.x=ft.oobStart.x+e*s,ft.y=ft.oobStart.y+n*s,ft.screenX=P(ft.x,ft.y);const c=.4,f=r<=c?r/c*(2-r/c):1-(r-c)/(1-c)*((r-c)/(1-c));if(ft.screenY=ft.y-a*Math.max(0,f),ft.rot+=.15,ft.oobT>=ft.oobDur){vt(0===ft.shooterId?1:0)}return}if("loose"===ft.state){if(ft.x+=ft.vx,ft.y+=ft.vy,ft.vx*=.96,ft.vy*=.96,ft.rot+=.05*ft.vx,ft.x<0||ft.x>x||ft.y<d||ft.y>u)return ft.state="oob",void(ft.oobT=180);const t=t=>{if(Math.abs(t.x-ft.x)<22&&Math.abs(t.y-ft.y)<22){const e=t.id;ot=e,t.hasBall=!0,ft.state="held",ft.trail=[],nt=5,lt=0}};if(t(pt),t(gt),Math.abs(ft.vx)<.1&&Math.abs(ft.vy)<.1){vt(Math.hypot(pt.x-ft.x,pt.y-ft.y)<Math.hypot(gt.x-ft.x,gt.y-ft.y)?0:1)}}}}function Lt(t,n,l,o,i){e.fillStyle=i,e.fillRect(~~t,~~n,l,o)}let Ht=null;function Wt(){if(!Ht){Ht=document.createElement("canvas"),Ht.width=n,Ht.height=l;const t=Ht.getContext("2d");t.fillStyle=s.crowd[0],t.fillRect(0,0,n,d);const e=Math.floor(d/28);for(let l=0;l<e;l++){t.fillStyle=s.crowd[l%s.crowd.length],t.fillRect(0,28*l,n,22);for(let e=0;e<32;e++){const n=16*e+l%2*8+2,o=28*l+3;t.fillStyle=s.crowdHead,t.fillRect(n,o,9,8),t.fillStyle=s.crowd[(l+1)%s.crowd.length],t.fillRect(n+1,o+8,7,12)}}t.fillStyle=s.crowd[1],t.beginPath(),t.moveTo(0,d),t.lineTo(P(0,d),d),t.lineTo(P(0,u),u),t.lineTo(0,u),t.closePath(),t.fill(),t.beginPath(),t.moveTo(P(x,d),d),t.lineTo(n,d),t.lineTo(n,u),t.lineTo(P(x,u),u),t.closePath(),t.fill(),t.beginPath(),t.moveTo(P(0,u),u),t.lineTo(P(x,u),u),t.lineTo(n,l),t.lineTo(0,l),t.closePath(),t.fillStyle=s.courtSide,t.fill()}e.drawImage(Ht,0,0)}function Bt(t,n,l,o,i,a){e.beginPath();for(let s=0;s<=a;s++){const r=o+s/a*(i-o),c=t+Math.cos(r)*l,f=n+Math.sin(r)*l,h=P(c,f);0===s?e.moveTo(h,f):e.lineTo(h,f)}e.stroke()}function Dt(){e.save(),e.beginPath(),e.moveTo(P(0,d),d),e.lineTo(P(x,d),d),e.lineTo(P(x,u),u),e.lineTo(P(0,u),u),e.closePath(),e.clip(),Lt(0,d,n,310,s.courtBase),e.restore(),e.strokeStyle=s.laneLine,e.lineWidth=2,e.beginPath(),e.moveTo(P(0,d),d),e.lineTo(P(x,d),d),e.lineTo(P(x,u),u),e.lineTo(P(0,u),u),e.closePath(),e.stroke(),e.beginPath(),e.moveTo(P(145,b),b),e.lineTo(P(235,b),b),e.lineTo(P(235,T),T),e.lineTo(P(145,T),T),e.closePath(),e.fillStyle=s.lane,e.fill(),e.strokeStyle=s.laneLine,e.lineWidth=2,e.stroke(),e.strokeStyle=s.ftLine,e.lineWidth=2,e.beginPath(),e.moveTo(P(145,S),S),e.lineTo(P(235,S),S),e.stroke(),e.strokeStyle=s.ftLine,e.lineWidth=2,Bt(y,S,36,Math.PI,2*Math.PI,30),e.setLineDash([4,4]),Bt(y,S,36,0,Math.PI,30),e.setLineDash([]);const t=Math.sqrt(8e3),l=m+t,o=0===ot?pt:1===ot?gt:null;o&&Math.hypot(o.x-p,o.y-m)<M&&e.setLineDash([6,6]),e.strokeStyle=s.threeArc,e.lineWidth=2,e.beginPath(),e.moveTo(P(0,d),d),e.lineTo(P(0,l),l),e.stroke(),e.beginPath(),e.moveTo(P(x,d),d),e.lineTo(P(x,l),l),e.stroke();const i=Math.atan2(l-m,-190),a=Math.atan2(l-m,190);Bt(p,m,M,i,a,50),e.setLineDash([]),e.strokeStyle=s.center,e.lineWidth=2,e.beginPath(),e.moveTo(P(0,u),u),e.lineTo(P(x,u),u),e.stroke()}const Ot=95,Ct=18;function Yt(){e.fillStyle="#666666",Lt(188,55,4,40),e.fillStyle="#888888",Lt(187,90,6,5),Lt(152.5,55,75,40,s.backboard),e.strokeStyle=s.bbEdge,e.lineWidth=2,e.strokeRect(152.5,55,75,40),e.strokeStyle="#cc4444",e.lineWidth=1.5,e.strokeRect(178,71,24,16)}function Xt(){const t=yt>=0&&yt<30?function(t){const e=[[0,0],[.1,-3],[.2,3],[.3,-3],[.4,3],[.5,-2],[.6,2],[.7,-1],[.8,1],[.9,-.5],[1,0]];for(let n=1;n<e.length;n++)if(t<=e[n][0]){const l=(t-e[n-1][0])/(e[n][0]-e[n-1][0]);return e[n-1][1]+(e[n][1]-e[n-1][1])*l}return 0}(yt/30):0,n=t,l=ht>=0&&ht<30?function(t){const e=[[0,0],[.111,0],[.222,-12.5],[.333,6.25],[.444,-3.125],[.555,1.5625],[.666,-.78125],[.777,.390625],[.888,-.1100313],[1,0]];for(let n=1;n<e.length;n++)if(t<=e[n][0]){const l=(t-e[n-1][0])/(e[n][0]-e[n-1][0]);return e[n-1][1]+(e[n][1]-e[n-1][1])*l}return 0}(ht/30):0,o=l*Math.PI/180,i=Math.tan(o);e.save(),e.translate(y,Ot+4+Ct/2+t),e.transform(1,i,i,1,0,0),e.translate(-y,-(Ot+4+Ct/2));for(let t=0;t<=8;t++){const n=t/8,l=176+28*n,o=182+8*n*2;e.strokeStyle="rgba(220,220,220,0.55)",e.lineWidth=.8,e.beginPath(),e.moveTo(l,Ot+4),e.lineTo(o,Ot+4+Ct),e.stroke()}for(let t=1;t<=4;t++){const n=t/5,l=g+-6*n;e.strokeStyle="rgba(220,220,220,0.4)",e.lineWidth=.8,e.beginPath(),e.moveTo(y-l,Ot+4+n*Ct),e.lineTo(y+l,Ot+4+n*Ct),e.stroke()}e.restore(),e.fillStyle=s.rim,Lt(176,Ot+n,28,4),e.strokeStyle=s.rim,e.lineWidth=2.5,e.beginPath(),e.moveTo(176,Ot+4+n),e.lineTo(204,Ot+4+n),e.stroke()}function Ft(t){const n=~~P(t.x,t.y),l=~~t.y,o=w(t.y),i=0===t.id?s.p1Jersey:s.p2Jersey,a=0===t.id?s.p1Shorts:s.p2Shorts,r=0===t.id?s.p1Skin:s.p2Skin,c=0===t.id?s.p1Shoe:s.p2Shoe;e.save(),e.translate(n,l),e.scale(o,o),e.fillStyle="rgba(0,0,0,0.4)",e.beginPath(),e.ellipse(2,3,14,7,0,0,2*Math.PI),e.fill(),e.translate(0,-t.jumpH);const f="run"===t.state,h=f?1.5*Math.sin(.35*t.anim):0,y=f?4*Math.sin(.35*t.anim):0;e.fillStyle=c,e.beginPath(),e.ellipse(-5,h+7+y,5,3,.3,0,2*Math.PI),e.fill(),e.beginPath(),e.ellipse(5,h+7-y,5,3,-.3,0,2*Math.PI),e.fill(),e.fillStyle=a,e.beginPath(),e.ellipse(0,h+2,10,6,0,0,2*Math.PI),e.fill(),e.fillStyle=i,e.beginPath(),e.ellipse(0,h-3,10,7,0,0,2*Math.PI),e.fill();const d=f?3*Math.sin(.35*t.anim):0;e.fillStyle=r,e.beginPath(),e.ellipse(-11,h-2+d,4,3,.5,0,2*Math.PI),e.fill(),e.beginPath(),e.ellipse(11,h-2-d,4,3,-.5,0,2*Math.PI),e.fill(),e.fillStyle=r,e.beginPath(),e.arc(0,h-12,8,0,2*Math.PI),e.fill(),e.restore()}function Gt(){const t="fly"===ft.state,n="net"===ft.state,l="oob"===ft.state,o=t||n||l,i=o?1:w(ft.y),a=o?ft.screenX:P(ft.x,ft.y),r=o?ft.screenY:ft.y-ft.h;if(t){const t=ft.y-ft.screenY,n=Math.max(.3,1-t/200);e.fillStyle=`rgba(0,0,0,${.4*n})`,e.beginPath(),e.ellipse(P(ft.x,ft.y),ft.y,8*n*1.2*w(ft.y),8*n*.6*w(ft.y),0,0,2*Math.PI),e.fill()}ft.trail.forEach((t,n)=>{const l=n/ft.trail.length*.3,o=n/ft.trail.length*8*.6;e.fillStyle=`rgba(224,85,21,${l})`,t.isScreen?(e.beginPath(),e.arc(t.x,t.y,o,0,2*Math.PI),e.fill()):(e.beginPath(),e.arc(P(t.x,t.y),t.y,o,0,2*Math.PI),e.fill())});const c=(8+.01*ft.h)*i;e.fillStyle=s.ball,e.beginPath(),e.arc(a,r,c,0,2*Math.PI),e.fill(),e.fillStyle=s.ballHi,e.beginPath(),e.arc(a-.3*c,r-.3*c,.4*c,0,2*Math.PI),e.fill(),e.strokeStyle=s.ballSeam,e.lineWidth=1.2,e.beginPath(),e.arc(a,r,c-1,ft.rot,ft.rot+Math.PI),e.stroke(),e.beginPath(),e.moveTo(a-c+1,r),e.lineTo(a+c-1,r),e.stroke()}const Jt={" ":[0,0,0,0,0,0,0],0:[14,17,17,17,17,17,14],1:[4,12,4,4,4,4,14],2:[14,17,1,6,8,16,31],3:[14,17,1,6,1,17,14],4:[2,6,10,18,31,2,2],5:[31,16,16,30,1,1,30],6:[6,8,16,30,17,17,14],7:[31,1,2,4,8,8,8],8:[14,17,17,14,17,17,14],9:[14,17,17,15,1,17,14],F:[31,16,16,30,16,16,16],H:[17,17,17,31,17,17,17],I:[14,4,4,4,4,4,14],O:[14,17,17,17,17,17,14],P:[30,17,17,30,16,16,16],R:[30,17,17,30,20,18,17],S:[15,16,16,14,1,1,30],T:[31,4,4,4,4,4,4],"%":[17,18,4,8,20,1,0]};function qt(t,n,l,o,i,a){const s=l+1,r=l/2,c=Jt[o.toUpperCase()]||Jt[" "];for(let l=0;l<7;l++){const o=c[l]||0;for(let c=0;c<5;c++)e.fillStyle=o>>4-c&1?i:a,e.beginPath(),e.arc(~~(t+c*s+r),~~(n+l*s+r),r,0,2*Math.PI),e.fill()}}function $t(t,e,n,l,o,i){const a=5*(n+1)+1;for(let s=0;s<l.length;s++)qt(t+s*a,e,n,l[s],o,i)}const Ut=(t,e)=>e*(5*(t+1)+1);function Nt(){const t=280,n=54,l=50;Lt(l,6,t,n,s.scoreBg),e.strokeStyle=s.scoreBdr,e.lineWidth=2,e.strokeRect(l,6,t,n),e.strokeStyle="#331100",e.lineWidth=1,e.strokeRect(53,9,274,48);const o=s.score,i="#1a1000",a=nt<=2?"#ff2200":nt<=3?"#ffaa00":"#ff8800",r=ot>=0?ot:ft.shooterId;e.font="bold 9px monospace",e.textAlign="left",e.fillStyle=s.p1Jersey,e.fillText("P1",58,20),e.textAlign="right",e.fillStyle=s.p2Jersey,e.fillText("P2",322,20);if($t(58,26,3,String(et[0]).padStart(2,"0"),o,i),$t(322-Ut(3,2),26,3,String(et[1]).padStart(2,"0"),o,i),dt&&pt&>){const t=1===r?gt:pt,n=1===r?pt:gt,l=Math.hypot(t.x-p,t.y-m)/Tt,i=Math.hypot(n.x-p,n.y-m),a=Math.max(0,Math.hypot(t.x-n.x,t.y-n.y)-2*It),s=i<l*Tt?a/Tt:8,c=Math.round(Mt(l,s)),f=-1===ot&&ut?ut.pct:c;e.font="bold 9px monospace",e.fillStyle=o,e.textAlign="center",e.fillText(`FG%:${f}%`,190,20)}else e.font="bold 8px monospace",e.fillStyle=o,e.textAlign="center",e.fillText("FIRST TO 21",190,20);$t(~~(190-Ut(3,1)/2),26,3,String(nt),a,"#1a0000");const c=0===r?120:260;e.fillStyle=s.score,e.beginPath(),e.moveTo(c,62),e.lineTo(c-5,68),e.lineTo(c+5,68),e.closePath(),e.fill()}let Kt=!0;function zt(){Wt(),Dt(),e.fillStyle="rgba(0,0,0,0.72)",e.fillRect(0,0,n,l),e.textAlign="center",e.font="bold 20px monospace",e.fillStyle="#ffee00",e.shadowColor="#ff4400",e.shadowBlur=20,e.fillText([82,101,116,114,111,32,71,97,109,101,115,58,32,66,97,115,107,101,116,98,97,108,108].map(t=>String.fromCharCode(t)).join(""),190,118),e.shadowBlur=0,e.font="9px monospace",e.fillStyle="#ffffff",e.fillText([98,121,32,105,100,101,97,77,97,114,99,111,115].map(t=>String.fromCharCode(t)).join(""),190,140);e.font="bold 8px monospace",e.fillStyle=W?"#333":"#ffee00",e.fillRect(92,q,80,14),e.fillStyle=W?"#aaa":"#000",e.textAlign="center",e.fillText("1P vs CPU",132,169),e.fillStyle=W?"#ffee00":"#333",e.fillRect($,q,80,14),e.fillStyle=W?"#000":"#aaa",e.fillText("2P LOCAL",248,169),e.font="bold 8px monospace",e.fillStyle="#666",e.textAlign="center",W?(e.fillText("P1 KB",81,190),e.fillText("P1 GP",143,190),e.fillText("P2 KB",269,190),e.fillText("P2 GP",332,190),e.strokeStyle="#444",e.lineWidth=1,e.beginPath(),e.moveTo(183,184),e.lineTo(183,F+20*Y.length-4),e.stroke()):(e.fillText("P1 KEYBOARD",152,190),e.fillText("P1 GAMEPAD",275,190));const t=(t,n,l,o,i,a)=>{e.fillStyle=o?"#ffee00":"#e8e8e8",e.fillRect(t,l-12,n,15),e.fillStyle=o?"#000":a?"#888":"#000",e.font="8px monospace",e.textAlign="center",e.fillText(o?"...":i,t+n/2,l-1)};Y.forEach((n,l)=>{const o=F+20*l,i=B===n&&"kb"===D&&1===O,a=B===n&&"gp"===D&&1===O,s=B===n&&"kb"===D&&2===O,r=B===n&&"gp"===D&&2===O;if(W)if(e.textAlign="right",e.font="9px monospace",e.fillStyle="#999",e.fillText(X[n],48,o),t(52,58,o,i,U(R[n]),!1),"fullscreen"!==n&&t(114,58,o,a,N(j[n]),null===j[n]),e.textAlign="right",e.font="9px monospace",e.fillStyle="#999",e.fillText(X[n],236,o),"fullscreen"===n){const t=122;e.fillStyle="#222",e.fillRect(G,o-12,t,15),e.fillStyle="#555",e.font="8px monospace",e.textAlign="center",e.fillText("shared with P1",G+t/2,o-1)}else t(G,58,o,s,U(L[n]),!1),t(J,60,o,r,N(H[n]),null===H[n]);else e.textAlign="right",e.font="10px monospace",e.fillStyle="#999",e.fillText(X[n],91,o),t(95,114,o,i,U(R[n]),!1),"fullscreen"!==n&&t(218,114,o,a,N(j[n]),null===j[n])}),e.textAlign="center",e.font="bold 13px monospace",e.fillStyle=~~(Date.now()/400)%2?"#ffffff":"#666666",e.fillText("PRESS SPACE TO TIP OFF",190,340)}let Vt=0;bt(),requestAnimationFrame(function a(r){if(Z)return Vt=r,void requestAnimationFrame(a);const c=Math.min((r-Vt)/k,3)||1;if(Vt=r,e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,t.width,t.height),e.setTransform(o,0,0,i,0,0),(I(R.fullscreen)||I(L.fullscreen))&&(document.fullscreenElement?document.exitFullscreen():document.documentElement.requestFullscreen()),Kt){!function(){if(B&&"gp"===D)for(const t of navigator.getGamepads())if(t&&t.connected){for(let e=0;e<t.buttons.length;e++)if(t.buttons[e].pressed)return 2===O?(z<0&&(z=t.index),H[B]={type:"btn",i:e}):(K<0&&(K=t.index),j[B]={type:"btn",i:e},"fullscreen"===B&&(H.fullscreen=j.fullscreen)),B=null,D=null,void(C=null);for(let e=0;e<t.axes.length;e++){const n=t.axes[e],l=C?C[e]??0:0;if(Math.abs(n-l)>=.5)return 2===O?(z<0&&(z=t.index),H[B]={type:"axis",i:e,value:n}):(K<0&&(K=t.index),j[B]={type:"axis",i:e,value:n},"fullscreen"===B&&(H.fullscreen=j.fullscreen)),B=null,D=null,void(C=null)}}}(),zt();Q(K);return!B&&I(" ")&&(Kt=!1,bt(),V=!0,_=!0),Object.assign(E,A),void requestAnimationFrame(a)}if("gameover"===it)return Wt(),Dt(),Yt(),Ft(gt),Ft(pt),Gt(),Xt(),Nt(),function(){e.fillStyle="rgba(0,0,0,0.8)",e.fillRect(0,0,n,l),e.textAlign="center",e.font="bold 34px monospace",e.fillStyle=s.scoreBdr,e.fillText("GAME OVER",190,155);const t=et[0]>et[1]?"P1 WINS!":et[1]>et[0]?"P2 WINS!":"TIE GAME!";e.font="bold 24px monospace",e.fillStyle=et[0]>et[1]?s.p1Jersey:s.p2Jersey,e.fillText(t,190,210),e.font="bold 18px monospace",e.fillStyle=s.score,e.fillText(`${et[0]} — ${et[1]}`,190,246),e.font="12px monospace",e.fillStyle="#555",e.fillText("SPACE TO REMATCH",190,282)}(),I(" ")&&bt(),Object.assign(E,A),void requestAnimationFrame(a);if("scored"===it?(at-=c,jt(),st=Math.max(0,st-c),ht>=0&&ht++,ht>=30&&(ht=-1),yt>=0&&yt++,yt>=30&&(yt=-1),at<=0&&vt(0===ct?1:0)):(ot>=0&&(lt+=c*k,lt>=1e3&&(lt-=1e3,nt=Math.max(0,nt-1)),nt<=0&<>=800&&vt(0===ot?1:0)),function(t){Pt(t,pt,0,R,j,K)}(c),W?Pt(c,gt,1,L,H,z):At(c),Et(pt,gt),Et(gt,pt),function(){const t=gt.x-pt.x,e=gt.y-pt.y,n=Math.sqrt(t*t+e*e),l=2*It;if(n<l&&n>0){const o=l-n,i=t/n,a=e/n,s=0!==pt.vx||0!==pt.vy,r=0!==gt.vx||0!==gt.vy;s&&!r?(pt.x-=i*o,pt.y-=a*o):r&&!s?(gt.x+=i*o,gt.y+=a*o):(pt.x-=i*o*.5,pt.y-=a*o*.5,gt.x+=i*o*.5,gt.y+=a*o*.5)}}(),jt(),st=Math.max(0,st-c),yt>=0&&yt++,yt>=30&&(yt=-1),ht>=0&&ht++,ht>=30&&(ht=-1)),Wt(),Dt(),Yt(),dt){if(e.save(),e.setLineDash([4,4]),e.lineWidth=1.5,1===ot&>.debugProbes)for(const t of gt.debugProbes){const n=gt.x+50*t.ddx,l=gt.y+50*t.ddy;e.fillStyle=t.skip?"rgba(255,60,60,0.6)":t.chosen?"rgba(0,255,80,0.9)":"rgba(255,220,0,0.6)",e.beginPath(),e.arc(n,l,t.chosen?4:3,0,2*Math.PI),e.fill()}const t=1===ot?pt:gt;e.strokeStyle="rgba(255,80,80,0.6)",e.beginPath(),e.arc(t.x,t.y,Rt,0,2*Math.PI),e.stroke(),e.restore()}const[f,h]=pt.y>gt.y?[pt,gt]:[gt,pt],y="held"===ft.state;if(y&&Gt(),Ft(h),Ft(f),y)Xt();else{"fly"===ft.state&&ft.ascending?(Xt(),Gt()):(Gt(),Xt())}Nt(),function(){if(st<=0)return;const t=Math.min(st/30,1);e.fillStyle=`rgba(255,220,60,${.12*t})`,e.fillRect(0,0,n,l),e.globalAlpha=Math.min(1.5*t,1),e.textAlign="center",e.font="bold 28px monospace",e.fillStyle=0===ct?"#ff5533":"#44ff88",e.fillText(rt,190,200),e.font="bold 16px monospace",e.fillStyle=s.white,e.fillText(`${et[0]} — ${et[1]}`,190,230),e.globalAlpha=1}(),I("`")&&(dt=!dt),Object.assign(E,A),requestAnimationFrame(a)})}()</script></body></html>