diff --git a/main.bundle.js b/main.bundle.js index f13a897..65aac70 100644 --- a/main.bundle.js +++ b/main.bundle.js @@ -1,2 +1,2 @@ -"use strict";(self.webpackChunkpikachu_volleyball=self.webpackChunkpikachu_volleyball||[]).push([[179],{982:(e,t,s)=>{s.d(t,{d:()=>i});const i={SPRITE_SHEET:"../resources/assets/images/sprite_sheet.json",TEXTURES:{},SOUNDS:{}},n=i.TEXTURES;n.PIKACHU=(e,t)=>`pikachu/pikachu_${e}_${t}.png`,n.BALL=e=>`ball/ball_${e}.png`,n.NUMBER=e=>`number/number_${e}.png`,n.SKY_BLUE="objects/sky_blue.png",n.MOUNTAIN="objects/mountain.png",n.GROUND_RED="objects/ground_red.png",n.GROUND_LINE="objects/ground_line.png",n.GROUND_LINE_LEFT_MOST="objects/ground_line_leftmost.png",n.GROUND_LINE_RIGHT_MOST="objects/ground_line_rightmost.png",n.GROUND_YELLOW="objects/ground_yellow.png",n.NET_PILLAR_TOP="objects/net_pillar_top.png",n.NET_PILLAR="objects/net_pillar.png",n.SHADOW="objects/shadow.png",n.BALL_HYPER="ball/ball_hyper.png",n.BALL_TRAIL="ball/ball_trail.png",n.BALL_PUNCH="ball/ball_punch.png",n.CLOUD="objects/cloud.png",n.WAVE="objects/wave.png",n.BLACK="objects/black.png",n.SACHISOFT="messages/common/sachisoft.png",n.READY="messages/common/ready.png",n.GAME_END="messages/common/game_end.png",n.MARK="messages/ja/mark.png",n.POKEMON="messages/ja/pokemon.png",n.PIKACHU_VOLLEYBALL="messages/ja/pikachu_volleyball.png",n.FIGHT="messages/ja/fight.png",n.WITH_COMPUTER="messages/ja/with_computer.png",n.WITH_FRIEND="messages/ja/with_friend.png",n.GAME_START="messages/ja/game_start.png",n.SITTING_PIKACHU="sitting_pikachu.png";const o=i.SOUNDS;o.BGM="../resources/assets/sounds/bgm.mp3",o.PIPIKACHU="../resources/assets/sounds/WAVE140_1.wav",o.PIKA="../resources/assets/sounds/WAVE141_1.wav",o.CHU="../resources/assets/sounds/WAVE142_1.wav",o.PI="../resources/assets/sounds/WAVE143_1.wav",o.PIKACHU="../resources/assets/sounds/WAVE144_1.wav",o.POWERHIT="../resources/assets/sounds/WAVE145_1.wav",o.BALLTOUCHESGROUND="../resources/assets/sounds/WAVE146_1.wav"},372:(e,t,s)=>{var i=s(319),n=s(680),o=s(710),a=s(858),r=s(585),l=s(550),h=s(126),c=s(679),d=s(93),u=s(196),m=s(619);s(971);function y(){return Math.floor(32768*Math.random())}const p=432,b=216,g=244,f=252;class w{constructor(e,t){this.player1=new v(!1,e),this.player2=new v(!0,t),this.ball=new E(!1)}runEngineForNextFrame(e){const t=function(e,t,s,i){const n=function(e){e.previousPreviousX=e.previousX,e.previousPreviousY=e.previousY,e.previousX=e.x,e.previousY=e.y;let t=e.fineRotation+(e.xVelocity/2|0);t<0?t+=50:t>50&&(t+=-50),e.fineRotation=t,e.rotation=e.fineRotation/10|0;const s=e.x+e.xVelocity;(s<20||s>p)&&(e.xVelocity=-e.xVelocity);let i=e.y+e.yVelocity;return i<0&&(e.yVelocity=1),Math.abs(e.x-b)<25&&e.y>176&&(e.y<=192?e.yVelocity>0&&(e.yVelocity=-e.yVelocity):e.xf?(e.sound.ballTouchesGround=!0,e.yVelocity=-e.yVelocity,e.punchEffectX=e.x,e.y=f,e.punchEffectRadius=20,e.punchEffectY=272,!0):(e.y=i,e.x=e.x+e.xVelocity,e.yVelocity+=1,!1)}(s);let o,a;for(let n=0;n<2;n++)0===n?(o=e,a=t):(o=t,a=e),C(s),L(o,i[n],a,s);for(let n=0;n<2;n++)o=0===n?e:t,!0===x(s,o.x,o.y)?!1===o.isCollisionWithBallHappened&&(k(s,o.x,i[n],o.state),o.isCollisionWithBallHappened=!0):o.isCollisionWithBallHappened=!1;return n}(this.player1,this.player2,this.ball,e);return t}}class v{constructor(e,t){this.isPlayer2=e,this.isComputer=t,this.initializeForNewRound(),this.divingDirection=0,this.lyingDownDurationLeft=-1,this.isWinner=!1,this.gameEnded=!1,this.computerWhereToStandBy=0,this.sound={pipikachu:!1,pika:!1,chu:!1}}initializeForNewRound(){this.x=36,this.isPlayer2&&(this.x=396),this.y=g,this.yVelocity=0,this.isCollisionWithBallHappened=!1,this.state=0,this.frameNumber=0,this.normalStatusArmSwingDirection=1,this.delayBeforeNextFrame=0,this.computerBoldness=y()%5}}class E{constructor(e){this.initializeForNewRound(e),this.expectedLandingPointX=0,this.rotation=0,this.fineRotation=0,this.punchEffectX=0,this.punchEffectY=0,this.previousX=0,this.previousPreviousX=0,this.previousY=0,this.previousPreviousY=0,this.sound={powerHit:!1,ballTouchesGround:!1}}initializeForNewRound(e){this.x=56,!0===e&&(this.x=376),this.y=0,this.xVelocity=0,this.yVelocity=1,this.punchEffectRadius=0,this.isPowerHit=!1}}function x(e,t,s){let i=e.x-t;return Math.abs(i)<=32&&(i=e.y-s,Math.abs(i)<=32)}function L(e,t,s,i){if(!0===e.isComputer&&function(e,t,s,i){i.xDirection=0,i.yDirection=0,i.powerHit=0;let n=t.expectedLandingPointX;if(Math.abs(t.x-e.x)>100&&Math.abs(t.xVelocity)=Number(e.isPlayer2)*p+b)&&0===e.computerWhereToStandBy&&(n=s+108)}if(Math.abs(n-e.x)>e.computerBoldness+8?e.x-36&&t.y<10*e.computerBoldness+84&&t.yVelocity>0&&(i.yDirection=-1);const s=Number(e.isPlayer2)*b,n=(Number(e.isPlayer2)+1)*b;t.expectedLandingPointX>s&&t.expectedLandingPointX5*e.computerBoldness+64&&t.x>s&&t.x174&&(i.powerHit=1,e.x8&&(e.x-1;n--)for(let o=-1;o<2;o++){const a=S(n,o,t);if((a<=Number(e.isPlayer2)*b||a>=Number(e.isPlayer2)*p+b)&&Math.abs(a-s.x)>64)return i.xDirection=n,i.yDirection=o,!0}else for(let n=1;n>-1;n--)for(let o=1;o>-2;o--){const a=S(n,o,t);if((a<=Number(e.isPlayer2)*b||a>=Number(e.isPlayer2)*p+b)&&Math.abs(a-s.x)>64)return i.xDirection=n,i.yDirection=o,!0}return!1}(e,t,s,i);!0===n&&(i.powerHit=1,Math.abs(s.x-e.x)<80&&-1!==i.yDirection&&(i.yDirection=-1))}}(e,i,s,t),4===e.state)return e.lyingDownDurationLeft+=-1,void(e.lyingDownDurationLeft<-1&&(e.state=0));let n=0;e.state<5&&(n=e.state<3?6*t.xDirection:8*e.divingDirection);const o=e.x+n;e.x=o,!1===e.isPlayer2?o<32?e.x=32:o>184&&(e.x=184):o<248?e.x=248:o>400&&(e.x=400),e.state<3&&-1===t.yDirection&&e.y===g&&(e.yVelocity=-16,e.state=1,e.frameNumber=0,e.sound.chu=!0);const a=e.y+e.yVelocity;if(e.y=a,ag&&(e.yVelocity=0,e.y=g,e.frameNumber=0,3===e.state?(e.state=4,e.frameNumber=0,e.lyingDownDurationLeft=3):e.state=0),1===t.powerHit&&(1===e.state?(e.delayBeforeNextFrame=5,e.frameNumber=0,e.state=2,e.sound.pika=!0):0===e.state&&0!==t.xDirection&&(e.state=3,e.frameNumber=0,e.divingDirection=t.xDirection,e.yVelocity=-5,e.sound.chu=!0)),1===e.state)e.frameNumber=(e.frameNumber+1)%3;else if(2===e.state)e.delayBeforeNextFrame<1?(e.frameNumber+=1,e.frameNumber>4&&(e.frameNumber=0,e.state=1)):e.delayBeforeNextFrame-=1;else if(0===e.state&&(e.delayBeforeNextFrame+=1,e.delayBeforeNextFrame>3)){e.delayBeforeNextFrame=0;const t=e.frameNumber+e.normalStatusArmSwingDirection;(t<0||t>4)&&(e.normalStatusArmSwingDirection=-e.normalStatusArmSwingDirection),e.frameNumber=e.frameNumber+e.normalStatusArmSwingDirection}!0===e.gameEnded&&(0===e.state&&(!0===e.isWinner?(e.state=5,e.sound.pipikachu=!0):e.state=6,e.delayBeforeNextFrame=0,e.frameNumber=0),function(e){!0===e.gameEnded&&e.frameNumber<4&&(e.delayBeforeNextFrame+=1,e.delayBeforeNextFrame>4&&(e.delayBeforeNextFrame=0,e.frameNumber+=1))}(e))}function k(e,t,s,i){e.xt&&(e.xVelocity=Math.abs(e.x-t)/3|0),0===e.xVelocity&&(e.xVelocity=y()%3-1);const n=Math.abs(e.yVelocity);e.yVelocity=-n,n<15&&(e.yVelocity=-15),2===i?(e.xp)&&(t.xVelocity=-t.xVelocity),t.y+t.yVelocity<0&&(t.yVelocity=1),Math.abs(t.x-b)<25&&t.y>176&&(t.y<192?t.yVelocity>0&&(t.yVelocity=-t.yVelocity):t.xf||s>=1e3)break;t.x=t.x+t.xVelocity,t.yVelocity+=1}e.expectedLandingPointX=t.x}function S(e,t,s){const i={x:s.x,y:s.y,xVelocity:s.xVelocity,yVelocity:s.yVelocity};i.xp)&&(i.xVelocity=-i.xVelocity),i.y+i.yVelocity<0&&(i.yVelocity=1),Math.abs(i.x-b)<25&&i.y>176&&i.yVelocity>0&&(i.yVelocity=-i.yVelocity),i.y=i.y+i.yVelocity,i.y>f||n>=1e3)return i.x;i.x=i.x+i.xVelocity,i.yVelocity+=1}}var B=s(408),I=s(33);class P{constructor(){this.topLeftPointX=y()%500-68,this.topLeftPointY=y()%152,this.topLeftPointXVelocity=1+y()%2,this.sizeDiffTurnNumber=y()%11}get sizeDiff(){return 5-Math.abs(this.sizeDiffTurnNumber-5)}get spriteTopLeftPointX(){return this.topLeftPointX-this.sizeDiff}get spriteTopLeftPointY(){return this.topLeftPointY-this.sizeDiff}get spriteWidth(){return 48+2*this.sizeDiff}get spriteHeight(){return 24+2*this.sizeDiff}}class M{constructor(){this.verticalCoord=0,this.verticalCoordVelocity=2,this.yCoords=[];for(let e=0;e<27;e++)this.yCoords.push(314)}}var V=s(982);const N=V.d.TEXTURES;class A{constructor(e){const t=e[V.d.SPRITE_SHEET].textures;this.mark=_(t,N.MARK,.5,.5),this.mark.x=216,this.mark.y=152,this.container=new r.W2,this.container.addChild(this.mark)}get visible(){return this.container.visible}set visible(e){this.container.visible=e}drawMark(e){const t=this.mark;0!==e?e<100?t.alpha=Math.min(1,t.alpha+.04):e>=100&&(t.alpha=Math.max(0,t.alpha-.04)):t.alpha=0}}class T{constructor(e){const t=e[V.d.SPRITE_SHEET].textures;this.messages={pokemon:_(t,N.POKEMON,0,0),pikachuVolleyball:_(t,N.PIKACHU_VOLLEYBALL,0,0),withWho:[_(t,N.WITH_COMPUTER,0,0),_(t,N.WITH_FRIEND,0,0)],sachisoft:_(t,N.SACHISOFT,0,0),fight:_(t,N.FIGHT,0,0)},this.sittingPikachuTilesContainer=function(e){const t=new r.W2,s=e[N.SITTING_PIKACHU],i=s.width,n=s.height;let o;for(let e=0;e70&&(this.messages.sachisoft.alpha=1)}drawSittingPikachuTiles(e){0===e&&(this.sittingPikachuTilesContainer.visible=!0,this.sittingPikachuTilesContainer.alpha=0);const t=this.sittingPikachuTilesContainer.getChildAt(0).texture.height;this.sittingPikachuTilesDisplacement=(this.sittingPikachuTilesDisplacement+2)%t,this.sittingPikachuTilesContainer.x=-this.sittingPikachuTilesDisplacement,this.sittingPikachuTilesContainer.y=-this.sittingPikachuTilesDisplacement,e>30&&(this.sittingPikachuTilesContainer.alpha=Math.min(1,this.sittingPikachuTilesContainer.alpha+.04)),e>70&&(this.sittingPikachuTilesContainer.alpha=1)}drawPikachuVolleyballMessage(e){if(0!==e)if(e>30&&(this.messages.pikachuVolleyball.visible=!0),e>30&&e<=44){const t=195-15*(e-30);this.messages.pikachuVolleyball.x=140+t}else e>44&&e<=55?(this.messages.pikachuVolleyball.x=140,this.messages.pikachuVolleyball.width=200-15*(e-44)):e>55&&e<=71?(this.messages.pikachuVolleyball.x=140,this.messages.pikachuVolleyball.width=40+15*(e-55)):e>71&&(this.messages.pikachuVolleyball.x=140,this.messages.pikachuVolleyball.width=this.messages.pikachuVolleyball.texture.width);else this.messages.pikachuVolleyball.visible=!1}drawPokemonMessage(e){0!==e?e>71&&(this.messages.pokemon.visible=!0):this.messages.pokemon.visible=!1}drawWithWhoMessages(e){const t=this.messages.withWho,s=t[0].texture.width,i=t[0].texture.height;if(0!==e){if(e>70){this.selectedWithWhoMessageSizeIncrement<10&&(this.selectedWithWhoMessageSizeIncrement+=1);for(let e=0;e<2;e++){const n=Number(this.selectedWithWho===e),o=n*(this.selectedWithWhoMessageSizeIncrement+2),a=n*this.selectedWithWhoMessageSizeIncrement;t[e].visible=!0,t[e].x=216-s/2-o,t[e].y=184+30*e-a,t[e].width=s+2*o,t[e].height=i+2*a}}}else for(let e=0;e<2;e++)t[e].visible=!1}selectWithWho(e){this.selectedWithWho=e,this.selectedWithWhoMessageSizeIncrement=2}}class D{constructor(e){const t=e[V.d.SPRITE_SHEET].textures;this.bgContainer=function(e){const t=new r.W2;let s,i=e[N.SKY_BLUE];for(let e=0;e<12;e++)for(let n=0;n<27;n++)s=new I.j(i),R(t,s,16*n,16*e);i=e[N.MOUNTAIN],s=new I.j(i),R(t,s,0,188),i=e[N.GROUND_RED];for(let e=0;e<27;e++)s=new I.j(i),R(t,s,16*e,248);i=e[N.GROUND_LINE];for(let e=1;e<26;e++)s=new I.j(i),R(t,s,16*e,264);i=e[N.GROUND_LINE_LEFT_MOST],s=new I.j(i),R(t,s,0,264),i=e[N.GROUND_LINE_RIGHT_MOST],s=new I.j(i),R(t,s,416,264),i=e[N.GROUND_YELLOW];for(let e=0;e<2;e++)for(let n=0;n<27;n++)s=new I.j(i),R(t,s,16*n,280+16*e);i=e[N.NET_PILLAR_TOP],s=new I.j(i),R(t,s,213,176),i=e[N.NET_PILLAR];for(let e=0;e<12;e++)s=new I.j(i),R(t,s,213,184+8*e);return t}(t);const s=function(e){const t=(t,s)=>e[N.PIKACHU(t,s)],s=[];for(let e=0;e<7;e++)if(3===e)s.push(t(e,0)),s.push(t(e,1));else if(4===e)s.push(t(e,0));else for(let i=0;i<5;i++)s.push(t(e,i));const i=new B.K(s,!1),n=new B.K(s,!1);return i.anchor.x=.5,i.anchor.y=.5,n.anchor.x=.5,n.anchor.y=.5,[i,n]}(t);this.player1=s[0],this.player2=s[1],this.ball=function(e){const t=t=>e[N.BALL(t)],s=[t(0),t(1),t(2),t(3),t(4),t("hyper")],i=new B.K(s,!1);return i.anchor.x=.5,i.anchor.y=.5,i}(t),this.ballHyper=_(t,N.BALL_HYPER,.5,.5),this.ballTrail=_(t,N.BALL_TRAIL,.5,.5),this.punch=_(t,N.BALL_PUNCH,.5,.5),this.scoreBoards=[O(t),O(t)],this.shadows={forPlayer1:_(t,N.SHADOW,.5,.5),forPlayer2:_(t,N.SHADOW,.5,.5),forBall:_(t,N.SHADOW,.5,.5)},this.messages={gameStart:_(t,N.GAME_START,0,0),ready:_(t,N.READY,0,0),gameEnd:_(t,N.GAME_END,0,0)},this.cloudContainer=function(e){const t=new r.W2,s=e[N.CLOUD];for(let e=0;e<10;e++){const e=new I.j(s);e.anchor.x=0,e.anchor.y=0,t.addChild(e)}return t}(t),this.waveContainer=function(e){const t=new r.W2,s=e[N.WAVE];for(let e=0;e<27;e++)R(t,new I.j(s),16*e,0);return t}(t),this.container=new r.W2,this.container.addChild(this.bgContainer),this.container.addChild(this.cloudContainer),this.container.addChild(this.waveContainer),this.container.addChild(this.shadows.forPlayer1),this.container.addChild(this.shadows.forPlayer2),this.container.addChild(this.shadows.forBall),this.container.addChild(this.player1),this.container.addChild(this.player2),this.container.addChild(this.ballTrail),this.container.addChild(this.ballHyper),this.container.addChild(this.ball),this.container.addChild(this.punch),this.container.addChild(this.scoreBoards[0]),this.container.addChild(this.scoreBoards[1]),this.container.addChild(this.messages.gameStart),this.container.addChild(this.messages.ready),this.container.addChild(this.messages.gameEnd),this.bgContainer.x=0,this.bgContainer.y=0,this.cloudContainer.x=0,this.cloudContainer.y=0,this.waveContainer.x=0,this.waveContainer.y=0,this.messages.ready.x=176,this.messages.ready.y=38,this.scoreBoards[0].x=14,this.scoreBoards[0].y=10,this.scoreBoards[1].x=354,this.scoreBoards[1].y=10,this.shadows.forPlayer1.y=273,this.shadows.forPlayer2.y=273,this.shadows.forBall.y=273,this.initializeVisibles(),this.cloudArray=[];for(let e=0;e<10;e++)this.cloudArray.push(new P);this.wave=new M}get visible(){return this.container.visible}set visible(e){this.container.visible=e,!1===e&&this.initializeVisibles()}initializeVisibles(){for(const e in this.messages)this.messages[e].visible=!1}drawPlayersAndBall(e){const t=e.player1,s=e.player2,i=e.ball;this.player1.x=t.x,this.player1.y=t.y,3===t.state||4===t.state?this.player1.scale.x=-1===t.divingDirection?-1:1:this.player1.scale.x=1,this.shadows.forPlayer1.x=t.x,this.player2.x=s.x,this.player2.y=s.y,3===s.state||4===s.state?this.player2.scale.x=1===s.divingDirection?1:-1:this.player2.scale.x=-1,this.shadows.forPlayer2.x=s.x;const n=H(t.state,t.frameNumber),o=H(s.state,s.frameNumber);this.player1.gotoAndStop(n),this.player2.gotoAndStop(o),this.ball.x=i.x,this.ball.y=i.y,this.shadows.forBall.x=i.x,this.ball.gotoAndStop(i.rotation),i.punchEffectRadius>0?(i.punchEffectRadius-=2,this.punch.width=2*i.punchEffectRadius,this.punch.height=2*i.punchEffectRadius,this.punch.x=i.punchEffectX,this.punch.y=i.punchEffectY,this.punch.visible=!0):this.punch.visible=!1,!0===i.isPowerHit?(this.ballHyper.x=i.previousX,this.ballHyper.y=i.previousY,this.ballTrail.x=i.previousPreviousX,this.ballTrail.y=i.previousPreviousY,this.ballHyper.visible=!0,this.ballTrail.visible=!0):(this.ballHyper.visible=!1,this.ballTrail.visible=!1)}drawScoresToScoreBoards(e){for(let t=0;t<2;t++){const s=this.scoreBoards[t],i=e[t],n=s.getChildAt(0),o=s.getChildAt(1);n.gotoAndStop(i%10),o.gotoAndStop(Math.floor(i/10)%10),o.visible=i>=10}}drawCloudsAndWave(){const e=this.cloudArray,t=this.wave;!function(e,t){for(let t=0;t<10;t++)e[t].topLeftPointX+=e[t].topLeftPointXVelocity,e[t].topLeftPointX>432&&(e[t].topLeftPointX=-68,e[t].topLeftPointY=y()%152,e[t].topLeftPointXVelocity=1+y()%2),e[t].sizeDiffTurnNumber=(e[t].sizeDiffTurnNumber+1)%11;t.verticalCoord+=t.verticalCoordVelocity,t.verticalCoord>32?(t.verticalCoord=32,t.verticalCoordVelocity=-1):t.verticalCoord<0&&t.verticalCoordVelocity<0&&(t.verticalCoordVelocity=2,t.verticalCoord=-y()%40);for(let e=0;e<27;e++)t.yCoords[e]=314-t.verticalCoord+y()%3}(e,t);for(let t=0;t<10;t++){const s=e[t],i=this.cloudContainer.getChildAt(t);i.x=s.spriteTopLeftPointX,i.y=s.spriteTopLeftPointY,i.width=s.spriteWidth,i.height=s.spriteHeight}for(let e=0;e<27;e++)this.waveContainer.getChildAt(e).y=t.yCoords[e]}drawGameStartMessage(e,t){if(0===e)this.messages.gameStart.visible=!0;else if(e>=t-1)return void(this.messages.gameStart.visible=!1);const s=this.messages.gameStart,i=s.texture.width,n=s.texture.height,o=Math.floor(i*e/50),a=Math.floor(n*e/50);s.x=216-o,s.y=50+2*a,s.width=2*o,s.height=2*a}drawReadyMessage(e){this.messages.ready.visible=e}toggleReadyMessage(){this.messages.ready.visible=!this.messages.ready.visible}drawGameEndMessage(e){const t=this.messages.gameEnd,s=t.texture.width,i=t.texture.height;if(0===e&&(t.visible=!0),e<50){const n=2*Math.floor((50-e)*s/50),o=2*Math.floor((50-e)*i/50);t.x=216-s/2-n,t.y=50-o,t.width=s+2*n,t.height=i+2*o}else t.x=216-s/2,t.y=50,t.width=s,t.height=i}}class W{constructor(e){const t=e[V.d.SPRITE_SHEET].textures;this.black=_(t,N.BLACK,0,0),this.black.width=432,this.black.height=304,this.black.x=0,this.black.y=0,this.black.alpha=1}get visible(){return this.black.visible}set visible(e){this.black.visible=e}setBlackAlphaTo(e){this.black.alpha=e,0===this.black.alpha?this.black.visible=!1:this.black.visible=!0}changeBlackAlphaBy(e){this.black.alpha=e>=0?Math.min(1,this.black.alpha+e):Math.max(0,this.black.alpha+e),0===this.black.alpha?this.black.visible=!1:this.black.visible=!0}}function _(e,t,s,i){const n=new I.j(e[t]);return n.anchor.x=s,n.anchor.y=i,n}function O(e){const t=[];for(let i=0;i<10;i++)t.push((s=i,e[N.NUMBER(s)]));var s;const i=[null,null];i[0]=new B.K(t,!1),i[1]=new B.K(t,!1);const n=new r.W2;return R(n,i[0],32,0),R(n,i[1],0,0),n.setChildIndex(i[0],0),n.setChildIndex(i[1],1),n}function R(e,t,s,i){e.addChild(t),t.anchor.x=0,t.anchor.y=0,t.x=s,t.y=i}function H(e,t){return e<4?5*e+t:4===e?17+t:e>4?18+5*(e-5)+t:void 0}class F extends class{constructor(){this.xDirection=0,this.yDirection=0,this.powerHit=0}}{constructor(e,t,s,i,n,o=null){super(),this.powerHitKeyIsDownPrevious=!1,this.leftKey=new K(e),this.rightKey=new K(t),this.upKey=new K(s),this.downKey=new K(i),this.powerHitKey=new K(n),this.downRightKey=new K(o)}getInput(){this.leftKey.isDown?this.xDirection=-1:this.rightKey.isDown||this.downRightKey&&this.downRightKey.isDown?this.xDirection=1:this.xDirection=0,this.upKey.isDown?this.yDirection=-1:this.downKey.isDown||this.downRightKey&&this.downRightKey.isDown?this.yDirection=1:this.yDirection=0;const e=this.powerHitKey.isDown;!this.powerHitKeyIsDownPrevious&&e?this.powerHit=1:this.powerHit=0,this.powerHitKeyIsDownPrevious=e}subscribe(){this.leftKey.subscribe(),this.rightKey.subscribe(),this.upKey.subscribe(),this.downKey.subscribe(),this.powerHitKey.subscribe(),this.downRightKey.subscribe()}unsubscribe(){this.leftKey.unsubscribe(),this.rightKey.unsubscribe(),this.upKey.unsubscribe(),this.downKey.unsubscribe(),this.powerHitKey.unsubscribe(),this.downRightKey.unsubscribe()}}class K{constructor(e){this.value=e,this.isDown=!1,this.isUp=!0,this.downListener=this.downHandler.bind(this),this.upListener=this.upHandler.bind(this),this.subscribe()}downHandler(e){e.code===this.value&&(this.isDown=!0,this.isUp=!1,e.preventDefault())}upHandler(e){e.code===this.value&&(this.isDown=!1,this.isUp=!0,e.preventDefault())}subscribe(){window.addEventListener("keyup",this.upListener),window.addEventListener("keydown",this.downListener)}unsubscribe(){window.removeEventListener("keydown",this.downListener),window.removeEventListener("keyup",this.upListener),this.isDown=!1,this.isUp=!0}}var U=s(292);const G=V.d.SOUNDS;class X{constructor(e){this.sounds={bgm:new Y(e[G.BGM].sound),pipikachu:new Y(e[G.PIPIKACHU].sound),pika:new Y(e[G.PIKA].sound),chu:new Y(e[G.CHU].sound),pi:new Y(e[G.PI].sound),pikachu:new Y(e[G.PIKACHU].sound),powerHit:new Y(e[G.POWERHIT].sound),ballTouchesGround:new Y(e[G.BALLTOUCHESGROUND].sound)},this.sounds.bgm.loop=!0,this.properBGMVolume=.2,this.properSFXVolume=.35,this.adjustVolume()}adjustVolume(){for(const e in this.sounds)this.sounds[e].volume="bgm"===e?this.properBGMVolume:this.properSFXVolume}turnBGMVolume(e){let t;t=e?this.properBGMVolume:0,this.sounds.bgm.volume=t}turnSFXVolume(e){let t;t=e?this.properSFXVolume:0;for(const e in this.sounds)"bgm"!==e&&(this.sounds[e].volume=t)}muteAll(){U.eq.muteAll()}unmuteAll(){U.eq.unmuteAll()}}class Y{constructor(e){this.center=e,this.left=U.$u.from(e.url),this.right=U.$u.from(e.url);const t=new U.u8.StereoFilter(0),s=new U.u8.StereoFilter(-.75),i=new U.u8.StereoFilter(.75);this.center.filters=[t],this.left.filters=[s],this.right.filters=[i]}set volume(e){this.center.volume=e,this.left.volume=e,this.right.volume=e}set loop(e){this.center.loop=e,this.left.loop=e,this.right.loop=e}play(e=0){0===e?this.center.play():-1===e?this.left.play():1===e&&this.right.play()}stop(){this.center.stop(),this.left.stop(),this.right.stop()}}class j{constructor(e,t){this.view={intro:new A(t),menu:new T(t),game:new D(t),fadeInOut:new W(t)},e.addChild(this.view.intro.container),e.addChild(this.view.menu.container),e.addChild(this.view.game.container),e.addChild(this.view.fadeInOut.black),this.view.intro.visible=!1,this.view.menu.visible=!1,this.view.game.visible=!1,this.view.fadeInOut.visible=!1,this.audio=new X(t),this.physics=new w(!0,!0),this.keyboardArray=[new F("KeyD","KeyG","KeyR","KeyV","KeyZ","KeyF"),new F("ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Enter")],this.normalFPS=25,this.slowMotionFPS=5,this.SLOW_MOTION_FRAMES_NUM=6,this.slowMotionFramesLeft=0,this.slowMotionNumOfSkippedFrames=0,this.selectedWithWho=0,this.scores=[0,0],this.winningScore=15,this.gameEnded=!1,this.roundEnded=!1,this.isPlayer2Serve=!1,this.frameCounter=0,this.frameTotal={intro:165,afterMenuSelection:15,beforeStartOfNewGame:15,startOfNewGame:71,afterEndOfRound:5,beforeStartOfNextRound:30,gameEnd:211},this.noInputFrameCounter=0,this.noInputFrameTotal={menu:225},this.paused=!1,this.isStereoSound=!0,this._isPracticeMode=!1,this.state=this.intro}gameLoop(){if(!0!==this.paused){if(this.slowMotionFramesLeft>0){if(this.slowMotionNumOfSkippedFrames++,this.slowMotionNumOfSkippedFrames%Math.round(this.normalFPS/this.slowMotionFPS)!=0)return;this.slowMotionFramesLeft--,this.slowMotionNumOfSkippedFrames=0}this.keyboardArray[0].getInput(),this.keyboardArray[1].getInput(),this.state()}}intro(){0===this.frameCounter&&(this.view.intro.visible=!0,this.view.fadeInOut.setBlackAlphaTo(0),this.audio.sounds.bgm.stop()),this.view.intro.drawMark(this.frameCounter),this.frameCounter++,1!==this.keyboardArray[0].powerHit&&1!==this.keyboardArray[1].powerHit||(this.frameCounter=0,this.view.intro.visible=!1,this.state=this.menu),this.frameCounter>=this.frameTotal.intro&&(this.frameCounter=0,this.view.intro.visible=!1,this.state=this.menu)}menu(){if(0===this.frameCounter&&(this.view.menu.visible=!0,this.view.fadeInOut.setBlackAlphaTo(0),this.selectedWithWho=0,this.view.menu.selectWithWho(this.selectedWithWho)),this.view.menu.drawFightMessage(this.frameCounter),this.view.menu.drawSachisoft(this.frameCounter),this.view.menu.drawSittingPikachuTiles(this.frameCounter),this.view.menu.drawPikachuVolleyballMessage(this.frameCounter),this.view.menu.drawPokemonMessage(this.frameCounter),this.view.menu.drawWithWhoMessages(this.frameCounter),this.frameCounter++,this.frameCounter<71&&(1===this.keyboardArray[0].powerHit||1===this.keyboardArray[1].powerHit))this.frameCounter=71;else if(!(this.frameCounter<=71)){if(-1!==this.keyboardArray[0].yDirection&&-1!==this.keyboardArray[1].yDirection||1!==this.selectedWithWho?1!==this.keyboardArray[0].yDirection&&1!==this.keyboardArray[1].yDirection||0!==this.selectedWithWho?this.noInputFrameCounter++:(this.noInputFrameCounter=0,this.selectedWithWho=1,this.view.menu.selectWithWho(this.selectedWithWho),this.audio.sounds.pi.play()):(this.noInputFrameCounter=0,this.selectedWithWho=0,this.view.menu.selectWithWho(this.selectedWithWho),this.audio.sounds.pi.play()),1===this.keyboardArray[0].powerHit||1===this.keyboardArray[1].powerHit)return 1===this.selectedWithWho?(this.physics.player1.isComputer=!1,this.physics.player2.isComputer=!1):1===this.keyboardArray[0].powerHit?(this.physics.player1.isComputer=!1,this.physics.player2.isComputer=!0):1===this.keyboardArray[1].powerHit&&(this.physics.player1.isComputer=!0,this.physics.player2.isComputer=!1),this.audio.sounds.pikachu.play(),this.frameCounter=0,this.noInputFrameCounter=0,void(this.state=this.afterMenuSelection);this.noInputFrameCounter>=this.noInputFrameTotal.menu&&(this.physics.player1.isComputer=!0,this.physics.player2.isComputer=!0,this.frameCounter=0,this.noInputFrameCounter=0,this.state=this.afterMenuSelection)}}afterMenuSelection(){this.view.fadeInOut.changeBlackAlphaBy(1/16),this.frameCounter++,this.frameCounter>=this.frameTotal.afterMenuSelection&&(this.frameCounter=0,this.state=this.beforeStartOfNewGame)}beforeStartOfNewGame(){this.frameCounter++,this.frameCounter>=this.frameTotal.beforeStartOfNewGame&&(this.frameCounter=0,this.view.menu.visible=!1,this.state=this.startOfNewGame)}startOfNewGame(){0===this.frameCounter&&(this.view.game.visible=!0,this.gameEnded=!1,this.roundEnded=!1,this.isPlayer2Serve=!1,this.physics.player1.gameEnded=!1,this.physics.player1.isWinner=!1,this.physics.player2.gameEnded=!1,this.physics.player2.isWinner=!1,this.scores[0]=0,this.scores[1]=0,this.view.game.drawScoresToScoreBoards(this.scores),this.physics.player1.initializeForNewRound(),this.physics.player2.initializeForNewRound(),this.physics.ball.initializeForNewRound(this.isPlayer2Serve),this.view.game.drawPlayersAndBall(this.physics),this.view.fadeInOut.setBlackAlphaTo(1),this.audio.sounds.bgm.play()),this.view.game.drawGameStartMessage(this.frameCounter,this.frameTotal.startOfNewGame),this.view.game.drawCloudsAndWave(),this.view.fadeInOut.changeBlackAlphaBy(-1/17),this.frameCounter++,this.frameCounter>=this.frameTotal.startOfNewGame&&(this.frameCounter=0,this.view.fadeInOut.setBlackAlphaTo(0),this.state=this.round)}round(){const e=1===this.keyboardArray[0].powerHit||1===this.keyboardArray[1].powerHit;if(!0===this.physics.player1.isComputer&&!0===this.physics.player2.isComputer&&e)return this.frameCounter=0,this.view.game.visible=!1,void(this.state=this.intro);const t=this.physics.runEngineForNextFrame(this.keyboardArray);if(this.playSoundEffect(),this.view.game.drawPlayersAndBall(this.physics),this.view.game.drawCloudsAndWave(),!0===this.gameEnded)return this.view.game.drawGameEndMessage(this.frameCounter),this.frameCounter++,void((this.frameCounter>=this.frameTotal.gameEnd||this.frameCounter>=70&&e)&&(this.frameCounter=0,this.view.game.visible=!1,this.state=this.intro));t&&!1===this._isPracticeMode&&!1===this.roundEnded&&!1===this.gameEnded&&(this.physics.ball.punchEffectX=this.winningScore&&(this.gameEnded=!0,this.physics.player1.isWinner=!1,this.physics.player2.isWinner=!0,this.physics.player1.gameEnded=!0,this.physics.player2.gameEnded=!0)):(this.isPlayer2Serve=!1,this.scores[0]+=1,this.scores[0]>=this.winningScore&&(this.gameEnded=!0,this.physics.player1.isWinner=!0,this.physics.player2.isWinner=!1,this.physics.player1.gameEnded=!0,this.physics.player2.gameEnded=!0)),this.view.game.drawScoresToScoreBoards(this.scores),!1===this.roundEnded&&!1===this.gameEnded&&(this.slowMotionFramesLeft=this.SLOW_MOTION_FRAMES_NUM),this.roundEnded=!0),!0===this.roundEnded&&!1===this.gameEnded&&0===this.slowMotionFramesLeft&&(this.view.fadeInOut.changeBlackAlphaBy(1/16),this.state=this.afterEndOfRound)}afterEndOfRound(){this.view.fadeInOut.changeBlackAlphaBy(1/16),this.frameCounter++,this.frameCounter>=this.frameTotal.afterEndOfRound&&(this.frameCounter=0,this.state=this.beforeStartOfNextRound)}beforeStartOfNextRound(){0===this.frameCounter&&(this.view.fadeInOut.setBlackAlphaTo(1),this.view.game.drawReadyMessage(!1),this.physics.player1.initializeForNewRound(),this.physics.player2.initializeForNewRound(),this.physics.ball.initializeForNewRound(this.isPlayer2Serve),this.view.game.drawPlayersAndBall(this.physics)),this.view.game.drawCloudsAndWave(),this.view.fadeInOut.changeBlackAlphaBy(-1/16),this.frameCounter++,this.frameCounter%5==0&&this.view.game.toggleReadyMessage(),this.frameCounter>=this.frameTotal.beforeStartOfNextRound&&(this.frameCounter=0,this.view.game.drawReadyMessage(!1),this.view.fadeInOut.setBlackAlphaTo(0),this.roundEnded=!1,this.state=this.round)}playSoundEffect(){const e=this.audio;for(let t=0;t<2;t++){const s=this.physics[`player${t+1}`].sound;let i=0;this.isStereoSound&&(i=0===t?-1:1),!0===s.pipikachu&&(e.sounds.pipikachu.play(i),s.pipikachu=!1),!0===s.pika&&(e.sounds.pika.play(i),s.pika=!1),!0===s.chu&&(e.sounds.chu.play(i),s.chu=!1)}const t=this.physics.ball,s=t.sound;let i=0;this.isStereoSound&&(t.punchEffectXb&&(i=1)),!0===s.powerHit&&(e.sounds.powerHit.play(i),s.powerHit=!1),!0===s.ballTouchesGround&&(e.sounds.ballTouchesGround.play(i),s.ballTouchesGround=!1)}restart(){this.frameCounter=0,this.noInputFrameCounter=0,this.slowMotionFramesLeft=0,this.slowMotionNumOfSkippedFrames=0,this.view.menu.visible=!1,this.view.game.visible=!1,this.state=this.intro}get isPracticeMode(){return this._isPracticeMode}set isPracticeMode(e){this._isPracticeMode=e,this.view.game.scoreBoards[0].visible=!e,this.view.game.scoreBoards[1].visible=!e}}var z=s(248);const $={_precedence:0,pause:function(e,t){t>this._precedence&&(e.paused=!0,this._precedence=t)},resume:function(e,t){t===this._precedence&&(e.paused=!1,this._precedence=0)}};function q(e){if(e.graphic){const t=document.getElementById("graphic-sharp-btn"),s=document.getElementById("graphic-soft-btn");switch(e.graphic){case"sharp":s.classList.remove("selected"),t.classList.add("selected");break;case"soft":t.classList.remove("selected"),s.classList.add("selected")}}if(e.bgm){const t=document.getElementById("bgm-on-btn"),s=document.getElementById("bgm-off-btn");switch(e.bgm){case"on":s.classList.remove("selected"),t.classList.add("selected");break;case"off":t.classList.remove("selected"),s.classList.add("selected")}}if(e.sfx){const t=document.getElementById("stereo-btn"),s=document.getElementById("mono-btn"),i=document.getElementById("sfx-off-btn");switch(e.sfx){case"stereo":s.classList.remove("selected"),i.classList.remove("selected"),t.classList.add("selected");break;case"mono":i.classList.remove("selected"),t.classList.remove("selected"),s.classList.add("selected");break;case"off":t.classList.remove("selected"),s.classList.remove("selected"),i.classList.add("selected")}}if(e.speed){const t=document.getElementById("slow-speed-btn"),s=document.getElementById("medium-speed-btn"),i=document.getElementById("fast-speed-btn");switch(e.speed){case"slow":s.classList.remove("selected"),i.classList.remove("selected"),t.classList.add("selected");break;case"medium":i.classList.remove("selected"),t.classList.remove("selected"),s.classList.add("selected");break;case"fast":t.classList.remove("selected"),s.classList.remove("selected"),i.classList.add("selected")}}if(e.winningScore){const t=document.getElementById("winning-score-5-btn"),s=document.getElementById("winning-score-10-btn"),i=document.getElementById("winning-score-15-btn");switch(e.winningScore){case"5":s.classList.remove("selected"),i.classList.remove("selected"),t.classList.add("selected");break;case"10":i.classList.remove("selected"),t.classList.remove("selected"),s.classList.add("selected");break;case"15":t.classList.remove("selected"),s.classList.remove("selected"),i.classList.add("selected")}}}function Z(e,t){ee(),Q(e),document.getElementById(e).classList.toggle("show")?$.pause(t,1):$.resume(t,1)}function J(e,t){ee(),document.getElementById(e).classList.add("open"),document.getElementById(t).classList.add("show")}function Q(e){const t=document.getElementsByClassName("dropdown");for(let s=0;s{switch(q(s),s.graphic){case"sharp":document.getElementById("game-canvas").classList.remove("graphic-soft");break;case"soft":document.getElementById("game-canvas").classList.add("graphic-soft")}switch(s.bgm){case"on":e.audio.turnBGMVolume(!0);break;case"off":e.audio.turnBGMVolume(!1)}switch(s.sfx){case"stereo":e.audio.turnSFXVolume(!0),e.isStereoSound=!0;break;case"mono":e.audio.turnSFXVolume(!0),e.isStereoSound=!1;break;case"off":e.audio.turnSFXVolume(!1)}switch(s.speed){case"slow":e.normalFPS=20,t.maxFPS=e.normalFPS;break;case"medium":e.normalFPS=25,t.maxFPS=e.normalFPS;break;case"fast":e.normalFPS=30,t.maxFPS=e.normalFPS}switch(s.winningScore){case"5":e.winningScore=5;break;case"10":e.winningScore=10;break;case"15":e.winningScore=15}};s({graphic:z.Y.get("pv-offline-graphic"),bgm:z.Y.get("pv-offline-bgm"),sfx:z.Y.get("pv-offline-sfx"),speed:z.Y.get("pv-offline-speed"),winningScore:z.Y.get("pv-offline-winningScore")}),function(e,t){const s=document.getElementById("game-dropdown-btn"),i=document.getElementById("options-dropdown-btn"),n=document.getElementById("about-btn");s.disabled=!1,i.disabled=!1,n.disabled=!1;const o=document.getElementById("pause-btn");o.addEventListener("click",(()=>{o.classList.contains("selected")?(o.classList.remove("selected"),$.resume(e,3)):(o.classList.add("selected"),$.pause(e,3))})),document.getElementById("restart-btn").addEventListener("click",(()=>{o.classList.contains("selected")&&(o.classList.remove("selected"),$.resume(e,3)),e.restart()}));const a=document.getElementById("graphic-sharp-btn"),r=document.getElementById("graphic-soft-btn");a.addEventListener("click",(()=>{t({graphic:"sharp"})})),r.addEventListener("click",(()=>{t({graphic:"soft"})}));const l=document.getElementById("bgm-on-btn"),h=document.getElementById("bgm-off-btn");l.addEventListener("click",(()=>{t({bgm:"on"})})),h.addEventListener("click",(()=>{t({bgm:"off"})}));const c=document.getElementById("stereo-btn"),d=document.getElementById("mono-btn"),u=document.getElementById("sfx-off-btn");c.addEventListener("click",(()=>{t({sfx:"stereo"})})),d.addEventListener("click",(()=>{t({sfx:"mono"})})),u.addEventListener("click",(()=>{t({sfx:"off"})}));const m=document.getElementById("slow-speed-btn"),y=document.getElementById("medium-speed-btn"),p=document.getElementById("fast-speed-btn");m.addEventListener("click",(()=>{t({speed:"slow"})})),y.addEventListener("click",(()=>{t({speed:"medium"})})),p.addEventListener("click",(()=>{t({speed:"fast"})}));const b=document.getElementById("winning-score-5-btn"),g=document.getElementById("winning-score-10-btn"),f=document.getElementById("winning-score-15-btn"),w=document.getElementById("notice-box-1"),v=document.getElementById("notice-ok-btn-1"),E=document.getElementById("winning-score-in-notice-box-1");function x(t){return!(e.state!==e.round&&e.state!==e.afterEndOfRound&&e.state!==e.beforeStartOfNextRound||!(e.scores[0]>=t||e.scores[1]>=t))}const L=document.getElementById("notice-box-2"),k=document.getElementById("notice-ok-btn-2");b.addEventListener("click",(()=>{if(!b.classList.contains("selected"))return!0===e.isPracticeMode?(L.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):x(5)?(E.textContent="5",w.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):void t({winningScore:"5"})})),g.addEventListener("click",(()=>{if(!g.classList.contains("selected"))return!0===e.isPracticeMode?(L.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):x(10)?(E.textContent="10",w.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):void t({winningScore:"10"})})),f.addEventListener("click",(()=>{if(!f.classList.contains("selected"))return!0===e.isPracticeMode?(L.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):x(15)?(E.textContent="15",w.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):void t({winningScore:"15"})})),v.addEventListener("click",(()=>{w.classList.contains("hidden")||(w.classList.add("hidden"),s.disabled=!1,i.disabled=!1,n.disabled=!1,$.resume(e,2))})),k.addEventListener("click",(()=>{L.classList.contains("hidden")||(L.classList.add("hidden"),s.disabled=!1,i.disabled=!1,n.disabled=!1,$.resume(e,2))}));const C=document.getElementById("practice-mode-on-btn"),S=document.getElementById("practice-mode-off-btn");C.addEventListener("click",(()=>{S.classList.remove("selected"),C.classList.add("selected"),e.isPracticeMode=!0})),S.addEventListener("click",(()=>{C.classList.remove("selected"),S.classList.add("selected"),e.isPracticeMode=!1}));const B=document.getElementById("about-box"),I=document.getElementById("close-about-btn");n.addEventListener("click",(()=>{B.classList.contains("hidden")?(B.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,$.pause(e,2)):(B.classList.add("hidden"),s.disabled=!1,i.disabled=!1,$.resume(e,2))})),I.addEventListener("click",(()=>{B.classList.contains("hidden")||(B.classList.add("hidden"),s.disabled=!1,i.disabled=!1,$.resume(e,2))})),document.getElementById("reset-to-default-btn").addEventListener("click",(()=>{S.click(),t({graphic:"sharp",bgm:"on",sfx:"stereo",speed:"medium",winningScore:"15"})}))}(e,(e=>{s(e),(e=>{q(e),e.graphic&&z.Y.set("pv-offline-graphic",e.graphic),e.bgm&&z.Y.set("pv-offline-bgm",e.bgm),e.sfx&&z.Y.set("pv-offline-sfx",e.sfx),e.speed&&z.Y.set("pv-offline-speed",e.speed),e.winningScore&&z.Y.set("pv-offline-winningScore",e.winningScore)})(e)})),function(e){window.addEventListener("click",(t=>{t.target.matches(".dropdown-btn, .submenu-btn")||(ee(),Q(""),$.resume(e,1))})),document.getElementById("game-dropdown-btn").addEventListener("click",(()=>{Z("game-dropdown",e)})),document.getElementById("options-dropdown-btn").addEventListener("click",(()=>{Z("options-dropdown",e)})),document.getElementById("graphic-submenu-btn").addEventListener("mouseover",(()=>{J("graphic-submenu-btn","graphic-submenu")})),document.getElementById("bgm-submenu-btn").addEventListener("mouseover",(()=>{J("bgm-submenu-btn","bgm-submenu")})),document.getElementById("sfx-submenu-btn").addEventListener("mouseover",(()=>{J("sfx-submenu-btn","sfx-submenu")})),document.getElementById("speed-submenu-btn").addEventListener("mouseover",(()=>{J("speed-submenu-btn","speed-submenu")})),document.getElementById("winning-score-submenu-btn").addEventListener("mouseover",(()=>{J("winning-score-submenu-btn","winning-score-submenu")})),document.getElementById("practice-mode-submenu-btn").addEventListener("mouseover",(()=>{J("practice-mode-submenu-btn","practice-mode-submenu")})),document.getElementById("reset-to-default-btn").addEventListener("mouseover",(()=>{ee()})),document.getElementById("bgm-submenu-btn").addEventListener("click",(()=>{J("bgm-submenu-btn","bgm-submenu")})),document.getElementById("sfx-submenu-btn").addEventListener("click",(()=>{J("sfx-submenu-btn","sfx-submenu")})),document.getElementById("speed-submenu-btn").addEventListener("click",(()=>{J("speed-submenu-btn","speed-submenu")})),document.getElementById("winning-score-submenu-btn").addEventListener("click",(()=>{J("winning-score-submenu-btn","winning-score-submenu")})),document.getElementById("practice-mode-submenu-btn").addEventListener("click",(()=>{J("practice-mode-submenu-btn","practice-mode-submenu")})),document.getElementById("reset-to-default-btn").addEventListener("click",(()=>{ee()}))}(e),window.addEventListener("keydown",(e=>{if("Escape"===e.code){const t=document.getElementById("menu-bar");t.classList.contains("hidden")?t.classList.remove("hidden"):t.classList.add("hidden"),e.preventDefault()}else"Space"===e.code&&document.getElementById("about-box").classList.contains("hidden")&&e.preventDefault()})),document.addEventListener("visibilitychange",(function(){"visible"===document.visibilityState?e.audio.unmuteAll():e.audio.muteAll()}))})(e,ie),function(e){ie.maxFPS=e.normalFPS,ie.add((()=>{e.gameLoop(),te.render(se)})),ie.start()}(e)}!function(){const e=document.getElementById("loading-box"),t=document.getElementById("progress-bar");ne.onProgress.add((()=>{t.style.width=`${ne.progress}%`})),ne.onComplete.add((()=>{e.classList.add("hidden")}));const s=document.getElementById("about-box"),i=document.getElementById("about-btn"),n=document.getElementById("close-about-btn"),o=document.getElementById("game-dropdown-btn"),a=document.getElementById("options-dropdown-btn");o.disabled=!0,a.disabled=!0;const r=()=>{s.classList.contains("hidden")||(s.classList.add("hidden"),i.disabled=!0),i.getElementsByClassName("text-play")[0].classList.add("hidden"),i.getElementsByClassName("text-about")[0].classList.remove("hidden"),i.classList.remove("glow"),n.getElementsByClassName("text-play")[0].classList.add("hidden"),n.getElementsByClassName("text-close")[0].classList.remove("hidden"),n.classList.remove("glow"),ne.load(oe),e.classList.remove("hidden"),i.removeEventListener("click",r),n.removeEventListener("click",r)};i.addEventListener("click",r),n.addEventListener("click",r)}()},248:(e,t,s)=>{s.d(t,{Y:()=>i});const i={get:e=>{let t=null;try{t=localStorage.getItem(e)}catch(e){console.error(e)}return t},set:(e,t)=>{try{localStorage.setItem(e,t)}catch(e){console.error(e)}}}}},e=>{e.O(0,[407],(()=>(372,e(e.s=372)))),e.O()}]); +"use strict";(self.webpackChunkpikachu_volleyball=self.webpackChunkpikachu_volleyball||[]).push([[179],{982:(e,t,s)=>{s.d(t,{d:()=>i});const i={SPRITE_SHEET:"../resources/assets/images/sprite_sheet.json",TEXTURES:{},SOUNDS:{}},n=i.TEXTURES;n.PIKACHU=(e,t)=>`pikachu/pikachu_${e}_${t}.png`,n.BALL=e=>`ball/ball_${e}.png`,n.NUMBER=e=>`number/number_${e}.png`,n.SKY_BLUE="objects/sky_blue.png",n.MOUNTAIN="objects/mountain.png",n.GROUND_RED="objects/ground_red.png",n.GROUND_LINE="objects/ground_line.png",n.GROUND_LINE_LEFT_MOST="objects/ground_line_leftmost.png",n.GROUND_LINE_RIGHT_MOST="objects/ground_line_rightmost.png",n.GROUND_YELLOW="objects/ground_yellow.png",n.NET_PILLAR_TOP="objects/net_pillar_top.png",n.NET_PILLAR="objects/net_pillar.png",n.SHADOW="objects/shadow.png",n.BALL_HYPER="ball/ball_hyper.png",n.BALL_TRAIL="ball/ball_trail.png",n.BALL_PUNCH="ball/ball_punch.png",n.CLOUD="objects/cloud.png",n.WAVE="objects/wave.png",n.BLACK="objects/black.png",n.SACHISOFT="messages/common/sachisoft.png",n.READY="messages/common/ready.png",n.GAME_END="messages/common/game_end.png",n.MARK="messages/ja/mark.png",n.POKEMON="messages/ja/pokemon.png",n.PIKACHU_VOLLEYBALL="messages/ja/pikachu_volleyball.png",n.FIGHT="messages/ja/fight.png",n.WITH_COMPUTER="messages/ja/with_computer.png",n.WITH_FRIEND="messages/ja/with_friend.png",n.GAME_START="messages/ja/game_start.png",n.SITTING_PIKACHU="sitting_pikachu.png";const o=i.SOUNDS;o.BGM="../resources/assets/sounds/bgm.mp3",o.PIPIKACHU="../resources/assets/sounds/WAVE140_1.wav",o.PIKA="../resources/assets/sounds/WAVE141_1.wav",o.CHU="../resources/assets/sounds/WAVE142_1.wav",o.PI="../resources/assets/sounds/WAVE143_1.wav",o.PIKACHU="../resources/assets/sounds/WAVE144_1.wav",o.POWERHIT="../resources/assets/sounds/WAVE145_1.wav",o.BALLTOUCHESGROUND="../resources/assets/sounds/WAVE146_1.wav"},372:(e,t,s)=>{var i=s(319),n=s(680),o=s(710),a=s(858),r=s(585),l=s(550),h=s(126),c=s(679),d=s(93),u=s(196),m=s(619);s(971);function y(){return Math.floor(32768*Math.random())}const p=432,b=216,g=244,f=252;class w{constructor(e,t){this.player1=new v(!1,e),this.player2=new v(!0,t),this.ball=new E(!1)}runEngineForNextFrame(e){const t=function(e,t,s,i){const n=function(e){e.previousPreviousX=e.previousX,e.previousPreviousY=e.previousY,e.previousX=e.x,e.previousY=e.y;let t=e.fineRotation+(e.xVelocity/2|0);t<0?t+=50:t>50&&(t+=-50),e.fineRotation=t,e.rotation=e.fineRotation/10|0;const s=e.x+e.xVelocity;(s<20||s>p)&&(e.xVelocity=-e.xVelocity);let i=e.y+e.yVelocity;return i<0&&(e.yVelocity=1),Math.abs(e.x-b)<25&&e.y>176&&(e.y<=192?e.yVelocity>0&&(e.yVelocity=-e.yVelocity):e.xf?(e.sound.ballTouchesGround=!0,e.yVelocity=-e.yVelocity,e.punchEffectX=e.x,e.y=f,e.punchEffectRadius=20,e.punchEffectY=272,!0):(e.y=i,e.x=e.x+e.xVelocity,e.yVelocity+=1,!1)}(s);let o,a;for(let n=0;n<2;n++)0===n?(o=e,a=t):(o=t,a=e),C(s),L(o,i[n],a,s);for(let n=0;n<2;n++)o=0===n?e:t,!0===x(s,o.x,o.y)?!1===o.isCollisionWithBallHappened&&(k(s,o.x,i[n],o.state),o.isCollisionWithBallHappened=!0):o.isCollisionWithBallHappened=!1;return n}(this.player1,this.player2,this.ball,e);return t}}class v{constructor(e,t){this.isPlayer2=e,this.isComputer=t,this.initializeForNewRound(),this.divingDirection=0,this.lyingDownDurationLeft=-1,this.isWinner=!1,this.gameEnded=!1,this.computerWhereToStandBy=0,this.sound={pipikachu:!1,pika:!1,chu:!1}}initializeForNewRound(){this.x=36,this.isPlayer2&&(this.x=396),this.y=g,this.yVelocity=0,this.isCollisionWithBallHappened=!1,this.state=0,this.frameNumber=0,this.normalStatusArmSwingDirection=1,this.delayBeforeNextFrame=0,this.computerBoldness=y()%5}}class E{constructor(e){this.initializeForNewRound(e),this.expectedLandingPointX=0,this.rotation=0,this.fineRotation=0,this.punchEffectX=0,this.punchEffectY=0,this.previousX=0,this.previousPreviousX=0,this.previousY=0,this.previousPreviousY=0,this.sound={powerHit:!1,ballTouchesGround:!1}}initializeForNewRound(e){this.x=56,!0===e&&(this.x=376),this.y=0,this.xVelocity=0,this.yVelocity=1,this.punchEffectRadius=0,this.isPowerHit=!1}}function x(e,t,s){let i=e.x-t;return Math.abs(i)<=32&&(i=e.y-s,Math.abs(i)<=32)}function L(e,t,s,i){if(!0===e.isComputer&&function(e,t,s,i){i.xDirection=0,i.yDirection=0,i.powerHit=0;let n=t.expectedLandingPointX;if(Math.abs(t.x-e.x)>100&&Math.abs(t.xVelocity)=Number(e.isPlayer2)*p+b)&&0===e.computerWhereToStandBy&&(n=s+108)}if(Math.abs(n-e.x)>e.computerBoldness+8?e.x-36&&t.y<10*e.computerBoldness+84&&t.yVelocity>0&&(i.yDirection=-1);const s=Number(e.isPlayer2)*b,n=(Number(e.isPlayer2)+1)*b;t.expectedLandingPointX>s&&t.expectedLandingPointX5*e.computerBoldness+64&&t.x>s&&t.x174&&(i.powerHit=1,e.x8&&(e.x-1;n--)for(let o=-1;o<2;o++){const a=S(n,o,t);if((a<=Number(e.isPlayer2)*b||a>=Number(e.isPlayer2)*p+b)&&Math.abs(a-s.x)>64)return i.xDirection=n,i.yDirection=o,!0}else for(let n=1;n>-1;n--)for(let o=1;o>-2;o--){const a=S(n,o,t);if((a<=Number(e.isPlayer2)*b||a>=Number(e.isPlayer2)*p+b)&&Math.abs(a-s.x)>64)return i.xDirection=n,i.yDirection=o,!0}return!1}(e,t,s,i);!0===n&&(i.powerHit=1,Math.abs(s.x-e.x)<80&&-1!==i.yDirection&&(i.yDirection=-1))}}(e,i,s,t),4===e.state)return e.lyingDownDurationLeft+=-1,void(e.lyingDownDurationLeft<-1&&(e.state=0));let n=0;e.state<5&&(n=e.state<3?6*t.xDirection:8*e.divingDirection);const o=e.x+n;e.x=o,!1===e.isPlayer2?o<32?e.x=32:o>184&&(e.x=184):o<248?e.x=248:o>400&&(e.x=400),e.state<3&&-1===t.yDirection&&e.y===g&&(e.yVelocity=-16,e.state=1,e.frameNumber=0,e.sound.chu=!0);const a=e.y+e.yVelocity;if(e.y=a,ag&&(e.yVelocity=0,e.y=g,e.frameNumber=0,3===e.state?(e.state=4,e.frameNumber=0,e.lyingDownDurationLeft=3):e.state=0),1===t.powerHit&&(1===e.state?(e.delayBeforeNextFrame=5,e.frameNumber=0,e.state=2,e.sound.pika=!0):0===e.state&&0!==t.xDirection&&(e.state=3,e.frameNumber=0,e.divingDirection=t.xDirection,e.yVelocity=-5,e.sound.chu=!0)),1===e.state)e.frameNumber=(e.frameNumber+1)%3;else if(2===e.state)e.delayBeforeNextFrame<1?(e.frameNumber+=1,e.frameNumber>4&&(e.frameNumber=0,e.state=1)):e.delayBeforeNextFrame-=1;else if(0===e.state&&(e.delayBeforeNextFrame+=1,e.delayBeforeNextFrame>3)){e.delayBeforeNextFrame=0;const t=e.frameNumber+e.normalStatusArmSwingDirection;(t<0||t>4)&&(e.normalStatusArmSwingDirection=-e.normalStatusArmSwingDirection),e.frameNumber=e.frameNumber+e.normalStatusArmSwingDirection}!0===e.gameEnded&&(0===e.state&&(!0===e.isWinner?(e.state=5,e.sound.pipikachu=!0):e.state=6,e.delayBeforeNextFrame=0,e.frameNumber=0),function(e){!0===e.gameEnded&&e.frameNumber<4&&(e.delayBeforeNextFrame+=1,e.delayBeforeNextFrame>4&&(e.delayBeforeNextFrame=0,e.frameNumber+=1))}(e))}function k(e,t,s,i){e.xt&&(e.xVelocity=Math.abs(e.x-t)/3|0),0===e.xVelocity&&(e.xVelocity=y()%3-1);const n=Math.abs(e.yVelocity);e.yVelocity=-n,n<15&&(e.yVelocity=-15),2===i?(e.xp)&&(t.xVelocity=-t.xVelocity),t.y+t.yVelocity<0&&(t.yVelocity=1),Math.abs(t.x-b)<25&&t.y>176&&(t.y<192?t.yVelocity>0&&(t.yVelocity=-t.yVelocity):t.xf||s>=1e3)break;t.x=t.x+t.xVelocity,t.yVelocity+=1}e.expectedLandingPointX=t.x}function S(e,t,s){const i={x:s.x,y:s.y,xVelocity:s.xVelocity,yVelocity:s.yVelocity};i.xp)&&(i.xVelocity=-i.xVelocity),i.y+i.yVelocity<0&&(i.yVelocity=1),Math.abs(i.x-b)<25&&i.y>176&&i.yVelocity>0&&(i.yVelocity=-i.yVelocity),i.y=i.y+i.yVelocity,i.y>f||n>=1e3)return i.x;i.x=i.x+i.xVelocity,i.yVelocity+=1}}var B=s(408),I=s(33);class P{constructor(){this.topLeftPointX=y()%500-68,this.topLeftPointY=y()%152,this.topLeftPointXVelocity=1+y()%2,this.sizeDiffTurnNumber=y()%11}get sizeDiff(){return 5-Math.abs(this.sizeDiffTurnNumber-5)}get spriteTopLeftPointX(){return this.topLeftPointX-this.sizeDiff}get spriteTopLeftPointY(){return this.topLeftPointY-this.sizeDiff}get spriteWidth(){return 48+2*this.sizeDiff}get spriteHeight(){return 24+2*this.sizeDiff}}class M{constructor(){this.verticalCoord=0,this.verticalCoordVelocity=2,this.yCoords=[];for(let e=0;e<27;e++)this.yCoords.push(314)}}var V=s(982);const N=V.d.TEXTURES;class A{constructor(e){const t=e[V.d.SPRITE_SHEET].textures;this.mark=_(t,N.MARK,.5,.5),this.mark.x=216,this.mark.y=152,this.container=new r.W2,this.container.addChild(this.mark)}get visible(){return this.container.visible}set visible(e){this.container.visible=e}drawMark(e){const t=this.mark;0!==e?e<100?t.alpha=Math.min(1,t.alpha+.04):e>=100&&(t.alpha=Math.max(0,t.alpha-.04)):t.alpha=0}}class T{constructor(e){const t=e[V.d.SPRITE_SHEET].textures;this.messages={pokemon:_(t,N.POKEMON,0,0),pikachuVolleyball:_(t,N.PIKACHU_VOLLEYBALL,0,0),withWho:[_(t,N.WITH_COMPUTER,0,0),_(t,N.WITH_FRIEND,0,0)],sachisoft:_(t,N.SACHISOFT,0,0),fight:_(t,N.FIGHT,0,0)},this.sittingPikachuTilesContainer=function(e){const t=new r.W2,s=e[N.SITTING_PIKACHU],i=s.width,n=s.height;let o;for(let e=0;e70&&(this.messages.sachisoft.alpha=1)}drawSittingPikachuTiles(e){0===e&&(this.sittingPikachuTilesContainer.visible=!0,this.sittingPikachuTilesContainer.alpha=0);const t=this.sittingPikachuTilesContainer.getChildAt(0).texture.height;this.sittingPikachuTilesDisplacement=(this.sittingPikachuTilesDisplacement+2)%t,this.sittingPikachuTilesContainer.x=-this.sittingPikachuTilesDisplacement,this.sittingPikachuTilesContainer.y=-this.sittingPikachuTilesDisplacement,e>30&&(this.sittingPikachuTilesContainer.alpha=Math.min(1,this.sittingPikachuTilesContainer.alpha+.04)),e>70&&(this.sittingPikachuTilesContainer.alpha=1)}drawPikachuVolleyballMessage(e){if(0!==e)if(e>30&&(this.messages.pikachuVolleyball.visible=!0),e>30&&e<=44){const t=195-15*(e-30);this.messages.pikachuVolleyball.x=140+t}else e>44&&e<=55?(this.messages.pikachuVolleyball.x=140,this.messages.pikachuVolleyball.width=200-15*(e-44)):e>55&&e<=71?(this.messages.pikachuVolleyball.x=140,this.messages.pikachuVolleyball.width=40+15*(e-55)):e>71&&(this.messages.pikachuVolleyball.x=140,this.messages.pikachuVolleyball.width=this.messages.pikachuVolleyball.texture.width);else this.messages.pikachuVolleyball.visible=!1}drawPokemonMessage(e){0!==e?e>71&&(this.messages.pokemon.visible=!0):this.messages.pokemon.visible=!1}drawWithWhoMessages(e){const t=this.messages.withWho,s=t[0].texture.width,i=t[0].texture.height;if(0!==e){if(e>70){this.selectedWithWhoMessageSizeIncrement<10&&(this.selectedWithWhoMessageSizeIncrement+=1);for(let e=0;e<2;e++){const n=Number(this.selectedWithWho===e),o=n*(this.selectedWithWhoMessageSizeIncrement+2),a=n*this.selectedWithWhoMessageSizeIncrement;t[e].visible=!0,t[e].x=216-s/2-o,t[e].y=184+30*e-a,t[e].width=s+2*o,t[e].height=i+2*a}}}else for(let e=0;e<2;e++)t[e].visible=!1}selectWithWho(e){this.selectedWithWho=e,this.selectedWithWhoMessageSizeIncrement=2}}class D{constructor(e){const t=e[V.d.SPRITE_SHEET].textures;this.bgContainer=function(e){const t=new r.W2;let s,i=e[N.SKY_BLUE];for(let e=0;e<12;e++)for(let n=0;n<27;n++)s=new I.j(i),R(t,s,16*n,16*e);i=e[N.MOUNTAIN],s=new I.j(i),R(t,s,0,188),i=e[N.GROUND_RED];for(let e=0;e<27;e++)s=new I.j(i),R(t,s,16*e,248);i=e[N.GROUND_LINE];for(let e=1;e<26;e++)s=new I.j(i),R(t,s,16*e,264);i=e[N.GROUND_LINE_LEFT_MOST],s=new I.j(i),R(t,s,0,264),i=e[N.GROUND_LINE_RIGHT_MOST],s=new I.j(i),R(t,s,416,264),i=e[N.GROUND_YELLOW];for(let e=0;e<2;e++)for(let n=0;n<27;n++)s=new I.j(i),R(t,s,16*n,280+16*e);i=e[N.NET_PILLAR_TOP],s=new I.j(i),R(t,s,213,176),i=e[N.NET_PILLAR];for(let e=0;e<12;e++)s=new I.j(i),R(t,s,213,184+8*e);return t}(t);const s=function(e){const t=(t,s)=>e[N.PIKACHU(t,s)],s=[];for(let e=0;e<7;e++)if(3===e)s.push(t(e,0)),s.push(t(e,1));else if(4===e)s.push(t(e,0));else for(let i=0;i<5;i++)s.push(t(e,i));const i=new B.K(s,!1),n=new B.K(s,!1);return i.anchor.x=.5,i.anchor.y=.5,n.anchor.x=.5,n.anchor.y=.5,[i,n]}(t);this.player1=s[0],this.player2=s[1],this.ball=function(e){const t=t=>e[N.BALL(t)],s=[t(0),t(1),t(2),t(3),t(4),t("hyper")],i=new B.K(s,!1);return i.anchor.x=.5,i.anchor.y=.5,i}(t),this.ballHyper=_(t,N.BALL_HYPER,.5,.5),this.ballTrail=_(t,N.BALL_TRAIL,.5,.5),this.punch=_(t,N.BALL_PUNCH,.5,.5),this.scoreBoards=[O(t),O(t)],this.shadows={forPlayer1:_(t,N.SHADOW,.5,.5),forPlayer2:_(t,N.SHADOW,.5,.5),forBall:_(t,N.SHADOW,.5,.5)},this.messages={gameStart:_(t,N.GAME_START,0,0),ready:_(t,N.READY,0,0),gameEnd:_(t,N.GAME_END,0,0)},this.cloudContainer=function(e){const t=new r.W2,s=e[N.CLOUD];for(let e=0;e<10;e++){const e=new I.j(s);e.anchor.x=0,e.anchor.y=0,t.addChild(e)}return t}(t),this.waveContainer=function(e){const t=new r.W2,s=e[N.WAVE];for(let e=0;e<27;e++)R(t,new I.j(s),16*e,0);return t}(t),this.container=new r.W2,this.container.addChild(this.bgContainer),this.container.addChild(this.cloudContainer),this.container.addChild(this.waveContainer),this.container.addChild(this.shadows.forPlayer1),this.container.addChild(this.shadows.forPlayer2),this.container.addChild(this.shadows.forBall),this.container.addChild(this.player1),this.container.addChild(this.player2),this.container.addChild(this.ballTrail),this.container.addChild(this.ballHyper),this.container.addChild(this.ball),this.container.addChild(this.punch),this.container.addChild(this.scoreBoards[0]),this.container.addChild(this.scoreBoards[1]),this.container.addChild(this.messages.gameStart),this.container.addChild(this.messages.ready),this.container.addChild(this.messages.gameEnd),this.bgContainer.x=0,this.bgContainer.y=0,this.cloudContainer.x=0,this.cloudContainer.y=0,this.waveContainer.x=0,this.waveContainer.y=0,this.messages.ready.x=176,this.messages.ready.y=38,this.scoreBoards[0].x=14,this.scoreBoards[0].y=10,this.scoreBoards[1].x=354,this.scoreBoards[1].y=10,this.shadows.forPlayer1.y=273,this.shadows.forPlayer2.y=273,this.shadows.forBall.y=273,this.initializeVisibles(),this.cloudArray=[];for(let e=0;e<10;e++)this.cloudArray.push(new P);this.wave=new M}get visible(){return this.container.visible}set visible(e){this.container.visible=e,!1===e&&this.initializeVisibles()}initializeVisibles(){for(const e in this.messages)this.messages[e].visible=!1}drawPlayersAndBall(e){const t=e.player1,s=e.player2,i=e.ball;this.player1.x=t.x,this.player1.y=t.y,3===t.state||4===t.state?this.player1.scale.x=-1===t.divingDirection?-1:1:this.player1.scale.x=1,this.shadows.forPlayer1.x=t.x,this.player2.x=s.x,this.player2.y=s.y,3===s.state||4===s.state?this.player2.scale.x=1===s.divingDirection?1:-1:this.player2.scale.x=-1,this.shadows.forPlayer2.x=s.x;const n=H(t.state,t.frameNumber),o=H(s.state,s.frameNumber);this.player1.gotoAndStop(n),this.player2.gotoAndStop(o),this.ball.x=i.x,this.ball.y=i.y,this.shadows.forBall.x=i.x,this.ball.gotoAndStop(i.rotation),i.punchEffectRadius>0?(i.punchEffectRadius-=2,this.punch.width=2*i.punchEffectRadius,this.punch.height=2*i.punchEffectRadius,this.punch.x=i.punchEffectX,this.punch.y=i.punchEffectY,this.punch.visible=!0):this.punch.visible=!1,!0===i.isPowerHit?(this.ballHyper.x=i.previousX,this.ballHyper.y=i.previousY,this.ballTrail.x=i.previousPreviousX,this.ballTrail.y=i.previousPreviousY,this.ballHyper.visible=!0,this.ballTrail.visible=!0):(this.ballHyper.visible=!1,this.ballTrail.visible=!1)}drawScoresToScoreBoards(e){for(let t=0;t<2;t++){const s=this.scoreBoards[t],i=e[t],n=s.getChildAt(0),o=s.getChildAt(1);n.gotoAndStop(i%10),o.gotoAndStop(Math.floor(i/10)%10),o.visible=i>=10}}drawCloudsAndWave(){const e=this.cloudArray,t=this.wave;!function(e,t){for(let t=0;t<10;t++)e[t].topLeftPointX+=e[t].topLeftPointXVelocity,e[t].topLeftPointX>432&&(e[t].topLeftPointX=-68,e[t].topLeftPointY=y()%152,e[t].topLeftPointXVelocity=1+y()%2),e[t].sizeDiffTurnNumber=(e[t].sizeDiffTurnNumber+1)%11;t.verticalCoord+=t.verticalCoordVelocity,t.verticalCoord>32?(t.verticalCoord=32,t.verticalCoordVelocity=-1):t.verticalCoord<0&&t.verticalCoordVelocity<0&&(t.verticalCoordVelocity=2,t.verticalCoord=-y()%40);for(let e=0;e<27;e++)t.yCoords[e]=314-t.verticalCoord+y()%3}(e,t);for(let t=0;t<10;t++){const s=e[t],i=this.cloudContainer.getChildAt(t);i.x=s.spriteTopLeftPointX,i.y=s.spriteTopLeftPointY,i.width=s.spriteWidth,i.height=s.spriteHeight}for(let e=0;e<27;e++)this.waveContainer.getChildAt(e).y=t.yCoords[e]}drawGameStartMessage(e,t){if(0===e)this.messages.gameStart.visible=!0;else if(e>=t-1)return void(this.messages.gameStart.visible=!1);const s=this.messages.gameStart,i=s.texture.width,n=s.texture.height,o=Math.floor(i*e/50),a=Math.floor(n*e/50);s.x=216-o,s.y=50+2*a,s.width=2*o,s.height=2*a}drawReadyMessage(e){this.messages.ready.visible=e}toggleReadyMessage(){this.messages.ready.visible=!this.messages.ready.visible}drawGameEndMessage(e){const t=this.messages.gameEnd,s=t.texture.width,i=t.texture.height;if(0===e&&(t.visible=!0),e<50){const n=2*Math.floor((50-e)*s/50),o=2*Math.floor((50-e)*i/50);t.x=216-s/2-n,t.y=50-o,t.width=s+2*n,t.height=i+2*o}else t.x=216-s/2,t.y=50,t.width=s,t.height=i}}class W{constructor(e){const t=e[V.d.SPRITE_SHEET].textures;this.black=_(t,N.BLACK,0,0),this.black.width=432,this.black.height=304,this.black.x=0,this.black.y=0,this.black.alpha=1}get visible(){return this.black.visible}set visible(e){this.black.visible=e}setBlackAlphaTo(e){this.black.alpha=e,0===this.black.alpha?this.black.visible=!1:this.black.visible=!0}changeBlackAlphaBy(e){this.black.alpha=e>=0?Math.min(1,this.black.alpha+e):Math.max(0,this.black.alpha+e),0===this.black.alpha?this.black.visible=!1:this.black.visible=!0}}function _(e,t,s,i){const n=new I.j(e[t]);return n.anchor.x=s,n.anchor.y=i,n}function O(e){const t=[];for(let i=0;i<10;i++)t.push((s=i,e[N.NUMBER(s)]));var s;const i=[null,null];i[0]=new B.K(t,!1),i[1]=new B.K(t,!1);const n=new r.W2;return R(n,i[0],32,0),R(n,i[1],0,0),n.setChildIndex(i[0],0),n.setChildIndex(i[1],1),n}function R(e,t,s,i){e.addChild(t),t.anchor.x=0,t.anchor.y=0,t.x=s,t.y=i}function H(e,t){return e<4?5*e+t:4===e?17+t:e>4?18+5*(e-5)+t:void 0}class F extends class{constructor(){this.xDirection=0,this.yDirection=0,this.powerHit=0}}{constructor(e,t,s,i,n,o=null){super(),this.powerHitKeyIsDownPrevious=!1,this.leftKey=new K(e),this.rightKey=new K(t),this.upKey=new K(s),this.downKey=new K(i),this.powerHitKey=new K(n),this.downRightKey=new K(o)}getInput(){this.leftKey.isDown?this.xDirection=-1:this.rightKey.isDown||this.downRightKey&&this.downRightKey.isDown?this.xDirection=1:this.xDirection=0,this.upKey.isDown?this.yDirection=-1:this.downKey.isDown||this.downRightKey&&this.downRightKey.isDown?this.yDirection=1:this.yDirection=0;const e=this.powerHitKey.isDown;!this.powerHitKeyIsDownPrevious&&e?this.powerHit=1:this.powerHit=0,this.powerHitKeyIsDownPrevious=e}subscribe(){this.leftKey.subscribe(),this.rightKey.subscribe(),this.upKey.subscribe(),this.downKey.subscribe(),this.powerHitKey.subscribe(),this.downRightKey.subscribe()}unsubscribe(){this.leftKey.unsubscribe(),this.rightKey.unsubscribe(),this.upKey.unsubscribe(),this.downKey.unsubscribe(),this.powerHitKey.unsubscribe(),this.downRightKey.unsubscribe()}}class K{constructor(e){this.value=e,this.isDown=!1,this.isUp=!0,this.downListener=this.downHandler.bind(this),this.upListener=this.upHandler.bind(this),this.subscribe()}downHandler(e){e.code===this.value&&(this.isDown=!0,this.isUp=!1,e.preventDefault())}upHandler(e){e.code===this.value&&(this.isDown=!1,this.isUp=!0,e.preventDefault())}subscribe(){window.addEventListener("keyup",this.upListener),window.addEventListener("keydown",this.downListener)}unsubscribe(){window.removeEventListener("keydown",this.downListener),window.removeEventListener("keyup",this.upListener),this.isDown=!1,this.isUp=!0}}var U=s(292);const G=V.d.SOUNDS;class X{constructor(e){this.sounds={bgm:new Y(e[G.BGM].sound),pipikachu:new Y(e[G.PIPIKACHU].sound),pika:new Y(e[G.PIKA].sound),chu:new Y(e[G.CHU].sound),pi:new Y(e[G.PI].sound),pikachu:new Y(e[G.PIKACHU].sound),powerHit:new Y(e[G.POWERHIT].sound),ballTouchesGround:new Y(e[G.BALLTOUCHESGROUND].sound)},this.sounds.bgm.loop=!0,this.properBGMVolume=.2,this.properSFXVolume=.35,this.adjustVolume()}adjustVolume(){for(const e in this.sounds)this.sounds[e].volume="bgm"===e?this.properBGMVolume:this.properSFXVolume}turnBGMVolume(e){let t;t=e?this.properBGMVolume:0,this.sounds.bgm.volume=t}turnSFXVolume(e){let t;t=e?this.properSFXVolume:0;for(const e in this.sounds)"bgm"!==e&&(this.sounds[e].volume=t)}muteAll(){U.eq.muteAll()}unmuteAll(){U.eq.unmuteAll()}}class Y{constructor(e){this.center=e,this.left=U.$u.from(e.url),this.right=U.$u.from(e.url);const t=new U.u8.StereoFilter(0),s=new U.u8.StereoFilter(-.75),i=new U.u8.StereoFilter(.75);this.center.filters=[t],this.left.filters=[s],this.right.filters=[i]}set volume(e){this.center.volume=e,this.left.volume=e,this.right.volume=e}set loop(e){this.center.loop=e,this.left.loop=e,this.right.loop=e}play(e=0){0===e?this.center.play():-1===e?this.left.play():1===e&&this.right.play()}stop(){this.center.stop(),this.left.stop(),this.right.stop()}}class j{constructor(e,t){this.view={intro:new A(t),menu:new T(t),game:new D(t),fadeInOut:new W(t)},e.addChild(this.view.intro.container),e.addChild(this.view.menu.container),e.addChild(this.view.game.container),e.addChild(this.view.fadeInOut.black),this.view.intro.visible=!1,this.view.menu.visible=!1,this.view.game.visible=!1,this.view.fadeInOut.visible=!1,this.audio=new X(t),this.physics=new w(!0,!0),this.keyboardArray=[new F("KeyD","KeyG","KeyR","KeyV","KeyZ","KeyF"),new F("ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Enter")],this.normalFPS=25,this.slowMotionFPS=5,this.SLOW_MOTION_FRAMES_NUM=6,this.slowMotionFramesLeft=0,this.slowMotionNumOfSkippedFrames=0,this.selectedWithWho=0,this.scores=[0,0],this.winningScore=15,this.gameEnded=!1,this.roundEnded=!1,this.isPlayer2Serve=!1,this.frameCounter=0,this.frameTotal={intro:165,afterMenuSelection:15,beforeStartOfNewGame:15,startOfNewGame:71,afterEndOfRound:5,beforeStartOfNextRound:30,gameEnd:211},this.noInputFrameCounter=0,this.noInputFrameTotal={menu:225},this.paused=!1,this.isStereoSound=!0,this._isPracticeMode=!1,this.state=this.intro}gameLoop(){if(!0!==this.paused){if(this.slowMotionFramesLeft>0){if(this.slowMotionNumOfSkippedFrames++,this.slowMotionNumOfSkippedFrames%Math.round(this.normalFPS/this.slowMotionFPS)!=0)return;this.slowMotionFramesLeft--,this.slowMotionNumOfSkippedFrames=0}this.keyboardArray[0].getInput(),this.keyboardArray[1].getInput(),this.state()}}intro(){0===this.frameCounter&&(this.view.intro.visible=!0,this.view.fadeInOut.setBlackAlphaTo(0),this.audio.sounds.bgm.stop()),this.view.intro.drawMark(this.frameCounter),this.frameCounter++,1!==this.keyboardArray[0].powerHit&&1!==this.keyboardArray[1].powerHit||(this.frameCounter=0,this.view.intro.visible=!1,this.state=this.menu),this.frameCounter>=this.frameTotal.intro&&(this.frameCounter=0,this.view.intro.visible=!1,this.state=this.menu)}menu(){if(0===this.frameCounter&&(this.view.menu.visible=!0,this.view.fadeInOut.setBlackAlphaTo(0),this.selectedWithWho=0,this.view.menu.selectWithWho(this.selectedWithWho)),this.view.menu.drawFightMessage(this.frameCounter),this.view.menu.drawSachisoft(this.frameCounter),this.view.menu.drawSittingPikachuTiles(this.frameCounter),this.view.menu.drawPikachuVolleyballMessage(this.frameCounter),this.view.menu.drawPokemonMessage(this.frameCounter),this.view.menu.drawWithWhoMessages(this.frameCounter),this.frameCounter++,this.frameCounter<71&&(1===this.keyboardArray[0].powerHit||1===this.keyboardArray[1].powerHit))this.frameCounter=71;else if(!(this.frameCounter<=71)){if(-1!==this.keyboardArray[0].yDirection&&-1!==this.keyboardArray[1].yDirection||1!==this.selectedWithWho?1!==this.keyboardArray[0].yDirection&&1!==this.keyboardArray[1].yDirection||0!==this.selectedWithWho?this.noInputFrameCounter++:(this.noInputFrameCounter=0,this.selectedWithWho=1,this.view.menu.selectWithWho(this.selectedWithWho),this.audio.sounds.pi.play()):(this.noInputFrameCounter=0,this.selectedWithWho=0,this.view.menu.selectWithWho(this.selectedWithWho),this.audio.sounds.pi.play()),1===this.keyboardArray[0].powerHit||1===this.keyboardArray[1].powerHit)return 1===this.selectedWithWho?(this.physics.player1.isComputer=!1,this.physics.player2.isComputer=!1):1===this.keyboardArray[0].powerHit?(this.physics.player1.isComputer=!1,this.physics.player2.isComputer=!0):1===this.keyboardArray[1].powerHit&&(this.physics.player1.isComputer=!0,this.physics.player2.isComputer=!1),this.audio.sounds.pikachu.play(),this.frameCounter=0,this.noInputFrameCounter=0,void(this.state=this.afterMenuSelection);this.noInputFrameCounter>=this.noInputFrameTotal.menu&&(this.physics.player1.isComputer=!0,this.physics.player2.isComputer=!0,this.frameCounter=0,this.noInputFrameCounter=0,this.state=this.afterMenuSelection)}}afterMenuSelection(){this.view.fadeInOut.changeBlackAlphaBy(1/16),this.frameCounter++,this.frameCounter>=this.frameTotal.afterMenuSelection&&(this.frameCounter=0,this.state=this.beforeStartOfNewGame)}beforeStartOfNewGame(){this.frameCounter++,this.frameCounter>=this.frameTotal.beforeStartOfNewGame&&(this.frameCounter=0,this.view.menu.visible=!1,this.state=this.startOfNewGame)}startOfNewGame(){0===this.frameCounter&&(this.view.game.visible=!0,this.gameEnded=!1,this.roundEnded=!1,this.isPlayer2Serve=!1,this.physics.player1.gameEnded=!1,this.physics.player1.isWinner=!1,this.physics.player2.gameEnded=!1,this.physics.player2.isWinner=!1,this.scores[0]=0,this.scores[1]=0,this.view.game.drawScoresToScoreBoards(this.scores),this.physics.player1.initializeForNewRound(),this.physics.player2.initializeForNewRound(),this.physics.ball.initializeForNewRound(this.isPlayer2Serve),this.view.game.drawPlayersAndBall(this.physics),this.view.fadeInOut.setBlackAlphaTo(1),this.audio.sounds.bgm.play()),this.view.game.drawGameStartMessage(this.frameCounter,this.frameTotal.startOfNewGame),this.view.game.drawCloudsAndWave(),this.view.fadeInOut.changeBlackAlphaBy(-1/17),this.frameCounter++,this.frameCounter>=this.frameTotal.startOfNewGame&&(this.frameCounter=0,this.view.fadeInOut.setBlackAlphaTo(0),this.state=this.round)}round(){const e=1===this.keyboardArray[0].powerHit||1===this.keyboardArray[1].powerHit;if(!0===this.physics.player1.isComputer&&!0===this.physics.player2.isComputer&&e)return this.frameCounter=0,this.view.game.visible=!1,void(this.state=this.intro);const t=this.physics.runEngineForNextFrame(this.keyboardArray);if(this.playSoundEffect(),this.view.game.drawPlayersAndBall(this.physics),this.view.game.drawCloudsAndWave(),!0===this.gameEnded)return this.view.game.drawGameEndMessage(this.frameCounter),this.frameCounter++,void((this.frameCounter>=this.frameTotal.gameEnd||this.frameCounter>=70&&e)&&(this.frameCounter=0,this.view.game.visible=!1,this.state=this.intro));t&&!1===this._isPracticeMode&&!1===this.roundEnded&&!1===this.gameEnded&&(this.physics.ball.punchEffectX=this.winningScore&&(this.gameEnded=!0,this.physics.player1.isWinner=!1,this.physics.player2.isWinner=!0,this.physics.player1.gameEnded=!0,this.physics.player2.gameEnded=!0)):(this.isPlayer2Serve=!1,this.scores[0]+=1,this.scores[0]>=this.winningScore&&(this.gameEnded=!0,this.physics.player1.isWinner=!0,this.physics.player2.isWinner=!1,this.physics.player1.gameEnded=!0,this.physics.player2.gameEnded=!0)),this.view.game.drawScoresToScoreBoards(this.scores),!1===this.roundEnded&&!1===this.gameEnded&&(this.slowMotionFramesLeft=this.SLOW_MOTION_FRAMES_NUM),this.roundEnded=!0),!0===this.roundEnded&&!1===this.gameEnded&&0===this.slowMotionFramesLeft&&(this.view.fadeInOut.changeBlackAlphaBy(1/16),this.state=this.afterEndOfRound)}afterEndOfRound(){this.view.fadeInOut.changeBlackAlphaBy(1/16),this.frameCounter++,this.frameCounter>=this.frameTotal.afterEndOfRound&&(this.frameCounter=0,this.state=this.beforeStartOfNextRound)}beforeStartOfNextRound(){0===this.frameCounter&&(this.view.fadeInOut.setBlackAlphaTo(1),this.view.game.drawReadyMessage(!1),this.physics.player1.initializeForNewRound(),this.physics.player2.initializeForNewRound(),this.physics.ball.initializeForNewRound(this.isPlayer2Serve),this.view.game.drawPlayersAndBall(this.physics)),this.view.game.drawCloudsAndWave(),this.view.fadeInOut.changeBlackAlphaBy(-1/16),this.frameCounter++,this.frameCounter%5==0&&this.view.game.toggleReadyMessage(),this.frameCounter>=this.frameTotal.beforeStartOfNextRound&&(this.frameCounter=0,this.view.game.drawReadyMessage(!1),this.view.fadeInOut.setBlackAlphaTo(0),this.roundEnded=!1,this.state=this.round)}playSoundEffect(){const e=this.audio;for(let t=0;t<2;t++){const s=this.physics[`player${t+1}`].sound;let i=0;this.isStereoSound&&(i=0===t?-1:1),!0===s.pipikachu&&(e.sounds.pipikachu.play(i),s.pipikachu=!1),!0===s.pika&&(e.sounds.pika.play(i),s.pika=!1),!0===s.chu&&(e.sounds.chu.play(i),s.chu=!1)}const t=this.physics.ball,s=t.sound;let i=0;this.isStereoSound&&(t.punchEffectXb&&(i=1)),!0===s.powerHit&&(e.sounds.powerHit.play(i),s.powerHit=!1),!0===s.ballTouchesGround&&(e.sounds.ballTouchesGround.play(i),s.ballTouchesGround=!1)}restart(){this.frameCounter=0,this.noInputFrameCounter=0,this.slowMotionFramesLeft=0,this.slowMotionNumOfSkippedFrames=0,this.view.menu.visible=!1,this.view.game.visible=!1,this.state=this.intro}get isPracticeMode(){return this._isPracticeMode}set isPracticeMode(e){this._isPracticeMode=e,this.view.game.scoreBoards[0].visible=!e,this.view.game.scoreBoards[1].visible=!e}}var z=s(248);const $={_precedence:0,pause:function(e,t){t>this._precedence&&(e.paused=!0,this._precedence=t)},resume:function(e,t){t===this._precedence&&(e.paused=!1,this._precedence=0)}};function q(e){if(e.graphic){const t=document.getElementById("graphic-sharp-btn"),s=document.getElementById("graphic-soft-btn");switch(e.graphic){case"sharp":s.classList.remove("selected"),t.classList.add("selected");break;case"soft":t.classList.remove("selected"),s.classList.add("selected")}}if(e.bgm){const t=document.getElementById("bgm-on-btn"),s=document.getElementById("bgm-off-btn");switch(e.bgm){case"on":s.classList.remove("selected"),t.classList.add("selected");break;case"off":t.classList.remove("selected"),s.classList.add("selected")}}if(e.sfx){const t=document.getElementById("stereo-btn"),s=document.getElementById("mono-btn"),i=document.getElementById("sfx-off-btn");switch(e.sfx){case"stereo":s.classList.remove("selected"),i.classList.remove("selected"),t.classList.add("selected");break;case"mono":i.classList.remove("selected"),t.classList.remove("selected"),s.classList.add("selected");break;case"off":t.classList.remove("selected"),s.classList.remove("selected"),i.classList.add("selected")}}if(e.speed){const t=document.getElementById("slow-speed-btn"),s=document.getElementById("medium-speed-btn"),i=document.getElementById("fast-speed-btn");switch(e.speed){case"slow":s.classList.remove("selected"),i.classList.remove("selected"),t.classList.add("selected");break;case"medium":i.classList.remove("selected"),t.classList.remove("selected"),s.classList.add("selected");break;case"fast":t.classList.remove("selected"),s.classList.remove("selected"),i.classList.add("selected")}}if(e.winningScore){const t=document.getElementById("winning-score-5-btn"),s=document.getElementById("winning-score-10-btn"),i=document.getElementById("winning-score-15-btn");switch(e.winningScore){case"5":s.classList.remove("selected"),i.classList.remove("selected"),t.classList.add("selected");break;case"10":i.classList.remove("selected"),t.classList.remove("selected"),s.classList.add("selected");break;case"15":t.classList.remove("selected"),s.classList.remove("selected"),i.classList.add("selected")}}}function Z(e,t){ee(),Q(e),document.getElementById(e).classList.toggle("show")?$.pause(t,1):$.resume(t,1)}function J(e,t){ee(),document.getElementById(e).classList.add("open"),document.getElementById(t).classList.add("show")}function Q(e){const t=document.getElementsByClassName("dropdown");for(let s=0;s{switch(q(s),s.graphic){case"sharp":document.getElementById("game-canvas").classList.remove("graphic-soft");break;case"soft":document.getElementById("game-canvas").classList.add("graphic-soft")}switch(s.bgm){case"on":e.audio.turnBGMVolume(!0);break;case"off":e.audio.turnBGMVolume(!1)}switch(s.sfx){case"stereo":e.audio.turnSFXVolume(!0),e.isStereoSound=!0;break;case"mono":e.audio.turnSFXVolume(!0),e.isStereoSound=!1;break;case"off":e.audio.turnSFXVolume(!1)}switch(s.speed){case"slow":e.normalFPS=20,t.maxFPS=e.normalFPS;break;case"medium":e.normalFPS=25,t.maxFPS=e.normalFPS;break;case"fast":e.normalFPS=30,t.maxFPS=e.normalFPS}switch(s.winningScore){case"5":e.winningScore=5;break;case"10":e.winningScore=10;break;case"15":e.winningScore=15}};s({graphic:z.Y.get("pv-offline-graphic"),bgm:z.Y.get("pv-offline-bgm"),sfx:z.Y.get("pv-offline-sfx"),speed:z.Y.get("pv-offline-speed"),winningScore:z.Y.get("pv-offline-winningScore")}),function(e,t){const s=document.getElementById("game-dropdown-btn"),i=document.getElementById("options-dropdown-btn"),n=document.getElementById("about-btn");s.disabled=!1,i.disabled=!1,n.disabled=!1;const o=document.getElementById("pause-btn");o.addEventListener("click",(()=>{o.classList.contains("selected")?(o.classList.remove("selected"),$.resume(e,3)):(o.classList.add("selected"),$.pause(e,3))})),document.getElementById("restart-btn").addEventListener("click",(()=>{o.classList.contains("selected")&&(o.classList.remove("selected"),$.resume(e,3)),e.restart()}));const a=document.getElementById("graphic-sharp-btn"),r=document.getElementById("graphic-soft-btn");a.addEventListener("click",(()=>{t({graphic:"sharp"})})),r.addEventListener("click",(()=>{t({graphic:"soft"})}));const l=document.getElementById("bgm-on-btn"),h=document.getElementById("bgm-off-btn");l.addEventListener("click",(()=>{t({bgm:"on"})})),h.addEventListener("click",(()=>{t({bgm:"off"})}));const c=document.getElementById("stereo-btn"),d=document.getElementById("mono-btn"),u=document.getElementById("sfx-off-btn");c.addEventListener("click",(()=>{t({sfx:"stereo"})})),d.addEventListener("click",(()=>{t({sfx:"mono"})})),u.addEventListener("click",(()=>{t({sfx:"off"})}));const m=document.getElementById("slow-speed-btn"),y=document.getElementById("medium-speed-btn"),p=document.getElementById("fast-speed-btn");m.addEventListener("click",(()=>{t({speed:"slow"})})),y.addEventListener("click",(()=>{t({speed:"medium"})})),p.addEventListener("click",(()=>{t({speed:"fast"})}));const b=document.getElementById("winning-score-5-btn"),g=document.getElementById("winning-score-10-btn"),f=document.getElementById("winning-score-15-btn"),w=document.getElementById("notice-box-1"),v=document.getElementById("notice-ok-btn-1"),E=document.getElementById("winning-score-in-notice-box-1");function x(t){return!(e.state!==e.round&&e.state!==e.afterEndOfRound&&e.state!==e.beforeStartOfNextRound||!(e.scores[0]>=t||e.scores[1]>=t))}const L=document.getElementById("notice-box-2"),k=document.getElementById("notice-ok-btn-2");b.addEventListener("click",(()=>{if(!b.classList.contains("selected"))return!0===e.isPracticeMode?(L.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):x(5)?(E.textContent="5",w.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):void t({winningScore:"5"})})),g.addEventListener("click",(()=>{if(!g.classList.contains("selected"))return!0===e.isPracticeMode?(L.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):x(10)?(E.textContent="10",w.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):void t({winningScore:"10"})})),f.addEventListener("click",(()=>{if(!f.classList.contains("selected"))return!0===e.isPracticeMode?(L.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):x(15)?(E.textContent="15",w.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,n.disabled=!0,void $.pause(e,2)):void t({winningScore:"15"})})),v.addEventListener("click",(()=>{w.classList.contains("hidden")||(w.classList.add("hidden"),s.disabled=!1,i.disabled=!1,n.disabled=!1,$.resume(e,2))})),k.addEventListener("click",(()=>{L.classList.contains("hidden")||(L.classList.add("hidden"),s.disabled=!1,i.disabled=!1,n.disabled=!1,$.resume(e,2))}));const C=document.getElementById("practice-mode-on-btn"),S=document.getElementById("practice-mode-off-btn");C.addEventListener("click",(()=>{S.classList.remove("selected"),C.classList.add("selected"),e.isPracticeMode=!0})),S.addEventListener("click",(()=>{C.classList.remove("selected"),S.classList.add("selected"),e.isPracticeMode=!1}));const B=document.getElementById("about-box"),I=document.getElementById("close-about-btn");n.addEventListener("click",(()=>{B.classList.contains("hidden")?(B.classList.remove("hidden"),s.disabled=!0,i.disabled=!0,$.pause(e,2)):(B.classList.add("hidden"),s.disabled=!1,i.disabled=!1,$.resume(e,2))})),I.addEventListener("click",(()=>{B.classList.contains("hidden")||(B.classList.add("hidden"),s.disabled=!1,i.disabled=!1,$.resume(e,2))})),document.getElementById("reset-to-default-btn").addEventListener("click",(()=>{S.click(),t({graphic:"sharp",bgm:"on",sfx:"stereo",speed:"medium",winningScore:"15"})}))}(e,(e=>{s(e),(e=>{q(e),e.graphic&&z.Y.set("pv-offline-graphic",e.graphic),e.bgm&&z.Y.set("pv-offline-bgm",e.bgm),e.sfx&&z.Y.set("pv-offline-sfx",e.sfx),e.speed&&z.Y.set("pv-offline-speed",e.speed),e.winningScore&&z.Y.set("pv-offline-winningScore",e.winningScore)})(e)})),function(e){window.addEventListener("click",(t=>{t.target.matches(".dropdown-btn, .submenu-btn")||(ee(),Q(""),$.resume(e,1))})),document.getElementById("game-dropdown-btn").addEventListener("click",(()=>{Z("game-dropdown",e)})),document.getElementById("options-dropdown-btn").addEventListener("click",(()=>{Z("options-dropdown",e)})),document.getElementById("graphic-submenu-btn").addEventListener("mouseover",(()=>{J("graphic-submenu-btn","graphic-submenu")})),document.getElementById("bgm-submenu-btn").addEventListener("mouseover",(()=>{J("bgm-submenu-btn","bgm-submenu")})),document.getElementById("sfx-submenu-btn").addEventListener("mouseover",(()=>{J("sfx-submenu-btn","sfx-submenu")})),document.getElementById("speed-submenu-btn").addEventListener("mouseover",(()=>{J("speed-submenu-btn","speed-submenu")})),document.getElementById("winning-score-submenu-btn").addEventListener("mouseover",(()=>{J("winning-score-submenu-btn","winning-score-submenu")})),document.getElementById("practice-mode-submenu-btn").addEventListener("mouseover",(()=>{J("practice-mode-submenu-btn","practice-mode-submenu")})),document.getElementById("reset-to-default-btn").addEventListener("mouseover",(()=>{ee()})),document.getElementById("bgm-submenu-btn").addEventListener("click",(()=>{J("bgm-submenu-btn","bgm-submenu")})),document.getElementById("sfx-submenu-btn").addEventListener("click",(()=>{J("sfx-submenu-btn","sfx-submenu")})),document.getElementById("speed-submenu-btn").addEventListener("click",(()=>{J("speed-submenu-btn","speed-submenu")})),document.getElementById("winning-score-submenu-btn").addEventListener("click",(()=>{J("winning-score-submenu-btn","winning-score-submenu")})),document.getElementById("practice-mode-submenu-btn").addEventListener("click",(()=>{J("practice-mode-submenu-btn","practice-mode-submenu")})),document.getElementById("reset-to-default-btn").addEventListener("click",(()=>{ee()}))}(e),window.addEventListener("keydown",(e=>{if("Escape"===e.code){const t=document.getElementById("menu-bar");t.classList.contains("hidden")?t.classList.remove("hidden"):t.classList.add("hidden"),e.preventDefault()}else"Space"===e.code&&document.getElementById("about-box").classList.contains("hidden")&&e.preventDefault()})),document.addEventListener("visibilitychange",(function(){"visible"===document.visibilityState?e.audio.unmuteAll():e.audio.muteAll()}))})(e,ie),function(e){ie.maxFPS=e.normalFPS,ie.add((()=>{e.gameLoop(),te.render(se)})),ie.start()}(e)}!function(){const e=document.getElementById("loading-box"),t=document.getElementById("progress-bar");ne.onProgress.add((()=>{t.style.width=`${ne.progress}%`})),ne.onComplete.add((()=>{e.classList.add("hidden")}));const s=document.getElementById("about-box"),i=document.getElementById("about-btn"),n=document.getElementById("close-about-btn"),o=document.getElementById("game-dropdown-btn"),a=document.getElementById("options-dropdown-btn");o.disabled=!0,a.disabled=!0;const r=()=>{s.classList.contains("hidden")||(s.classList.add("hidden"),i.disabled=!0),i.getElementsByClassName("text-play")[0].classList.add("hidden"),i.getElementsByClassName("text-about")[0].classList.remove("hidden"),i.classList.remove("glow"),n.getElementsByClassName("text-play")[0].classList.add("hidden"),n.getElementsByClassName("text-close")[0].classList.remove("hidden"),n.classList.remove("glow"),ne.load(oe),e.classList.remove("hidden"),i.removeEventListener("click",r),n.removeEventListener("click",r)};i.addEventListener("click",r),n.addEventListener("click",r)}()},248:(e,t,s)=>{s.d(t,{Y:()=>i});const i={get:e=>{let t=null;try{t=localStorage.getItem(e)}catch(e){console.error(e)}return t},set:(e,t)=>{try{localStorage.setItem(e,t)}catch(e){console.error(e)}}}}},e=>{e.O(0,[407],(()=>(372,e(e.s=372)))),e.O()}]); //# sourceMappingURL=main.bundle.js.map \ No newline at end of file diff --git a/main.bundle.js.map b/main.bundle.js.map index 8b03a84..de96df6 100644 --- a/main.bundle.js.map +++ b/main.bundle.js.map @@ -1 +1 @@ -{"version":3,"file":"main.bundle.js","mappings":"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","sources":["webpack://pikachu-volleyball/./src/resources/js/assets_path.js","webpack://pikachu-volleyball/./src/resources/js/rand.js","webpack://pikachu-volleyball/./src/resources/js/physics.js","webpack://pikachu-volleyball/./src/resources/js/cloud_and_wave.js","webpack://pikachu-volleyball/./src/resources/js/view.js","webpack://pikachu-volleyball/./src/resources/js/keyboard.js","webpack://pikachu-volleyball/./src/resources/js/audio.js","webpack://pikachu-volleyball/./src/resources/js/pikavolley.js","webpack://pikachu-volleyball/./src/resources/js/ui.js","webpack://pikachu-volleyball/./src/resources/js/main.js","webpack://pikachu-volleyball/./src/resources/js/utils/local_storage_wrapper.js"],"sourcesContent":["/**\n * Manages the paths (file locations) of the game assets.\n */\n'use strict';\n\nexport const ASSETS_PATH = {\n SPRITE_SHEET: '../resources/assets/images/sprite_sheet.json',\n TEXTURES: {},\n SOUNDS: {},\n};\n\nconst TEXTURES = ASSETS_PATH.TEXTURES;\nTEXTURES.PIKACHU = (i, j) => `pikachu/pikachu_${i}_${j}.png`;\nTEXTURES.BALL = (s) => `ball/ball_${s}.png`;\nTEXTURES.NUMBER = (n) => `number/number_${n}.png`;\n\nTEXTURES.SKY_BLUE = 'objects/sky_blue.png';\nTEXTURES.MOUNTAIN = 'objects/mountain.png';\nTEXTURES.GROUND_RED = 'objects/ground_red.png';\nTEXTURES.GROUND_LINE = 'objects/ground_line.png';\nTEXTURES.GROUND_LINE_LEFT_MOST = 'objects/ground_line_leftmost.png';\nTEXTURES.GROUND_LINE_RIGHT_MOST = 'objects/ground_line_rightmost.png';\nTEXTURES.GROUND_YELLOW = 'objects/ground_yellow.png';\nTEXTURES.NET_PILLAR_TOP = 'objects/net_pillar_top.png';\nTEXTURES.NET_PILLAR = 'objects/net_pillar.png';\nTEXTURES.SHADOW = 'objects/shadow.png';\nTEXTURES.BALL_HYPER = 'ball/ball_hyper.png';\nTEXTURES.BALL_TRAIL = 'ball/ball_trail.png';\nTEXTURES.BALL_PUNCH = 'ball/ball_punch.png';\nTEXTURES.CLOUD = 'objects/cloud.png';\nTEXTURES.WAVE = 'objects/wave.png';\nTEXTURES.BLACK = 'objects/black.png';\n\nTEXTURES.SACHISOFT = 'messages/common/sachisoft.png';\nTEXTURES.READY = 'messages/common/ready.png';\nTEXTURES.GAME_END = 'messages/common/game_end.png';\n\nTEXTURES.MARK = 'messages/ja/mark.png';\nTEXTURES.POKEMON = 'messages/ja/pokemon.png';\nTEXTURES.PIKACHU_VOLLEYBALL = 'messages/ja/pikachu_volleyball.png';\nTEXTURES.FIGHT = 'messages/ja/fight.png';\nTEXTURES.WITH_COMPUTER = 'messages/ja/with_computer.png';\nTEXTURES.WITH_FRIEND = 'messages/ja/with_friend.png';\nTEXTURES.GAME_START = 'messages/ja/game_start.png';\n\nTEXTURES.SITTING_PIKACHU = 'sitting_pikachu.png';\n\nconst SOUNDS = ASSETS_PATH.SOUNDS;\nSOUNDS.BGM = '../resources/assets/sounds/bgm.mp3';\nSOUNDS.PIPIKACHU = '../resources/assets/sounds/WAVE140_1.wav';\nSOUNDS.PIKA = '../resources/assets/sounds/WAVE141_1.wav';\nSOUNDS.CHU = '../resources/assets/sounds/WAVE142_1.wav';\nSOUNDS.PI = '../resources/assets/sounds/WAVE143_1.wav';\nSOUNDS.PIKACHU = '../resources/assets/sounds/WAVE144_1.wav';\nSOUNDS.POWERHIT = '../resources/assets/sounds/WAVE145_1.wav';\nSOUNDS.BALLTOUCHESGROUND = '../resources/assets/sounds/WAVE146_1.wav';\n","/**\n * This module contains random number generator used for the game\n */\n'use strict';\n/** @typedef {function():number} RNG */\n\n/** @type {RNG} custom RNG (random number generator) function which generates a random number in [0, 1] */\nlet customRng = null;\n\n/**\n * Return random integer in [0, 32767]\n *\n * The machine code of the original game use \"_rand()\" function in Visual Studio 1988 Library.\n * I could't find out how this function works exactly.\n * But, anyhow, it should be a function that generate a random number.\n * I decided to use custom rand function which generates random integer in [0, 32767]\n * which follows rand() function in Visual Studio 2017 Library.\n *\n * By default, it uses the function \"Math.random\" for generating a random number.\n * A custom RNG function can used by setting the \"customRng\" as the custom RNG function.\n *\n * @return {number} random integer\n */\nexport function rand() {\n if (customRng === null) {\n return Math.floor(32768 * Math.random());\n }\n return Math.floor(32768 * customRng());\n}\n\n/**\n * Set custom RNG function\n * @param {RNG} rng\n */\nexport function setCustomRng(rng) {\n customRng = rng;\n}\n","/**\n * The Model part in the MVC pattern\n *\n * It is the core module which acts as a physics engine.\n * This physics engine calculates the movements of the ball and the players (Pikachus).\n *\n * It was gained by reverse engineering the original game.\n * The address of each function in the original machine code is specified at the comment above each function.\n * ex) FUN_00403dd0 means the original function at the address 00403dd0.\n *\n *\n * ** Some useful infos below **\n *\n * Ground width: 432 = 0x1B0\n * Ground height: 304 = 0x130\n *\n * X position coordinate: [0, 432], right-direction increasing\n * Y position coordinate: [0, 304], down-direction increasing\n *\n * Ball radius: 20 = 0x14\n * Ball diameter: 40 = 0x28\n *\n * Player half-width: 32 = 0x20\n * Player half-height: 32 = 0x20\n * Player width: 64 = 0x40\n * Player height: 64 = 0x40\n *\n */\n'use strict';\nimport { rand } from './rand.js';\n\n/** @constant @type {number} ground width */\nconst GROUND_WIDTH = 432;\n/** @constant @type {number} ground half-width, it is also the net pillar x coordinate */\nexport const GROUND_HALF_WIDTH = (GROUND_WIDTH / 2) | 0; // integer division\n/** @constant @type {number} player (Pikachu) length: width = height = 64 */\nconst PLAYER_LENGTH = 64;\n/** @constant @type {number} player half length */\nconst PLAYER_HALF_LENGTH = (PLAYER_LENGTH / 2) | 0; // integer division\n/** @constant @type {number} player's y coordinate when they are touching ground */\nconst PLAYER_TOUCHING_GROUND_Y_COORD = 244;\n/** @constant @type {number} ball's radius */\nconst BALL_RADIUS = 20;\n/** @constant @type {number} ball's y coordinate when it is touching ground */\nconst BALL_TOUCHING_GROUND_Y_COORD = 252;\n/** @constant @type {number} net pillar's half width (this value is on this physics engine only, not on the sprite pixel size) */\nconst NET_PILLAR_HALF_WIDTH = 25;\n/** @constant @type {number} net pillar top's top side y coordinate */\nconst NET_PILLAR_TOP_TOP_Y_COORD = 176;\n/** @constant @type {number} net pillar top's bottom side y coordinate (this value is on this physics engine only) */\nconst NET_PILLAR_TOP_BOTTOM_Y_COORD = 192;\n\n/**\n * It's for to limit the looping number of the infinite loops.\n * This constant is not in the original machine code. (The original machine code does not limit the looping number.)\n *\n * In the original ball x coord range setting (ball x coord in [20, 432]), the infinite loops in\n * {@link calculateExpectedLandingPointXFor} function and {@link expectedLandingPointXWhenPowerHit} function seems to be always terminated soon.\n * But if the ball x coord range is edited, for example, to [20, 432 - 20] for left-right symmetry,\n * it is observed that the infinite loop in {@link expectedLandingPointXWhenPowerHit} does not terminate.\n * So for safety, this infinite loop limit is included for the infinite loops mentioned above.\n * @constant @type {number}\n */\nconst INFINITE_LOOP_LIMIT = 1000;\n\n/**\n * Class representing a pack of physical objects i.e. players and ball\n * whose physical values are calculated and set by {@link physicsEngine} function\n */\nexport class PikaPhysics {\n /**\n * Create a physics pack\n * @param {boolean} isPlayer1Computer Is player on the left (player 1) controlled by computer?\n * @param {boolean} isPlayer2Computer Is player on the right (player 2) controlled by computer?\n */\n constructor(isPlayer1Computer, isPlayer2Computer) {\n this.player1 = new Player(false, isPlayer1Computer);\n this.player2 = new Player(true, isPlayer2Computer);\n this.ball = new Ball(false);\n }\n\n /**\n * run {@link physicsEngine} function with this physics object and user input\n *\n * @param {PikaUserInput[]} userInputArray userInputArray[0]: PikaUserInput object for player 1, userInputArray[1]: PikaUserInput object for player 2\n * @return {boolean} Is ball touching ground?\n */\n runEngineForNextFrame(userInputArray) {\n const isBallTouchingGround = physicsEngine(\n this.player1,\n this.player2,\n this.ball,\n userInputArray\n );\n return isBallTouchingGround;\n }\n}\n\n/**\n * Class (or precisely, Interface) representing user input (from keyboard or joystick, whatever)\n */\nexport class PikaUserInput {\n constructor() {\n /** @type {number} 0: no horizontal-direction input, -1: left-direction input, 1: right-direction input */\n this.xDirection = 0;\n /** @type {number} 0: no vertical-direction input, -1: up-direction input, 1: down-direction input */\n this.yDirection = 0;\n /** @type {number} 0: auto-repeated or no power hit input, 1: not auto-repeated power hit input */\n this.powerHit = 0;\n }\n}\n\n/**\n * Class representing a player\n *\n * Player 1 property address: 00411F28 -> +28 -> +10 -> +C -> ...\n * Player 2 property address: 00411F28 -> +28 -> +10 -> +10 -> ...\n * The \"...\" part is written on the line comment at the right side of each property.\n * e.g. address to player1.isPlayer: 00411F28 -> +28 -> +10 -> +C -> +A0\n * e.g. address to player2.isComputer: 00411F28 -> +28 -> +10 -> +10 -> +A4\n *\n * For initial values: refer to FUN_000403a90 && FUN_00401f40\n */\nclass Player {\n /**\n * create a player\n * @param {boolean} isPlayer2 Is this player on the right side?\n * @param {boolean} isComputer Is this player controlled by computer?\n */\n constructor(isPlayer2, isComputer) {\n /** @type {boolean} Is this player on the right side? */\n this.isPlayer2 = isPlayer2; // 0xA0\n /** @type {boolean} Is controlled by computer? */\n this.isComputer = isComputer; // 0xA4\n this.initializeForNewRound();\n\n /** @type {number} -1: left, 0: no diving, 1: right */\n this.divingDirection = 0; // 0xB4\n /** @type {number} */\n this.lyingDownDurationLeft = -1; // 0xB8\n /** @type {boolean} */\n this.isWinner = false; // 0xD0\n /** @type {boolean} */\n this.gameEnded = false; // 0xD4\n\n /**\n * It flips randomly to 0 or 1 by the {@link letComputerDecideUserInput} function (FUN_00402360)\n * when ball is hanging around on the other player's side.\n * If it is 0, computer player stands by around the middle point of their side.\n * If it is 1, computer player stands by adjacent to the net.\n * @type {number} 0 or 1\n */\n this.computerWhereToStandBy = 0; // 0xDC\n\n /**\n * This property is not in the player pointers of the original source code.\n * But for sound effect (especially for stereo sound),\n * it is convenient way to give sound property to a Player.\n * The original name is stereo sound.\n * @type {Object.}\n */\n this.sound = {\n pipikachu: false,\n pika: false,\n chu: false,\n };\n }\n\n /**\n * initialize for new round\n */\n initializeForNewRound() {\n /** @type {number} x coord */\n this.x = 36; // 0xA8 // initialized to 36 (player1) or 396 (player2)\n if (this.isPlayer2) {\n this.x = GROUND_WIDTH - 36;\n }\n /** @type {number} y coord */\n this.y = PLAYER_TOUCHING_GROUND_Y_COORD; // 0xAC // initialized to 244\n /** @type {number} y direction velocity */\n this.yVelocity = 0; // 0xB0 // initialized to 0\n /** @type {boolean} */\n this.isCollisionWithBallHappened = false; // 0xBC // initialized to 0 i.e false\n\n /**\n * Player's state\n * 0: normal, 1: jumping, 2: jumping_and_power_hitting, 3: diving\n * 4: lying_down_after_diving\n * 5: win!, 6: lost..\n * @type {number} 0, 1, 2, 3, 4, 5 or 6\n */\n this.state = 0; // 0xC0 // initialized to 0\n /** @type {number} */\n this.frameNumber = 0; // 0xC4 // initialized to 0\n /** @type {number} */\n this.normalStatusArmSwingDirection = 1; // 0xC8 // initialized to 1\n /** @type {number} */\n this.delayBeforeNextFrame = 0; // 0xCC // initialized to 0\n\n /**\n * This value is initialized to (_rand() % 5) before the start of every round.\n * The greater the number, the bolder the computer player.\n *\n * If computer has higher boldness,\n * judges more the ball is hanging around the other player's side,\n * has greater distance to the expected landing point of the ball,\n * jumps more,\n * and dives less.\n * See the source code of the {@link letComputerDecideUserInput} function (FUN_00402360).\n *\n * @type {number} 0, 1, 2, 3 or 4\n */\n this.computerBoldness = rand() % 5; // 0xD8 // initialized to (_rand() % 5)\n }\n}\n\n/**\n * Class representing a ball\n *\n * Ball property address: 00411F28 -> +28 -> +10 -> +14 -> ...\n * The \"...\" part is written on the line comment at the right side of each property.\n * e.g. address to ball.fineRotation: 00411F28 -> +28 -> +10 -> +14 -> +48\n *\n * For initial Values: refer to FUN_000403a90 && FUN_00402d60\n */\nclass Ball {\n /**\n * Create a ball\n * @param {boolean} isPlayer2Serve Will player 2 serve on this new round?\n */\n constructor(isPlayer2Serve) {\n this.initializeForNewRound(isPlayer2Serve);\n /** @type {number} x coord of expected lang point */\n this.expectedLandingPointX = 0; // 0x40\n /**\n * ball rotation frame number selector\n * During the period where it continues to be 5, hyper ball glitch occur.\n * @type {number} 0, 1, 2, 3, 4 or 5\n * */\n this.rotation = 0; // 0x44\n /** @type {number} */\n this.fineRotation = 0; // 0x48\n /** @type {number} x coord for punch effect */\n this.punchEffectX = 0; // 0x50\n /** @type {number} y coord for punch effect */\n this.punchEffectY = 0; // 0x54\n\n /**\n * Following previous values are for trailing effect for power hit\n * @type {number}\n */\n this.previousX = 0; // 0x58\n this.previousPreviousX = 0; // 0x5c\n this.previousY = 0; // 0x60\n this.previousPreviousY = 0; // 0x64\n\n /**\n * this property is not in the ball pointer of the original source code.\n * But for sound effect (especially for stereo sound),\n * it is convenient way to give sound property to a Ball.\n * The original name is stereo sound.\n */\n this.sound = {\n powerHit: false,\n ballTouchesGround: false,\n };\n }\n\n /**\n * Initialize for new round\n * @param {boolean} isPlayer2Serve will player on the right side serve on this new round?\n */\n initializeForNewRound(isPlayer2Serve) {\n /** @type {number} x coord */\n this.x = 56; // 0x30 // initialized to 56 or 376\n if (isPlayer2Serve === true) {\n this.x = GROUND_WIDTH - 56;\n }\n /** @type {number} y coord */\n this.y = 0; // 0x34 // initialized to 0\n /** @type {number} x direction velocity */\n this.xVelocity = 0; // 0x38 // initialized to 0\n /** @type {number} y direction velocity */\n this.yVelocity = 1; // 0x3C // initialized to 1\n /** @type {number} punch effect radius */\n this.punchEffectRadius = 0; // 0x4c // initialized to 0\n /** @type {boolean} is power hit */\n this.isPowerHit = false; // 0x68 // initialized to 0 i.e. false\n }\n}\n\n/**\n * FUN_00403dd0\n * This is the Pikachu Volleyball physics engine!\n * This physics engine calculates and set the physics values for the next frame.\n *\n * @param {Player} player1 player on the left side\n * @param {Player} player2 player on the right side\n * @param {Ball} ball ball\n * @param {PikaUserInput[]} userInputArray userInputArray[0]: user input for player 1, userInputArray[1]: user input for player 2\n * @return {boolean} Is ball touching ground?\n */\nfunction physicsEngine(player1, player2, ball, userInputArray) {\n const isBallTouchingGround =\n processCollisionBetweenBallAndWorldAndSetBallPosition(ball);\n\n let player;\n let theOtherPlayer;\n for (let i = 0; i < 2; i++) {\n if (i === 0) {\n player = player1;\n theOtherPlayer = player2;\n } else {\n player = player2;\n theOtherPlayer = player1;\n }\n\n // FUN_00402d90 omitted\n // FUN_00402810 omitted\n // this javascript code is refactored not to need above two function except for\n // a part of FUN_00402d90:\n // FUN_00402d90 include FUN_004031b0(calculateExpectedLandingPointXFor)\n calculateExpectedLandingPointXFor(ball); // calculate expected_X;\n\n processPlayerMovementAndSetPlayerPosition(\n player,\n userInputArray[i],\n theOtherPlayer,\n ball\n );\n\n // FUN_00402830 omitted\n // FUN_00406020 omitted\n // These two functions omitted above maybe participate in graphic drawing for a player\n }\n\n for (let i = 0; i < 2; i++) {\n if (i === 0) {\n player = player1;\n } else {\n player = player2;\n }\n\n // FUN_00402810 omitted: this javascript code is refactored not to need this function\n\n const isHappened = isCollisionBetweenBallAndPlayerHappened(\n ball,\n player.x,\n player.y\n );\n if (isHappened === true) {\n if (player.isCollisionWithBallHappened === false) {\n processCollisionBetweenBallAndPlayer(\n ball,\n player.x,\n userInputArray[i],\n player.state\n );\n player.isCollisionWithBallHappened = true;\n }\n } else {\n player.isCollisionWithBallHappened = false;\n }\n }\n\n // FUN_00403040\n // FUN_00406020\n // These two functions omitted above maybe participate in graphic drawing for a player\n\n return isBallTouchingGround;\n}\n\n/**\n * FUN_00403070\n * Is collision between ball and player happened?\n * @param {Ball} ball\n * @param {Player[\"x\"]} playerX player.x\n * @param {Player[\"y\"]} playerY player.y\n * @return {boolean}\n */\nfunction isCollisionBetweenBallAndPlayerHappened(ball, playerX, playerY) {\n let diff = ball.x - playerX;\n if (Math.abs(diff) <= PLAYER_HALF_LENGTH) {\n diff = ball.y - playerY;\n if (Math.abs(diff) <= PLAYER_HALF_LENGTH) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * FUN_00402dc0\n * Process collision between ball and world and set ball position\n * @param {Ball} ball\n * @return {boolean} Is ball touching ground?\n */\nfunction processCollisionBetweenBallAndWorldAndSetBallPosition(ball) {\n // This is not part of this function in the original assembly code.\n // In the original assembly code, it is processed in other function (FUN_00402ee0)\n // But it is proper to process here.\n ball.previousPreviousX = ball.previousX;\n ball.previousPreviousY = ball.previousY;\n ball.previousX = ball.x;\n ball.previousY = ball.y;\n\n // \"(ball.xVelocity / 2) | 0\" is integer division by 2\n let futureFineRotation = ball.fineRotation + ((ball.xVelocity / 2) | 0);\n // If futureFineRotation === 50, it skips next if statement finely.\n // Then ball.fineRotation = 50, and then ball.rotation = 5 (which designates hyper ball sprite!).\n // In this way, hyper ball glitch occur!\n // If this happen at the end of round,\n // since ball.xVelocity is 0-initialized at each start of round,\n // hyper ball sprite is rendered continuously until a collision happens.\n if (futureFineRotation < 0) {\n futureFineRotation += 50;\n } else if (futureFineRotation > 50) {\n futureFineRotation += -50;\n }\n ball.fineRotation = futureFineRotation;\n ball.rotation = (ball.fineRotation / 10) | 0; // integer division\n\n const futureBallX = ball.x + ball.xVelocity;\n /*\n If the center of ball would get out of left world bound or right world bound, bounce back.\n \n In this if statement, when considering left-right symmetry,\n \"futureBallX > GROUND_WIDTH\" should be changed to \"futureBallX > (GROUND_WIDTH - BALL_RADIUS)\",\n or \"futureBallX < BALL_RADIUS\" should be changed to \"futureBallX < 0\".\n Maybe the former one is more proper when seeing Pikachu player's x-direction boundary.\n Is this a mistake of the author of the original game?\n Or, was it set to this value to resolve infinite loop problem? (See comments on the constant INFINITE_LOOP_LIMIT.)\n If apply (futureBallX > (GROUND_WIDTH - BALL_RADIUS)), and if the maximum number of loop is not limited,\n it is observed that infinite loop in the function expectedLandingPointXWhenPowerHit does not terminate.\n */\n if (futureBallX < BALL_RADIUS || futureBallX > GROUND_WIDTH) {\n ball.xVelocity = -ball.xVelocity;\n }\n\n let futureBallY = ball.y + ball.yVelocity;\n // if the center of ball would get out of upper world bound\n if (futureBallY < 0) {\n ball.yVelocity = 1;\n }\n\n // If ball touches net\n if (\n Math.abs(ball.x - GROUND_HALF_WIDTH) < NET_PILLAR_HALF_WIDTH &&\n ball.y > NET_PILLAR_TOP_TOP_Y_COORD\n ) {\n if (ball.y <= NET_PILLAR_TOP_BOTTOM_Y_COORD) {\n if (ball.yVelocity > 0) {\n ball.yVelocity = -ball.yVelocity;\n }\n } else {\n if (ball.x < GROUND_HALF_WIDTH) {\n ball.xVelocity = -Math.abs(ball.xVelocity);\n } else {\n ball.xVelocity = Math.abs(ball.xVelocity);\n }\n }\n }\n\n futureBallY = ball.y + ball.yVelocity;\n // if ball would touch ground\n if (futureBallY > BALL_TOUCHING_GROUND_Y_COORD) {\n // FUN_00408470 omitted\n // the function omitted above receives 100 * (ball.x - 216),\n // i.e. horizontal displacement from net maybe for stereo sound?\n // code function (ballpointer + 0x28 + 0x10)? omitted\n // the omitted two functions maybe do a part of sound playback role.\n ball.sound.ballTouchesGround = true;\n\n ball.yVelocity = -ball.yVelocity;\n ball.punchEffectX = ball.x;\n ball.y = BALL_TOUCHING_GROUND_Y_COORD;\n ball.punchEffectRadius = BALL_RADIUS;\n ball.punchEffectY = BALL_TOUCHING_GROUND_Y_COORD + BALL_RADIUS;\n return true;\n }\n ball.y = futureBallY;\n ball.x = ball.x + ball.xVelocity;\n ball.yVelocity += 1;\n\n return false;\n}\n\n/**\n * FUN_00401fc0\n * Process player movement according to user input and set player position\n * @param {Player} player\n * @param {PikaUserInput} userInput\n * @param {Player} theOtherPlayer\n * @param {Ball} ball\n */\nfunction processPlayerMovementAndSetPlayerPosition(\n player,\n userInput,\n theOtherPlayer,\n ball\n) {\n if (player.isComputer === true) {\n letComputerDecideUserInput(player, ball, theOtherPlayer, userInput);\n }\n\n // if player is lying down.. don't move\n if (player.state === 4) {\n player.lyingDownDurationLeft += -1;\n if (player.lyingDownDurationLeft < -1) {\n player.state = 0;\n }\n return;\n }\n\n // process x-direction movement\n let playerVelocityX = 0;\n if (player.state < 5) {\n if (player.state < 3) {\n playerVelocityX = userInput.xDirection * 6;\n } else {\n // player.state === 3 i.e. player is diving..\n playerVelocityX = player.divingDirection * 8;\n }\n }\n\n const futurePlayerX = player.x + playerVelocityX;\n player.x = futurePlayerX;\n\n // process player's x-direction world boundary\n if (player.isPlayer2 === false) {\n // if player is player1\n if (futurePlayerX < PLAYER_HALF_LENGTH) {\n player.x = PLAYER_HALF_LENGTH;\n } else if (futurePlayerX > GROUND_HALF_WIDTH - PLAYER_HALF_LENGTH) {\n player.x = GROUND_HALF_WIDTH - PLAYER_HALF_LENGTH;\n }\n } else {\n // if player is player2\n if (futurePlayerX < GROUND_HALF_WIDTH + PLAYER_HALF_LENGTH) {\n player.x = GROUND_HALF_WIDTH + PLAYER_HALF_LENGTH;\n } else if (futurePlayerX > GROUND_WIDTH - PLAYER_HALF_LENGTH) {\n player.x = GROUND_WIDTH - PLAYER_HALF_LENGTH;\n }\n }\n\n // jump\n if (\n player.state < 3 &&\n userInput.yDirection === -1 && // up-direction input\n player.y === PLAYER_TOUCHING_GROUND_Y_COORD // player is touching on the ground\n ) {\n player.yVelocity = -16;\n player.state = 1;\n player.frameNumber = 0;\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-sound code function (playerpointer + 0x90 + 0x10)? omitted\n player.sound.chu = true;\n }\n\n // gravity\n const futurePlayerY = player.y + player.yVelocity;\n player.y = futurePlayerY;\n if (futurePlayerY < PLAYER_TOUCHING_GROUND_Y_COORD) {\n player.yVelocity += 1;\n } else if (futurePlayerY > PLAYER_TOUCHING_GROUND_Y_COORD) {\n // if player is landing..\n player.yVelocity = 0;\n player.y = PLAYER_TOUCHING_GROUND_Y_COORD;\n player.frameNumber = 0;\n if (player.state === 3) {\n // if player is diving..\n player.state = 4;\n player.frameNumber = 0;\n player.lyingDownDurationLeft = 3;\n } else {\n player.state = 0;\n }\n }\n\n if (userInput.powerHit === 1) {\n if (player.state === 1) {\n // if player is jumping..\n // then player do power hit!\n player.delayBeforeNextFrame = 5;\n player.frameNumber = 0;\n player.state = 2;\n // maybe-sound function (playerpointer + 0x90 + 0x18)? omitted\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-sound function (playerpointer + 0x90 + 0x14)? omitted\n player.sound.pika = true;\n } else if (player.state === 0 && userInput.xDirection !== 0) {\n // then player do diving!\n player.state = 3;\n player.frameNumber = 0;\n player.divingDirection = userInput.xDirection;\n player.yVelocity = -5;\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-sound code function (playerpointer + 0x90 + 0x10)? omitted\n player.sound.chu = true;\n }\n }\n\n if (player.state === 1) {\n player.frameNumber = (player.frameNumber + 1) % 3;\n } else if (player.state === 2) {\n if (player.delayBeforeNextFrame < 1) {\n player.frameNumber += 1;\n if (player.frameNumber > 4) {\n player.frameNumber = 0;\n player.state = 1;\n }\n } else {\n player.delayBeforeNextFrame -= 1;\n }\n } else if (player.state === 0) {\n player.delayBeforeNextFrame += 1;\n if (player.delayBeforeNextFrame > 3) {\n player.delayBeforeNextFrame = 0;\n const futureFrameNumber =\n player.frameNumber + player.normalStatusArmSwingDirection;\n if (futureFrameNumber < 0 || futureFrameNumber > 4) {\n player.normalStatusArmSwingDirection =\n -player.normalStatusArmSwingDirection;\n }\n player.frameNumber =\n player.frameNumber + player.normalStatusArmSwingDirection;\n }\n }\n\n if (player.gameEnded === true) {\n if (player.state === 0) {\n if (player.isWinner === true) {\n player.state = 5;\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-sound code function (0x98 + 0x10) omitted\n player.sound.pipikachu = true;\n } else {\n player.state = 6;\n }\n player.delayBeforeNextFrame = 0;\n player.frameNumber = 0;\n }\n processGameEndFrameFor(player);\n }\n}\n\n/**\n * FUN_004025e0\n * Process game end frame (for winner and loser motions) for the given player\n * @param {Player} player\n */\nfunction processGameEndFrameFor(player) {\n if (player.gameEnded === true && player.frameNumber < 4) {\n player.delayBeforeNextFrame += 1;\n if (player.delayBeforeNextFrame > 4) {\n player.delayBeforeNextFrame = 0;\n player.frameNumber += 1;\n }\n }\n}\n\n/**\n * FUN_004030a0\n * Process collision between ball and player.\n * This function only sets velocity of ball and expected landing point x of ball.\n * This function does not set position of ball.\n * The ball position is set by {@link processCollisionBetweenBallAndWorldAndSetBallPosition} function\n *\n * @param {Ball} ball\n * @param {Player[\"x\"]} playerX\n * @param {PikaUserInput} userInput\n * @param {Player[\"state\"]} playerState\n */\nfunction processCollisionBetweenBallAndPlayer(\n ball,\n playerX,\n userInput,\n playerState\n) {\n // playerX is maybe pika's x position\n // if collision occur,\n // greater the x position difference between pika and ball,\n // greater the x velocity of the ball.\n if (ball.x < playerX) {\n // Since javascript division is float division by default,\n // Here we use \"| 0\" to do integer division (refer to: https://stackoverflow.com/a/17218003/8581025)\n ball.xVelocity = -((Math.abs(ball.x - playerX) / 3) | 0);\n } else if (ball.x > playerX) {\n ball.xVelocity = (Math.abs(ball.x - playerX) / 3) | 0;\n }\n\n // If ball velocity x is 0, randomly choose one of -1, 0, 1.\n if (ball.xVelocity === 0) {\n ball.xVelocity = (rand() % 3) - 1;\n }\n\n const ballAbsYVelocity = Math.abs(ball.yVelocity);\n ball.yVelocity = -ballAbsYVelocity;\n\n if (ballAbsYVelocity < 15) {\n ball.yVelocity = -15;\n }\n\n // player is jumping and power hitting\n if (playerState === 2) {\n if (ball.x < GROUND_HALF_WIDTH) {\n ball.xVelocity = (Math.abs(userInput.xDirection) + 1) * 10;\n } else {\n ball.xVelocity = -(Math.abs(userInput.xDirection) + 1) * 10;\n }\n ball.punchEffectX = ball.x;\n ball.punchEffectY = ball.y;\n\n ball.yVelocity = Math.abs(ball.yVelocity) * userInput.yDirection * 2;\n ball.punchEffectRadius = BALL_RADIUS;\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-soundcode function (ballpointer + 0x24 + 0x10) omitted:\n ball.sound.powerHit = true;\n\n ball.isPowerHit = true;\n } else {\n ball.isPowerHit = false;\n }\n\n calculateExpectedLandingPointXFor(ball);\n}\n\n/**\n * FUN_004031b0\n * Calculate x coordinate of expected landing point of the ball\n * @param {Ball} ball\n */\nfunction calculateExpectedLandingPointXFor(ball) {\n const copyBall = {\n x: ball.x,\n y: ball.y,\n xVelocity: ball.xVelocity,\n yVelocity: ball.yVelocity,\n };\n let loopCounter = 0;\n while (true) {\n loopCounter++;\n\n const futureCopyBallX = copyBall.xVelocity + copyBall.x;\n if (futureCopyBallX < BALL_RADIUS || futureCopyBallX > GROUND_WIDTH) {\n copyBall.xVelocity = -copyBall.xVelocity;\n }\n if (copyBall.y + copyBall.yVelocity < 0) {\n copyBall.yVelocity = 1;\n }\n\n // If copy ball touches net\n if (\n Math.abs(copyBall.x - GROUND_HALF_WIDTH) < NET_PILLAR_HALF_WIDTH &&\n copyBall.y > NET_PILLAR_TOP_TOP_Y_COORD\n ) {\n // It maybe should be <= NET_PILLAR_TOP_BOTTOM_Y_COORD as in FUN_00402dc0, is it the original game author's mistake?\n if (copyBall.y < NET_PILLAR_TOP_BOTTOM_Y_COORD) {\n if (copyBall.yVelocity > 0) {\n copyBall.yVelocity = -copyBall.yVelocity;\n }\n } else {\n if (copyBall.x < GROUND_HALF_WIDTH) {\n copyBall.xVelocity = -Math.abs(copyBall.xVelocity);\n } else {\n copyBall.xVelocity = Math.abs(copyBall.xVelocity);\n }\n }\n }\n\n copyBall.y = copyBall.y + copyBall.yVelocity;\n // if copyBall would touch ground\n if (\n copyBall.y > BALL_TOUCHING_GROUND_Y_COORD ||\n loopCounter >= INFINITE_LOOP_LIMIT\n ) {\n break;\n }\n copyBall.x = copyBall.x + copyBall.xVelocity;\n copyBall.yVelocity += 1;\n }\n ball.expectedLandingPointX = copyBall.x;\n}\n\n/**\n * FUN_00402360\n * Computer controls its player by this function.\n * Computer decides the user input for the player it controls,\n * according to the game situation it figures out\n * by the given parameters (player, ball and theOtherPlayer),\n * and reflects these to the given user input object.\n *\n * @param {Player} player The player whom computer controls\n * @param {Ball} ball ball\n * @param {Player} theOtherPlayer The other player\n * @param {PikaUserInput} userInput user input of the player whom computer controls\n */\nfunction letComputerDecideUserInput(player, ball, theOtherPlayer, userInput) {\n userInput.xDirection = 0;\n userInput.yDirection = 0;\n userInput.powerHit = 0;\n\n let virtualExpectedLandingPointX = ball.expectedLandingPointX;\n if (\n Math.abs(ball.x - player.x) > 100 &&\n Math.abs(ball.xVelocity) < player.computerBoldness + 5\n ) {\n const leftBoundary = Number(player.isPlayer2) * GROUND_HALF_WIDTH;\n if (\n (ball.expectedLandingPointX <= leftBoundary ||\n ball.expectedLandingPointX >=\n Number(player.isPlayer2) * GROUND_WIDTH + GROUND_HALF_WIDTH) &&\n player.computerWhereToStandBy === 0\n ) {\n // If conditions above met, the computer estimates the proper location to stay as the middle point of their side\n virtualExpectedLandingPointX =\n leftBoundary + ((GROUND_HALF_WIDTH / 2) | 0);\n }\n }\n\n if (\n Math.abs(virtualExpectedLandingPointX - player.x) >\n player.computerBoldness + 8\n ) {\n if (player.x < virtualExpectedLandingPointX) {\n userInput.xDirection = 1;\n } else {\n userInput.xDirection = -1;\n }\n } else if (rand() % 20 === 0) {\n player.computerWhereToStandBy = rand() % 2;\n }\n\n if (player.state === 0) {\n if (\n Math.abs(ball.xVelocity) < player.computerBoldness + 3 &&\n Math.abs(ball.x - player.x) < PLAYER_HALF_LENGTH &&\n ball.y > -36 &&\n ball.y < 10 * player.computerBoldness + 84 &&\n ball.yVelocity > 0\n ) {\n userInput.yDirection = -1;\n }\n\n const leftBoundary = Number(player.isPlayer2) * GROUND_HALF_WIDTH;\n const rightBoundary = (Number(player.isPlayer2) + 1) * GROUND_HALF_WIDTH;\n if (\n ball.expectedLandingPointX > leftBoundary &&\n ball.expectedLandingPointX < rightBoundary &&\n Math.abs(ball.x - player.x) >\n player.computerBoldness * 5 + PLAYER_LENGTH &&\n ball.x > leftBoundary &&\n ball.x < rightBoundary &&\n ball.y > 174\n ) {\n // If conditions above met, the computer decides to dive!\n userInput.powerHit = 1;\n if (player.x < ball.x) {\n userInput.xDirection = 1;\n } else {\n userInput.xDirection = -1;\n }\n }\n } else if (player.state === 1 || player.state === 2) {\n if (Math.abs(ball.x - player.x) > 8) {\n if (player.x < ball.x) {\n userInput.xDirection = 1;\n } else {\n userInput.xDirection = -1;\n }\n }\n if (Math.abs(ball.x - player.x) < 48 && Math.abs(ball.y - player.y) < 48) {\n const willInputPowerHit = decideWhetherInputPowerHit(\n player,\n ball,\n theOtherPlayer,\n userInput\n );\n if (willInputPowerHit === true) {\n userInput.powerHit = 1;\n if (\n Math.abs(theOtherPlayer.x - player.x) < 80 &&\n userInput.yDirection !== -1\n ) {\n userInput.yDirection = -1;\n }\n }\n }\n }\n}\n\n/**\n * FUN_00402630\n * This function is called by {@link letComputerDecideUserInput},\n * and also sets x and y direction user input so that it participate in\n * the decision of the direction of power hit.\n * @param {Player} player the player whom computer controls\n * @param {Ball} ball ball\n * @param {Player} theOtherPlayer The other player\n * @param {PikaUserInput} userInput user input for the player whom computer controls\n * @return {boolean} Will input power hit?\n */\nfunction decideWhetherInputPowerHit(player, ball, theOtherPlayer, userInput) {\n if (rand() % 2 === 0) {\n for (let xDirection = 1; xDirection > -1; xDirection--) {\n for (let yDirection = -1; yDirection < 2; yDirection++) {\n const expectedLandingPointX = expectedLandingPointXWhenPowerHit(\n xDirection,\n yDirection,\n ball\n );\n if (\n (expectedLandingPointX <=\n Number(player.isPlayer2) * GROUND_HALF_WIDTH ||\n expectedLandingPointX >=\n Number(player.isPlayer2) * GROUND_WIDTH + GROUND_HALF_WIDTH) &&\n Math.abs(expectedLandingPointX - theOtherPlayer.x) > PLAYER_LENGTH\n ) {\n userInput.xDirection = xDirection;\n userInput.yDirection = yDirection;\n return true;\n }\n }\n }\n } else {\n for (let xDirection = 1; xDirection > -1; xDirection--) {\n for (let yDirection = 1; yDirection > -2; yDirection--) {\n const expectedLandingPointX = expectedLandingPointXWhenPowerHit(\n xDirection,\n yDirection,\n ball\n );\n if (\n (expectedLandingPointX <=\n Number(player.isPlayer2) * GROUND_HALF_WIDTH ||\n expectedLandingPointX >=\n Number(player.isPlayer2) * GROUND_WIDTH + GROUND_HALF_WIDTH) &&\n Math.abs(expectedLandingPointX - theOtherPlayer.x) > PLAYER_LENGTH\n ) {\n userInput.xDirection = xDirection;\n userInput.yDirection = yDirection;\n return true;\n }\n }\n }\n }\n return false;\n}\n\n/**\n * FUN_00402870\n * This function is called by {@link decideWhetherInputPowerHit},\n * and calculates the expected x coordinate of the landing point of the ball\n * when power hit\n * @param {PikaUserInput[\"xDirection\"]} userInputXDirection\n * @param {PikaUserInput[\"yDirection\"]} userInputYDirection\n * @param {Ball} ball\n * @return {number} x coord of expected landing point when power hit the ball\n */\nfunction expectedLandingPointXWhenPowerHit(\n userInputXDirection,\n userInputYDirection,\n ball\n) {\n const copyBall = {\n x: ball.x,\n y: ball.y,\n xVelocity: ball.xVelocity,\n yVelocity: ball.yVelocity,\n };\n if (copyBall.x < GROUND_HALF_WIDTH) {\n copyBall.xVelocity = (Math.abs(userInputXDirection) + 1) * 10;\n } else {\n copyBall.xVelocity = -(Math.abs(userInputXDirection) + 1) * 10;\n }\n copyBall.yVelocity = Math.abs(copyBall.yVelocity) * userInputYDirection * 2;\n\n let loopCounter = 0;\n while (true) {\n loopCounter++;\n\n const futureCopyBallX = copyBall.x + copyBall.xVelocity;\n if (futureCopyBallX < BALL_RADIUS || futureCopyBallX > GROUND_WIDTH) {\n copyBall.xVelocity = -copyBall.xVelocity;\n }\n if (copyBall.y + copyBall.yVelocity < 0) {\n copyBall.yVelocity = 1;\n }\n if (\n Math.abs(copyBall.x - GROUND_HALF_WIDTH) < NET_PILLAR_HALF_WIDTH &&\n copyBall.y > NET_PILLAR_TOP_TOP_Y_COORD\n ) {\n /*\n The code below maybe is intended to make computer do mistakes.\n The player controlled by computer occasionally power hit ball that is bounced back by the net pillar,\n since code below do not anticipate the bounce back.\n */\n if (copyBall.yVelocity > 0) {\n copyBall.yVelocity = -copyBall.yVelocity;\n }\n /*\n An alternative code for making the computer not do those mistakes is as below.\n\n if (copyBall.y <= NET_PILLAR_TOP_BOTTOM_Y_COORD) {\n if (copyBall.yVelocity > 0) {\n copyBall.yVelocity = -copyBall.yVelocity;\n }\n } else {\n if (copyBall.x < GROUND_HALF_WIDTH) {\n copyBall.xVelocity = -Math.abs(copyBall.xVelocity);\n } else {\n copyBall.xVelocity = Math.abs(copyBall.xVelocity);\n }\n }\n */\n }\n copyBall.y = copyBall.y + copyBall.yVelocity;\n if (\n copyBall.y > BALL_TOUCHING_GROUND_Y_COORD ||\n loopCounter >= INFINITE_LOOP_LIMIT\n ) {\n return copyBall.x;\n }\n copyBall.x = copyBall.x + copyBall.xVelocity;\n copyBall.yVelocity += 1;\n }\n}\n","/**\n * This module takes charge of the physical motion of clouds (on the sky) and wave (on the bottom of game screen) in the game.\n * It is also a Model in MVC pattern and also rendered by \"view.js\".\n *\n * It is gained by reverse engineering the original game.\n * The address of the original function is in the comment.\n * ex) FUN_00404770 means the function at the address 00404770 in the machine code.\n */\n'use strict';\nimport { rand } from './rand.js';\n\n/**\n * Class represents a cloud\n */\nexport class Cloud {\n constructor() {\n this.topLeftPointX = -68 + (rand() % (432 + 68));\n this.topLeftPointY = rand() % 152;\n this.topLeftPointXVelocity = 1 + (rand() % 2);\n this.sizeDiffTurnNumber = rand() % 11;\n }\n\n get sizeDiff() {\n // this same as return [0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0][this.sizeDiffTurnNumber]\n return 5 - Math.abs(this.sizeDiffTurnNumber - 5);\n }\n\n get spriteTopLeftPointX() {\n return this.topLeftPointX - this.sizeDiff;\n }\n\n get spriteTopLeftPointY() {\n return this.topLeftPointY - this.sizeDiff;\n }\n\n get spriteWidth() {\n return 48 + 2 * this.sizeDiff;\n }\n\n get spriteHeight() {\n return 24 + 2 * this.sizeDiff;\n }\n}\n\n/**\n * Class representing wave\n */\nexport class Wave {\n constructor() {\n this.verticalCoord = 0;\n this.verticalCoordVelocity = 2;\n this.yCoords = [];\n for (let i = 0; i < 432 / 16; i++) {\n this.yCoords.push(314);\n }\n }\n}\n\n/**\n * FUN_00404770\n * Move clouds and wave\n * @param {Cloud[]} cloudArray\n * @param {Wave} wave\n */\nexport function cloudAndWaveEngine(cloudArray, wave) {\n for (let i = 0; i < 10; i++) {\n cloudArray[i].topLeftPointX += cloudArray[i].topLeftPointXVelocity;\n if (cloudArray[i].topLeftPointX > 432) {\n cloudArray[i].topLeftPointX = -68;\n cloudArray[i].topLeftPointY = rand() % 152;\n cloudArray[i].topLeftPointXVelocity = 1 + (rand() % 2);\n }\n cloudArray[i].sizeDiffTurnNumber =\n (cloudArray[i].sizeDiffTurnNumber + 1) % 11;\n }\n\n wave.verticalCoord += wave.verticalCoordVelocity;\n if (wave.verticalCoord > 32) {\n wave.verticalCoord = 32;\n wave.verticalCoordVelocity = -1;\n } else if (wave.verticalCoord < 0 && wave.verticalCoordVelocity < 0) {\n wave.verticalCoordVelocity = 2;\n wave.verticalCoord = -(rand() % 40);\n }\n\n for (let i = 0; i < 432 / 16; i++) {\n wave.yCoords[i] = 314 - wave.verticalCoord + (rand() % 3);\n }\n}\n","/**\n * The View part in the MVC pattern\n *\n * Some codes in this module were gained by reverse engineering the original machine code.\n * The codes gained by reverse engineering are commented by the address of the function referred to in the machine code.\n * ex) FUN_00405d50 means the function at the address 00405d50 in the machine code.\n */\n'use strict';\nimport { AnimatedSprite } from '@pixi/sprite-animated';\nimport { Sprite } from '@pixi/sprite';\nimport { Container } from '@pixi/display';\nimport { Cloud, Wave, cloudAndWaveEngine } from './cloud_and_wave.js';\nimport { ASSETS_PATH } from './assets_path.js';\n\n/** @typedef {import('@pixi/loaders').LoaderResource} LoaderResource */\n/** @typedef {import('@pixi/core').Texture} Texture */\n\nconst TEXTURES = ASSETS_PATH.TEXTURES;\n\n/** @constant @type {number} number of clouds to be rendered */\nconst NUM_OF_CLOUDS = 10;\n\n/**\n * Class representing intro view where the man with a briefcase mark appears\n */\nexport class IntroView {\n /**\n * Create an IntroView object\n * @param {Object.} resources loader.resources\n */\n constructor(resources) {\n const textures = resources[ASSETS_PATH.SPRITE_SHEET].textures;\n\n this.mark = makeSpriteWithAnchorXY(textures, TEXTURES.MARK, 0.5, 0.5);\n this.mark.x = 432 / 2;\n this.mark.y = 304 / 2;\n\n this.container = new Container();\n this.container.addChild(this.mark);\n }\n\n /** @return {boolean} Is visible? */\n get visible() {\n return this.container.visible;\n }\n\n /** @param {boolean} bool Is visible? */\n set visible(bool) {\n this.container.visible = bool;\n }\n\n /**\n * draw \"a man with a briefcase\" mark\n * @param {number} frameCounter\n */\n drawMark(frameCounter) {\n const mark = this.mark;\n if (frameCounter === 0) {\n mark.alpha = 0;\n return;\n }\n if (frameCounter < 100) {\n mark.alpha = Math.min(1, mark.alpha + 1 / 25);\n } else if (frameCounter >= 100) {\n mark.alpha = Math.max(0, mark.alpha - 1 / 25);\n }\n }\n}\n\n/**\n * Class representing menu view where you can select \"play with computer\" or \"play with friend\"\n */\nexport class MenuView {\n /**\n * Create a MenuView object\n * @param {Object.} resources loader.resources\n */\n constructor(resources) {\n const textures = resources[ASSETS_PATH.SPRITE_SHEET].textures;\n\n this.messages = {\n pokemon: makeSpriteWithAnchorXY(textures, TEXTURES.POKEMON, 0, 0),\n pikachuVolleyball: makeSpriteWithAnchorXY(\n textures,\n TEXTURES.PIKACHU_VOLLEYBALL,\n 0,\n 0\n ),\n withWho: [\n makeSpriteWithAnchorXY(textures, TEXTURES.WITH_COMPUTER, 0, 0),\n makeSpriteWithAnchorXY(textures, TEXTURES.WITH_FRIEND, 0, 0),\n ],\n sachisoft: makeSpriteWithAnchorXY(textures, TEXTURES.SACHISOFT, 0, 0),\n fight: makeSpriteWithAnchorXY(textures, TEXTURES.FIGHT, 0, 0),\n };\n this.sittingPikachuTilesContainer =\n makeSittingPikachuTilesContainer(textures);\n\n // referred to FUN_004059f0\n this.messages.sachisoft.x = 216 - this.messages.sachisoft.texture.width / 2;\n this.messages.sachisoft.y = 264;\n\n // referred to FUN_00405b70\n this.messages.pikachuVolleyball.x = 140;\n this.messages.pikachuVolleyball.y = 80;\n this.messages.pokemon.x = 170;\n this.messages.pokemon.y = 40;\n\n this.container = new Container();\n this.container.addChild(this.sittingPikachuTilesContainer);\n this.container.addChild(this.messages.pokemon);\n this.container.addChild(this.messages.pikachuVolleyball);\n this.container.addChild(this.messages.withWho[0]);\n this.container.addChild(this.messages.withWho[1]);\n this.container.addChild(this.messages.sachisoft);\n this.container.addChild(this.messages.fight);\n this.initializeVisibles();\n\n this.sittingPikachuTilesDisplacement = 0;\n this.selectedWithWho = -1; // 0: with computer, 1: with friend, -1: not selected\n this.selectedWithWhoMessageSizeIncrement = 2;\n }\n\n /** @return {boolean} Is visible? */\n get visible() {\n return this.container.visible;\n }\n\n /** @param {boolean} bool Is visible? */\n set visible(bool) {\n this.container.visible = bool;\n\n // when turn off view, initialize visibilities of sprites in this view\n if (bool === false) {\n this.initializeVisibles();\n }\n }\n\n initializeVisibles() {\n for (const prop in this.messages) {\n this.messages[prop].visible = false;\n }\n }\n\n /**\n * referred to FUN_00405d50\n * Draw \"fight!\" message which get bigger and smaller as frame goes\n * @param {number} frameCounter\n */\n drawFightMessage(frameCounter) {\n const sizeArray = [20, 22, 25, 27, 30, 27, 25, 22, 20];\n const fightMessage = this.messages.fight;\n const w = fightMessage.texture.width;\n const h = fightMessage.texture.height;\n\n if (frameCounter === 0) {\n fightMessage.visible = true;\n }\n\n if (frameCounter < 30) {\n const halfWidth = Math.floor(Math.floor((frameCounter * w) / 30) / 2);\n const halfHeight = Math.floor(Math.floor((frameCounter * h) / 30) / 2);\n fightMessage.width = halfWidth * 2; // width\n fightMessage.height = halfHeight * 2; // height\n fightMessage.x = 100 - halfWidth; // x coord\n fightMessage.y = 70 - halfHeight; // y coord\n } else {\n const index = (frameCounter + 1) % 9;\n // code ...\n const halfWidth = Math.floor(Math.floor((sizeArray[index] * w) / 30) / 2);\n const halfHeight = Math.floor(\n Math.floor((sizeArray[index] * h) / 30) / 2\n );\n fightMessage.width = halfWidth * 2; // width\n fightMessage.height = halfHeight * 2; // height\n fightMessage.y = 70 - halfHeight; // y coord\n fightMessage.x = 100 - halfWidth; // x coord\n }\n }\n\n /**\n * Draw sachisoft message as frame goes\n * @param {number} frameCounter\n */\n drawSachisoft(frameCounter) {\n if (frameCounter === 0) {\n this.messages.sachisoft.visible = true;\n this.messages.sachisoft.alpha = 0;\n }\n this.messages.sachisoft.alpha = Math.min(\n 1,\n this.messages.sachisoft.alpha + 0.04\n );\n\n if (frameCounter > 70) {\n this.messages.sachisoft.alpha = 1;\n }\n }\n\n /**\n * referred to FUN_00405ca0\n * Draw sitting pikachu tiles as frame goes\n * @param {number} frameCounter\n */\n drawSittingPikachuTiles(frameCounter) {\n if (frameCounter === 0) {\n this.sittingPikachuTilesContainer.visible = true;\n this.sittingPikachuTilesContainer.alpha = 0;\n }\n\n // movement\n // @ts-ignore\n const h = this.sittingPikachuTilesContainer.getChildAt(0).texture.height;\n this.sittingPikachuTilesDisplacement =\n (this.sittingPikachuTilesDisplacement + 2) % h;\n this.sittingPikachuTilesContainer.x = -this.sittingPikachuTilesDisplacement;\n this.sittingPikachuTilesContainer.y = -this.sittingPikachuTilesDisplacement;\n\n if (frameCounter > 30) {\n // alpha\n this.sittingPikachuTilesContainer.alpha = Math.min(\n 1,\n this.sittingPikachuTilesContainer.alpha + 0.04\n );\n }\n\n if (frameCounter > 70) {\n this.sittingPikachuTilesContainer.alpha = 1;\n }\n }\n\n /**\n * referred to FUN_00405b70\n * Draw pikachu volleyball message as frame goes\n * @param {number} frameCounter\n */\n drawPikachuVolleyballMessage(frameCounter) {\n if (frameCounter === 0) {\n this.messages.pikachuVolleyball.visible = false;\n return;\n }\n\n if (frameCounter > 30) {\n this.messages.pikachuVolleyball.visible = true;\n }\n\n if (frameCounter > 30 && frameCounter <= 44) {\n const xDiff = 195 - 15 * (frameCounter - 30);\n this.messages.pikachuVolleyball.x = 140 + xDiff;\n } else if (frameCounter > 44 && frameCounter <= 55) {\n this.messages.pikachuVolleyball.x = 140;\n this.messages.pikachuVolleyball.width = 200 - 15 * (frameCounter - 44);\n } else if (frameCounter > 55 && frameCounter <= 71) {\n this.messages.pikachuVolleyball.x = 140;\n this.messages.pikachuVolleyball.width = 40 + 15 * (frameCounter - 55);\n } else if (frameCounter > 71) {\n this.messages.pikachuVolleyball.x = 140;\n this.messages.pikachuVolleyball.width =\n this.messages.pikachuVolleyball.texture.width;\n }\n }\n\n /**\n * referred to FUN_00405b70\n * Draw pokemon message as frame goes\n * @param {number} frameCounter\n */\n drawPokemonMessage(frameCounter) {\n if (frameCounter === 0) {\n this.messages.pokemon.visible = false;\n return;\n }\n\n if (frameCounter > 71) {\n this.messages.pokemon.visible = true;\n }\n }\n\n /**\n * referred to FUN_00405ec0\n * Draw with who messages (with computer or with friend) as frame goes\n * @param {number} frameCounter\n */\n drawWithWhoMessages(frameCounter) {\n const withWho = this.messages.withWho;\n const w = withWho[0].texture.width;\n const h = withWho[0].texture.height;\n\n if (frameCounter === 0) {\n for (let i = 0; i < 2; i++) {\n withWho[i].visible = false;\n }\n return;\n }\n\n if (frameCounter > 70) {\n if (this.selectedWithWhoMessageSizeIncrement < 10) {\n this.selectedWithWhoMessageSizeIncrement += 1;\n }\n for (let i = 0; i < 2; i++) {\n const selected = Number(this.selectedWithWho === i); // 1 if selected, 0 otherwise\n const halfWidthIncrement =\n selected * (this.selectedWithWhoMessageSizeIncrement + 2);\n const halfHeightIncrement =\n selected * this.selectedWithWhoMessageSizeIncrement;\n\n withWho[i].visible = true;\n withWho[i].x = 216 - w / 2 - halfWidthIncrement;\n withWho[i].y = 184 + 30 * i - halfHeightIncrement;\n withWho[i].width = w + 2 * halfWidthIncrement;\n withWho[i].height = h + 2 * halfHeightIncrement;\n }\n }\n }\n\n /**\n * Select with who for the effect that selected option gets bigger\n * @param {number} i 0: with computer, 1: with friend\n */\n selectWithWho(i) {\n this.selectedWithWho = i;\n this.selectedWithWhoMessageSizeIncrement = 2;\n }\n}\n\n/**\n * Class represent a game view where pikachus, ball, clouds, waves, and backgrounds are\n */\nexport class GameView {\n /**\n * Create a GameView object\n * @param {Object.} resources\n */\n constructor(resources) {\n const textures = resources[ASSETS_PATH.SPRITE_SHEET].textures;\n\n // Display objects below\n this.bgContainer = makeBGContainer(textures);\n const playerSprites = makePlayerAnimatedSprites(textures);\n this.player1 = playerSprites[0];\n this.player2 = playerSprites[1];\n this.ball = makeBallAnimatedSprites(textures);\n this.ballHyper = makeSpriteWithAnchorXY(\n textures,\n TEXTURES.BALL_HYPER,\n 0.5,\n 0.5\n );\n this.ballTrail = makeSpriteWithAnchorXY(\n textures,\n TEXTURES.BALL_TRAIL,\n 0.5,\n 0.5\n );\n this.punch = makeSpriteWithAnchorXY(\n textures,\n TEXTURES.BALL_PUNCH,\n 0.5,\n 0.5\n );\n\n // this.scoreBoards[0] for player1, this.scoreBoards[1] for player2\n this.scoreBoards = [\n makeScoreBoardSprite(textures),\n makeScoreBoardSprite(textures),\n ];\n\n this.shadows = {\n forPlayer1: makeSpriteWithAnchorXY(textures, TEXTURES.SHADOW, 0.5, 0.5),\n forPlayer2: makeSpriteWithAnchorXY(textures, TEXTURES.SHADOW, 0.5, 0.5),\n forBall: makeSpriteWithAnchorXY(textures, TEXTURES.SHADOW, 0.5, 0.5),\n };\n\n this.messages = {\n gameStart: makeSpriteWithAnchorXY(textures, TEXTURES.GAME_START, 0, 0),\n ready: makeSpriteWithAnchorXY(textures, TEXTURES.READY, 0, 0),\n gameEnd: makeSpriteWithAnchorXY(textures, TEXTURES.GAME_END, 0, 0),\n };\n\n this.cloudContainer = makeCloudContainer(textures);\n this.waveContainer = makeWaveContainer(textures);\n\n // container which include whole display objects\n // Should be careful on addChild order\n // The later added, the more front(z-index) on screen\n this.container = new Container();\n this.container.addChild(this.bgContainer);\n this.container.addChild(this.cloudContainer);\n this.container.addChild(this.waveContainer);\n this.container.addChild(this.shadows.forPlayer1);\n this.container.addChild(this.shadows.forPlayer2);\n this.container.addChild(this.shadows.forBall);\n this.container.addChild(this.player1);\n this.container.addChild(this.player2);\n this.container.addChild(this.ballTrail);\n this.container.addChild(this.ballHyper);\n this.container.addChild(this.ball);\n this.container.addChild(this.punch);\n this.container.addChild(this.scoreBoards[0]);\n this.container.addChild(this.scoreBoards[1]);\n this.container.addChild(this.messages.gameStart);\n this.container.addChild(this.messages.ready);\n this.container.addChild(this.messages.gameEnd);\n\n // location and visibility setting\n this.bgContainer.x = 0;\n this.bgContainer.y = 0;\n this.cloudContainer.x = 0;\n this.cloudContainer.y = 0;\n this.waveContainer.x = 0;\n this.waveContainer.y = 0;\n\n this.messages.ready.x = 176;\n this.messages.ready.y = 38;\n this.scoreBoards[0].x = 14; // score board is 14 pixel distant from boundary\n this.scoreBoards[0].y = 10;\n this.scoreBoards[1].x = 432 - 32 - 32 - 14; // 32 pixel is for number (32x32px) width; one score board has tow numbers\n this.scoreBoards[1].y = 10;\n\n this.shadows.forPlayer1.y = 273;\n this.shadows.forPlayer2.y = 273;\n this.shadows.forBall.y = 273;\n\n this.initializeVisibles();\n\n // clouds and wave model.\n // This model is included in this view object, not on controller object\n // since it is not dependent on user input, and only used for rendering.\n this.cloudArray = [];\n for (let i = 0; i < NUM_OF_CLOUDS; i++) {\n this.cloudArray.push(new Cloud());\n }\n this.wave = new Wave();\n }\n\n /** @return {boolean} Is visible? */\n get visible() {\n return this.container.visible;\n }\n\n /** @param {boolean} bool Is visible? */\n set visible(bool) {\n this.container.visible = bool;\n\n // when turn off view\n if (bool === false) {\n this.initializeVisibles();\n }\n }\n\n initializeVisibles() {\n for (const prop in this.messages) {\n this.messages[prop].visible = false;\n }\n }\n\n /** @typedef {import(\"./physics\").PikaPhysics} PikaPhysics */\n /**\n * Draw players and ball in the given physics object\n * @param {PikaPhysics} physics PikaPhysics object to draw\n */\n drawPlayersAndBall(physics) {\n const player1 = physics.player1;\n const player2 = physics.player2;\n const ball = physics.ball;\n\n this.player1.x = player1.x;\n this.player1.y = player1.y;\n if (player1.state === 3 || player1.state === 4) {\n this.player1.scale.x = player1.divingDirection === -1 ? -1 : 1;\n } else {\n this.player1.scale.x = 1;\n }\n this.shadows.forPlayer1.x = player1.x;\n\n this.player2.x = player2.x;\n this.player2.y = player2.y;\n if (player2.state === 3 || player2.state === 4) {\n this.player2.scale.x = player2.divingDirection === 1 ? 1 : -1;\n } else {\n this.player2.scale.x = -1;\n }\n this.shadows.forPlayer2.x = player2.x;\n\n const frameNumber1 = getFrameNumberForPlayerAnimatedSprite(\n player1.state,\n player1.frameNumber\n );\n const frameNumber2 = getFrameNumberForPlayerAnimatedSprite(\n player2.state,\n player2.frameNumber\n );\n this.player1.gotoAndStop(frameNumber1);\n this.player2.gotoAndStop(frameNumber2);\n\n this.ball.x = ball.x;\n this.ball.y = ball.y;\n this.shadows.forBall.x = ball.x;\n this.ball.gotoAndStop(ball.rotation);\n\n // For punch effect, refer FUN_00402ee0\n if (ball.punchEffectRadius > 0) {\n ball.punchEffectRadius -= 2;\n this.punch.width = 2 * ball.punchEffectRadius;\n this.punch.height = 2 * ball.punchEffectRadius;\n this.punch.x = ball.punchEffectX;\n this.punch.y = ball.punchEffectY;\n this.punch.visible = true;\n } else {\n this.punch.visible = false;\n }\n\n if (ball.isPowerHit === true) {\n this.ballHyper.x = ball.previousX;\n this.ballHyper.y = ball.previousY;\n this.ballTrail.x = ball.previousPreviousX;\n this.ballTrail.y = ball.previousPreviousY;\n\n this.ballHyper.visible = true;\n this.ballTrail.visible = true;\n } else {\n this.ballHyper.visible = false;\n this.ballTrail.visible = false;\n }\n }\n\n /**\n * Draw scores to each score board\n * @param {number[]} scores [0] for player1 score, [1] for player2 score\n */\n drawScoresToScoreBoards(scores) {\n for (let i = 0; i < 2; i++) {\n const scoreBoard = this.scoreBoards[i];\n const score = scores[i];\n const unitsAnimatedSprite = scoreBoard.getChildAt(0);\n const tensAnimatedSprite = scoreBoard.getChildAt(1);\n // @ts-ignore\n unitsAnimatedSprite.gotoAndStop(score % 10);\n // @ts-ignore\n tensAnimatedSprite.gotoAndStop(Math.floor(score / 10) % 10);\n if (score >= 10) {\n tensAnimatedSprite.visible = true;\n } else {\n tensAnimatedSprite.visible = false;\n }\n }\n }\n\n /**\n * Draw clouds and wave\n */\n drawCloudsAndWave() {\n const cloudArray = this.cloudArray;\n const wave = this.wave;\n\n cloudAndWaveEngine(cloudArray, wave);\n\n for (let i = 0; i < NUM_OF_CLOUDS; i++) {\n const cloud = cloudArray[i];\n const cloudSprite = this.cloudContainer.getChildAt(i);\n cloudSprite.x = cloud.spriteTopLeftPointX;\n cloudSprite.y = cloud.spriteTopLeftPointY;\n // @ts-ignore\n cloudSprite.width = cloud.spriteWidth;\n // @ts-ignore\n cloudSprite.height = cloud.spriteHeight;\n }\n\n for (let i = 0; i < 432 / 16; i++) {\n const waveSprite = this.waveContainer.getChildAt(i);\n waveSprite.y = wave.yCoords[i];\n }\n }\n\n /**\n * refered FUN_00403f20\n * Draw game start message as frame goes\n * @param {number} frameCounter current frame number\n * @param {number} frameTotal total frame number for game start message\n */\n drawGameStartMessage(frameCounter, frameTotal) {\n if (frameCounter === 0) {\n this.messages.gameStart.visible = true;\n } else if (frameCounter >= frameTotal - 1) {\n this.messages.gameStart.visible = false;\n return;\n }\n\n const gameStartMessage = this.messages.gameStart;\n // game start message rendering\n const w = gameStartMessage.texture.width; // game start message texture width\n const h = gameStartMessage.texture.height; // game start message texture height\n const halfWidth = Math.floor((w * frameCounter) / 50);\n const halfHeight = Math.floor((h * frameCounter) / 50);\n gameStartMessage.x = 216 - halfWidth;\n gameStartMessage.y = 50 + 2 * halfHeight;\n gameStartMessage.width = 2 * halfWidth;\n gameStartMessage.height = 2 * halfHeight;\n }\n\n /**\n * Draw ready message\n * @param {boolean} bool turn on?\n */\n drawReadyMessage(bool) {\n this.messages.ready.visible = bool;\n }\n\n /**\n * Togle ready message.\n * Turn off if it's on, turn on if it's off.\n */\n toggleReadyMessage() {\n this.messages.ready.visible = !this.messages.ready.visible;\n }\n\n /**\n * refered FUN_00404070\n * Draw game end message as frame goes\n * @param {number} frameCounter\n */\n drawGameEndMessage(frameCounter) {\n const gameEndMessage = this.messages.gameEnd;\n const w = gameEndMessage.texture.width; // game end message texture width;\n const h = gameEndMessage.texture.height; // game end message texture height;\n\n if (frameCounter === 0) {\n gameEndMessage.visible = true;\n }\n if (frameCounter < 50) {\n const halfWidthIncrement = 2 * Math.floor(((50 - frameCounter) * w) / 50);\n const halfHeightIncrement =\n 2 * Math.floor(((50 - frameCounter) * h) / 50);\n\n gameEndMessage.x = 216 - w / 2 - halfWidthIncrement;\n gameEndMessage.y = 50 - halfHeightIncrement;\n gameEndMessage.width = w + 2 * halfWidthIncrement;\n gameEndMessage.height = h + 2 * halfHeightIncrement;\n } else {\n gameEndMessage.x = 216 - w / 2;\n gameEndMessage.y = 50;\n gameEndMessage.width = w;\n gameEndMessage.height = h;\n }\n }\n}\n\n/**\n * Class representing fade in out effect\n */\nexport class FadeInOut {\n constructor(resources) {\n const textures = resources[ASSETS_PATH.SPRITE_SHEET].textures;\n this.black = makeSpriteWithAnchorXY(textures, TEXTURES.BLACK, 0, 0);\n this.black.width = 432;\n this.black.height = 304;\n this.black.x = 0;\n this.black.y = 0;\n this.black.alpha = 1;\n }\n\n /** @return {boolean} Is visible? */\n get visible() {\n return this.black.visible;\n }\n\n /** @param {boolean} bool Is visible? */\n set visible(bool) {\n this.black.visible = bool;\n }\n\n /**\n * Set black alpha for fade in out\n * @param {number} alpha number in [0, 1]\n */\n setBlackAlphaTo(alpha) {\n this.black.alpha = alpha;\n if (this.black.alpha === 0) {\n this.black.visible = false;\n } else {\n this.black.visible = true;\n }\n }\n\n /**\n * Increase black alpha for fade in out\n * @param {number} alphaIncrement if alphaIncrement > 0: fade out, else fade in\n */\n changeBlackAlphaBy(alphaIncrement) {\n if (alphaIncrement >= 0) {\n this.black.alpha = Math.min(1, this.black.alpha + alphaIncrement);\n } else {\n this.black.alpha = Math.max(0, this.black.alpha + alphaIncrement);\n }\n if (this.black.alpha === 0) {\n this.black.visible = false;\n } else {\n this.black.visible = true;\n }\n }\n}\n\n/**\n * Make sitting pikachu tiles\n * @param {Object.} textures\n * @return {Container}\n */\nfunction makeSittingPikachuTilesContainer(textures) {\n const container = new Container();\n const texture = textures[TEXTURES.SITTING_PIKACHU];\n const w = texture.width;\n const h = texture.height;\n\n let tile;\n for (let j = 0; j < Math.floor(304 / h) + 2; j++) {\n for (let i = 0; i < Math.floor(432 / w) + 2; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(container, tile, w * i, h * j);\n }\n }\n\n return container;\n}\n\n/**\n * Make background\n * @param {Object.} textures\n * @return {Container}\n */\nfunction makeBGContainer(textures) {\n const bgContainer = new Container();\n\n // sky\n let tile;\n let texture = textures[TEXTURES.SKY_BLUE];\n for (let j = 0; j < 12; j++) {\n for (let i = 0; i < 432 / 16; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 16 * i, 16 * j);\n }\n }\n\n // mountain\n texture = textures[TEXTURES.MOUNTAIN];\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 0, 188);\n\n // ground_red\n texture = textures[TEXTURES.GROUND_RED];\n for (let i = 0; i < 432 / 16; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 16 * i, 248);\n }\n\n // ground_line\n texture = textures[TEXTURES.GROUND_LINE];\n for (let i = 1; i < 432 / 16 - 1; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 16 * i, 264);\n }\n texture = textures[TEXTURES.GROUND_LINE_LEFT_MOST];\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 0, 264);\n texture = textures[TEXTURES.GROUND_LINE_RIGHT_MOST];\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 432 - 16, 264);\n\n // ground_yellow\n texture = textures[TEXTURES.GROUND_YELLOW];\n for (let j = 0; j < 2; j++) {\n for (let i = 0; i < 432 / 16; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(\n bgContainer,\n tile,\n 16 * i,\n 280 + 16 * j\n );\n }\n }\n\n // net pillar\n texture = textures[TEXTURES.NET_PILLAR_TOP];\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 213, 176);\n texture = textures[TEXTURES.NET_PILLAR];\n for (let j = 0; j < 12; j++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 213, 184 + 8 * j);\n }\n\n return bgContainer;\n}\n\n/**\n * Make animated sprites for both players\n * @param {Object.} textures\n * @return {AnimatedSprite[]} [0] for player 1, [1] for player2\n */\nfunction makePlayerAnimatedSprites(textures) {\n const getPlayerTexture = (i, j) => textures[TEXTURES.PIKACHU(i, j)];\n const playerTextureArray = [];\n for (let i = 0; i < 7; i++) {\n if (i === 3) {\n playerTextureArray.push(getPlayerTexture(i, 0));\n playerTextureArray.push(getPlayerTexture(i, 1));\n } else if (i === 4) {\n playerTextureArray.push(getPlayerTexture(i, 0));\n } else {\n for (let j = 0; j < 5; j++) {\n playerTextureArray.push(getPlayerTexture(i, j));\n }\n }\n }\n const player1AnimatedSprite = new AnimatedSprite(playerTextureArray, false);\n const player2AnimatedSprite = new AnimatedSprite(playerTextureArray, false);\n\n player1AnimatedSprite.anchor.x = 0.5;\n player1AnimatedSprite.anchor.y = 0.5;\n player2AnimatedSprite.anchor.x = 0.5;\n player2AnimatedSprite.anchor.y = 0.5;\n\n return [player1AnimatedSprite, player2AnimatedSprite];\n}\n\n/**\n * Make animated sprite of ball\n * @param {Object.} textures\n * @return {AnimatedSprite}\n */\nfunction makeBallAnimatedSprites(textures) {\n const getBallTexture = (s) => textures[TEXTURES.BALL(s)];\n const ballTextureArray = [\n getBallTexture(0),\n getBallTexture(1),\n getBallTexture(2),\n getBallTexture(3),\n getBallTexture(4),\n getBallTexture('hyper'),\n ];\n const ballAnimatedSprite = new AnimatedSprite(ballTextureArray, false);\n\n ballAnimatedSprite.anchor.x = 0.5;\n ballAnimatedSprite.anchor.y = 0.5;\n\n return ballAnimatedSprite;\n}\n\n/**\n * Make sprite with the texture on the path and with the given anchor x, y\n * @param {Object.} textures\n * @param {string} path\n * @param {number} anchorX anchor.x, number in [0, 1]\n * @param {number} anchorY anchor.y, number in [0, 1]\n * @return {Sprite}\n */\nfunction makeSpriteWithAnchorXY(textures, path, anchorX, anchorY) {\n const sprite = new Sprite(textures[path]);\n sprite.anchor.x = anchorX;\n sprite.anchor.y = anchorY;\n return sprite;\n}\n\n/**\n * Make score boards\n * @param {Object.} textures\n * @return {Container} child with index 0 for player 1 score board, child with index 1 for player2 score board\n */\nfunction makeScoreBoardSprite(textures) {\n const getNumberTexture = (n) => textures[TEXTURES.NUMBER(n)];\n const numberTextureArray = [];\n for (let i = 0; i < 10; i++) {\n numberTextureArray.push(getNumberTexture(i));\n }\n const numberAnimatedSprites = [null, null];\n numberAnimatedSprites[0] = new AnimatedSprite(numberTextureArray, false);\n numberAnimatedSprites[1] = new AnimatedSprite(numberTextureArray, false);\n\n const scoreBoard = new Container();\n addChildToParentAndSetLocalPosition(\n scoreBoard,\n numberAnimatedSprites[0],\n 32,\n 0\n ); // for units\n addChildToParentAndSetLocalPosition(\n scoreBoard,\n numberAnimatedSprites[1],\n 0,\n 0\n ); // for tens\n\n scoreBoard.setChildIndex(numberAnimatedSprites[0], 0); // for units\n scoreBoard.setChildIndex(numberAnimatedSprites[1], 1); // for tens\n\n return scoreBoard;\n}\n\n/**\n * Make a container with cloud sprites\n * @param {Object.} textures\n * @return {Container}\n */\nfunction makeCloudContainer(textures) {\n const cloudContainer = new Container();\n const texture = textures[TEXTURES.CLOUD];\n for (let i = 0; i < NUM_OF_CLOUDS; i++) {\n const cloud = new Sprite(texture);\n cloud.anchor.x = 0;\n cloud.anchor.y = 0;\n cloudContainer.addChild(cloud);\n }\n\n return cloudContainer;\n}\n\n/**\n * Make a container with wave sprites\n * @param {Object.} textures\n * @return {Container}\n */\nfunction makeWaveContainer(textures) {\n const waveContainer = new Container();\n const texture = textures[TEXTURES.WAVE];\n for (let i = 0; i < 432 / 16; i++) {\n const tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(waveContainer, tile, 16 * i, 0);\n }\n\n return waveContainer;\n}\n\n/**\n * Add child to parent and set local position\n * @param {Container} parent\n * @param {Sprite} child\n * @param {number} x local x\n * @param {number} y local y\n */\nfunction addChildToParentAndSetLocalPosition(parent, child, x, y) {\n parent.addChild(child);\n child.anchor.x = 0;\n child.anchor.y = 0;\n child.x = x;\n child.y = y;\n}\n\n/**\n * Get frame number for player animated sprite corresponds to the player state\n *\n * number of frames for state 0, state 1 and state 2 is 5 for each.\n * number of frames for state 3 is 2.\n * number of frames for state 4 is 1.\n * number of frames for state 5, state 6 is 5 for each.\n * @param {number} state player state\n * @param {number} frameNumber\n */\nfunction getFrameNumberForPlayerAnimatedSprite(state, frameNumber) {\n if (state < 4) {\n return 5 * state + frameNumber;\n } else if (state === 4) {\n return 17 + frameNumber;\n } else if (state > 4) {\n return 18 + 5 * (state - 5) + frameNumber;\n }\n}\n","/**\n * This module takes charge of the user input via keyboard\n */\n'use strict';\nimport { PikaUserInput } from './physics.js';\n\n/**\n * Class representing a keyboard used to control a player\n */\nexport class PikaKeyboard extends PikaUserInput {\n /**\n * Create a keyboard used for game controller\n * left, right, up, down, powerHit: KeyboardEvent.code value for each\n * Refer {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values}\n * @param {string} left KeyboardEvent.code value of the key to use for left\n * @param {string} right KeyboardEvent.code value of the key to use for right\n * @param {string} up KeyboardEvent.code value of the key to use for up\n * @param {string} down KeyboardEvent.code value of the key to use for down\n * @param {string} powerHit KeyboardEvent.code value of the key to use for power hit or selection\n * @param {string} downRight KeyboardEvent.code value of the key to use for having the same effect\n * when pressing down key and right key at the same time (Only player 1\n * has this key)\n */\n constructor(left, right, up, down, powerHit, downRight = null) {\n super();\n\n /** @type {boolean} */\n this.powerHitKeyIsDownPrevious = false;\n\n /** @type {Key} */\n this.leftKey = new Key(left);\n /** @type {Key} */\n this.rightKey = new Key(right);\n /** @type {Key} */\n this.upKey = new Key(up);\n /** @type {Key} */\n this.downKey = new Key(down);\n /** @type {Key} */\n this.powerHitKey = new Key(powerHit);\n /** @type {Key} */\n this.downRightKey = new Key(downRight);\n }\n\n /**\n * Get xDirection, yDirection, powerHit input from the keyboard.\n * This method is for freezing the keyboard input during the process of one game frame.\n */\n getInput() {\n if (this.leftKey.isDown) {\n this.xDirection = -1;\n } else if (\n this.rightKey.isDown ||\n (this.downRightKey && this.downRightKey.isDown)\n ) {\n this.xDirection = 1;\n } else {\n this.xDirection = 0;\n }\n\n if (this.upKey.isDown) {\n this.yDirection = -1;\n } else if (\n this.downKey.isDown ||\n (this.downRightKey && this.downRightKey.isDown)\n ) {\n this.yDirection = 1;\n } else {\n this.yDirection = 0;\n }\n\n const isDown = this.powerHitKey.isDown;\n if (!this.powerHitKeyIsDownPrevious && isDown) {\n this.powerHit = 1;\n } else {\n this.powerHit = 0;\n }\n this.powerHitKeyIsDownPrevious = isDown;\n }\n\n /**\n * Subscribe keydown, keyup event listeners for the keys of this keyboard\n */\n subscribe() {\n this.leftKey.subscribe();\n this.rightKey.subscribe();\n this.upKey.subscribe();\n this.downKey.subscribe();\n this.powerHitKey.subscribe();\n this.downRightKey.subscribe();\n }\n\n /**\n * Unsubscribe keydown, keyup event listeners for the keys of this keyboard\n */\n unsubscribe() {\n this.leftKey.unsubscribe();\n this.rightKey.unsubscribe();\n this.upKey.unsubscribe();\n this.downKey.unsubscribe();\n this.powerHitKey.unsubscribe();\n this.downRightKey.unsubscribe();\n }\n}\n\n/**\n * Class representing a key on a keyboard\n * referred to: https://github.com/kittykatattack/learningPixi\n */\nclass Key {\n /**\n * Create a key\n * Refer {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values}\n * @param {string} value KeyboardEvent.code value of this key\n */\n constructor(value) {\n this.value = value;\n this.isDown = false;\n this.isUp = true;\n\n this.downListener = this.downHandler.bind(this);\n this.upListener = this.upHandler.bind(this);\n this.subscribe();\n }\n\n /**\n * When key downed\n * @param {KeyboardEvent} event\n */\n downHandler(event) {\n if (event.code === this.value) {\n this.isDown = true;\n this.isUp = false;\n event.preventDefault();\n }\n }\n\n /**\n * When key upped\n * @param {KeyboardEvent} event\n */\n upHandler(event) {\n if (event.code === this.value) {\n this.isDown = false;\n this.isUp = true;\n event.preventDefault();\n }\n }\n\n /**\n * Subscribe event listeners\n */\n subscribe() {\n // I think an event listener for keyup should be attached\n // before the one for keydown to prevent a buggy behavior.\n // If keydown event listener were attached first and\n // a key was downed and upped before keyup event listener were attached,\n // I think the value of this.isDown would be true (and the value of this.isUp would be false)\n // for a while before the user press this key again.\n window.addEventListener('keyup', this.upListener);\n window.addEventListener('keydown', this.downListener);\n }\n\n /**\n * Unsubscribe event listeners\n */\n unsubscribe() {\n window.removeEventListener('keydown', this.downListener);\n window.removeEventListener('keyup', this.upListener);\n this.isDown = false;\n this.isUp = true;\n }\n}\n","/**\n * This module takes charge of the game audio (or sounds)\n */\n'use strict';\nimport { sound, Sound, filters } from '@pixi/sound';\nimport { ASSETS_PATH } from './assets_path.js';\n\nconst SOUNDS = ASSETS_PATH.SOUNDS;\n\n/** @typedef {import('@pixi/loaders').LoaderResource} LoaderResource */\n\n/**\n * Class representing audio\n */\nexport class PikaAudio {\n /**\n * Create a PikaAudio object\n * @param {Object.} resources loader.resources\n */\n constructor(resources) {\n /** @type {Object.} sounds pack */\n this.sounds = {\n bgm: new PikaStereoSound(resources[SOUNDS.BGM].sound),\n pipikachu: new PikaStereoSound(resources[SOUNDS.PIPIKACHU].sound),\n pika: new PikaStereoSound(resources[SOUNDS.PIKA].sound),\n chu: new PikaStereoSound(resources[SOUNDS.CHU].sound),\n pi: new PikaStereoSound(resources[SOUNDS.PI].sound),\n pikachu: new PikaStereoSound(resources[SOUNDS.PIKACHU].sound),\n powerHit: new PikaStereoSound(resources[SOUNDS.POWERHIT].sound),\n ballTouchesGround: new PikaStereoSound(\n resources[SOUNDS.BALLTOUCHESGROUND].sound\n ),\n };\n\n this.sounds.bgm.loop = true;\n /** @constant @type {number} proper bgm volume */\n this.properBGMVolume = 0.2;\n /** @constant @type {number} proper sfx volume */\n this.properSFXVolume = 0.35;\n this.adjustVolume();\n }\n\n /**\n * Adjust audio volume\n */\n adjustVolume() {\n for (const prop in this.sounds) {\n if (prop === 'bgm') {\n this.sounds[prop].volume = this.properBGMVolume;\n } else {\n this.sounds[prop].volume = this.properSFXVolume;\n }\n }\n }\n\n /**\n * turn BGM volume\n * @param {boolean} turnOn turnOn? turnOff\n */\n turnBGMVolume(turnOn) {\n let volume;\n if (turnOn) {\n volume = this.properBGMVolume;\n } else {\n volume = 0;\n }\n this.sounds.bgm.volume = volume;\n }\n\n /**\n * turn SFX volume\n * @param {boolean} turnOn turnOn? turnOff\n */\n turnSFXVolume(turnOn) {\n let volume;\n if (turnOn) {\n volume = this.properSFXVolume;\n } else {\n volume = 0;\n }\n for (const prop in this.sounds) {\n if (prop !== 'bgm') {\n this.sounds[prop].volume = volume;\n }\n }\n }\n\n muteAll() {\n sound.muteAll();\n }\n\n unmuteAll() {\n sound.unmuteAll();\n }\n}\n\n/**\n * Class representing a stereo sound\n */\nclass PikaStereoSound {\n /**\n * create a PikaStereoSound object\n * @param {Sound} sound\n */\n constructor(sound) {\n this.center = sound;\n this.left = Sound.from(sound.url);\n this.right = Sound.from(sound.url);\n\n const centerPanning = new filters.StereoFilter(0);\n const leftPanning = new filters.StereoFilter(-0.75);\n const rightPanning = new filters.StereoFilter(0.75);\n this.center.filters = [centerPanning];\n this.left.filters = [leftPanning];\n this.right.filters = [rightPanning];\n }\n\n /**\n * @param {number} v volume: number in [0, 1]\n */\n set volume(v) {\n this.center.volume = v;\n this.left.volume = v;\n this.right.volume = v;\n }\n\n /**\n * @param {boolean} bool\n */\n set loop(bool) {\n this.center.loop = bool;\n this.left.loop = bool;\n this.right.loop = bool;\n }\n\n /**\n * play this stereo sound\n * @param {number} leftOrCenterOrRight -1: left, 0: center, 1: right\n */\n play(leftOrCenterOrRight = 0) {\n if (leftOrCenterOrRight === 0) {\n this.center.play();\n } else if (leftOrCenterOrRight === -1) {\n this.left.play();\n } else if (leftOrCenterOrRight === 1) {\n this.right.play();\n }\n }\n\n /**\n * stop this stereo sound\n */\n stop() {\n this.center.stop();\n this.left.stop();\n this.right.stop();\n }\n}\n","/**\n * The Controller part in MVC pattern\n */\n'use strict';\nimport { GROUND_HALF_WIDTH, PikaPhysics } from './physics.js';\nimport { MenuView, GameView, FadeInOut, IntroView } from './view.js';\nimport { PikaKeyboard } from './keyboard.js';\nimport { PikaAudio } from './audio.js';\n\n/** @typedef {import('@pixi/display').Container} Container */\n/** @typedef {import('@pixi/loaders').LoaderResource} LoaderResource */\n\n/** @typedef GameState @type {function():void} */\n\n/**\n * Class representing Pikachu Volleyball game\n */\nexport class PikachuVolleyball {\n /**\n * Create a Pikachu Volleyball game which includes physics, view, audio\n * @param {Container} stage container which is rendered by PIXI.Renderer or PIXI.CanvasRenderer\n * @param {Object.} resources resources property of the PIXI.Loader object which is used for loading the game resources\n */\n constructor(stage, resources) {\n this.view = {\n intro: new IntroView(resources),\n menu: new MenuView(resources),\n game: new GameView(resources),\n fadeInOut: new FadeInOut(resources),\n };\n stage.addChild(this.view.intro.container);\n stage.addChild(this.view.menu.container);\n stage.addChild(this.view.game.container);\n stage.addChild(this.view.fadeInOut.black);\n this.view.intro.visible = false;\n this.view.menu.visible = false;\n this.view.game.visible = false;\n this.view.fadeInOut.visible = false;\n\n this.audio = new PikaAudio(resources);\n this.physics = new PikaPhysics(true, true);\n this.keyboardArray = [\n new PikaKeyboard('KeyD', 'KeyG', 'KeyR', 'KeyV', 'KeyZ', 'KeyF'), // for player1\n new PikaKeyboard( // for player2\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Enter'\n ),\n ];\n\n /** @type {number} game fps */\n this.normalFPS = 25;\n /** @type {number} fps for slow motion */\n this.slowMotionFPS = 5;\n\n /** @constant @type {number} number of frames for slow motion */\n this.SLOW_MOTION_FRAMES_NUM = 6;\n /** @type {number} number of frames left for slow motion */\n this.slowMotionFramesLeft = 0;\n /** @type {number} number of elapsed normal fps frames for rendering slow motion */\n this.slowMotionNumOfSkippedFrames = 0;\n\n /** @type {number} 0: with computer, 1: with friend */\n this.selectedWithWho = 0;\n\n /** @type {number[]} [0] for player 1 score, [1] for player 2 score */\n this.scores = [0, 0];\n /** @type {number} winning score: if either one of the players reaches this score, game ends */\n this.winningScore = 15;\n\n /** @type {boolean} Is the game ended? */\n this.gameEnded = false;\n /** @type {boolean} Is the round ended? */\n this.roundEnded = false;\n /** @type {boolean} Will player 2 serve? */\n this.isPlayer2Serve = false;\n\n /** @type {number} frame counter */\n this.frameCounter = 0;\n /** @type {Object.} total number of frames for each game state */\n this.frameTotal = {\n intro: 165,\n afterMenuSelection: 15,\n beforeStartOfNewGame: 15,\n startOfNewGame: 71,\n afterEndOfRound: 5,\n beforeStartOfNextRound: 30,\n gameEnd: 211,\n };\n\n /** @type {number} counter for frames while there is no input from keyboard */\n this.noInputFrameCounter = 0;\n /** @type {Object.} total number of frames to be rendered while there is no input */\n this.noInputFrameTotal = {\n menu: 225,\n };\n\n /** @type {boolean} true: paused, false: not paused */\n this.paused = false;\n\n /** @type {boolean} true: stereo, false: mono */\n this.isStereoSound = true;\n\n /** @type {boolean} true: practice mode on, false: practice mode off */\n this._isPracticeMode = false;\n\n /**\n * The game state which is being rendered now\n * @type {GameState}\n */\n this.state = this.intro;\n }\n\n /**\n * Game loop\n * This function should be called at regular intervals ( interval = (1 / FPS) second )\n */\n gameLoop() {\n if (this.paused === true) {\n return;\n }\n if (this.slowMotionFramesLeft > 0) {\n this.slowMotionNumOfSkippedFrames++;\n if (\n this.slowMotionNumOfSkippedFrames %\n Math.round(this.normalFPS / this.slowMotionFPS) !==\n 0\n ) {\n return;\n }\n this.slowMotionFramesLeft--;\n this.slowMotionNumOfSkippedFrames = 0;\n }\n // catch keyboard input and freeze it\n this.keyboardArray[0].getInput();\n this.keyboardArray[1].getInput();\n this.state();\n }\n\n /**\n * Intro: a man with a brief case\n * @type {GameState}\n */\n intro() {\n if (this.frameCounter === 0) {\n this.view.intro.visible = true;\n this.view.fadeInOut.setBlackAlphaTo(0);\n this.audio.sounds.bgm.stop();\n }\n this.view.intro.drawMark(this.frameCounter);\n this.frameCounter++;\n\n if (\n this.keyboardArray[0].powerHit === 1 ||\n this.keyboardArray[1].powerHit === 1\n ) {\n this.frameCounter = 0;\n this.view.intro.visible = false;\n this.state = this.menu;\n }\n\n if (this.frameCounter >= this.frameTotal.intro) {\n this.frameCounter = 0;\n this.view.intro.visible = false;\n this.state = this.menu;\n }\n }\n\n /**\n * Menu: select who do you want to play. With computer? With friend?\n * @type {GameState}\n */\n menu() {\n if (this.frameCounter === 0) {\n this.view.menu.visible = true;\n this.view.fadeInOut.setBlackAlphaTo(0);\n this.selectedWithWho = 0;\n this.view.menu.selectWithWho(this.selectedWithWho);\n }\n this.view.menu.drawFightMessage(this.frameCounter);\n this.view.menu.drawSachisoft(this.frameCounter);\n this.view.menu.drawSittingPikachuTiles(this.frameCounter);\n this.view.menu.drawPikachuVolleyballMessage(this.frameCounter);\n this.view.menu.drawPokemonMessage(this.frameCounter);\n this.view.menu.drawWithWhoMessages(this.frameCounter);\n this.frameCounter++;\n\n if (\n this.frameCounter < 71 &&\n (this.keyboardArray[0].powerHit === 1 ||\n this.keyboardArray[1].powerHit === 1)\n ) {\n this.frameCounter = 71;\n return;\n }\n\n if (this.frameCounter <= 71) {\n return;\n }\n\n if (\n (this.keyboardArray[0].yDirection === -1 ||\n this.keyboardArray[1].yDirection === -1) &&\n this.selectedWithWho === 1\n ) {\n this.noInputFrameCounter = 0;\n this.selectedWithWho = 0;\n this.view.menu.selectWithWho(this.selectedWithWho);\n this.audio.sounds.pi.play();\n } else if (\n (this.keyboardArray[0].yDirection === 1 ||\n this.keyboardArray[1].yDirection === 1) &&\n this.selectedWithWho === 0\n ) {\n this.noInputFrameCounter = 0;\n this.selectedWithWho = 1;\n this.view.menu.selectWithWho(this.selectedWithWho);\n this.audio.sounds.pi.play();\n } else {\n this.noInputFrameCounter++;\n }\n\n if (\n this.keyboardArray[0].powerHit === 1 ||\n this.keyboardArray[1].powerHit === 1\n ) {\n if (this.selectedWithWho === 1) {\n this.physics.player1.isComputer = false;\n this.physics.player2.isComputer = false;\n } else {\n if (this.keyboardArray[0].powerHit === 1) {\n this.physics.player1.isComputer = false;\n this.physics.player2.isComputer = true;\n } else if (this.keyboardArray[1].powerHit === 1) {\n this.physics.player1.isComputer = true;\n this.physics.player2.isComputer = false;\n }\n }\n this.audio.sounds.pikachu.play();\n this.frameCounter = 0;\n this.noInputFrameCounter = 0;\n this.state = this.afterMenuSelection;\n return;\n }\n\n if (this.noInputFrameCounter >= this.noInputFrameTotal.menu) {\n this.physics.player1.isComputer = true;\n this.physics.player2.isComputer = true;\n this.frameCounter = 0;\n this.noInputFrameCounter = 0;\n this.state = this.afterMenuSelection;\n }\n }\n\n /**\n * Fade out after menu selection\n * @type {GameState}\n */\n afterMenuSelection() {\n this.view.fadeInOut.changeBlackAlphaBy(1 / 16);\n this.frameCounter++;\n if (this.frameCounter >= this.frameTotal.afterMenuSelection) {\n this.frameCounter = 0;\n this.state = this.beforeStartOfNewGame;\n }\n }\n\n /**\n * Delay before start of new game (This is for the delay that exist in the original game)\n * @type {GameState}\n */\n beforeStartOfNewGame() {\n this.frameCounter++;\n if (this.frameCounter >= this.frameTotal.beforeStartOfNewGame) {\n this.frameCounter = 0;\n this.view.menu.visible = false;\n this.state = this.startOfNewGame;\n }\n }\n\n /**\n * Start of new game: Initialize ball and players and print game start message\n * @type {GameState}\n */\n startOfNewGame() {\n if (this.frameCounter === 0) {\n this.view.game.visible = true;\n this.gameEnded = false;\n this.roundEnded = false;\n this.isPlayer2Serve = false;\n this.physics.player1.gameEnded = false;\n this.physics.player1.isWinner = false;\n this.physics.player2.gameEnded = false;\n this.physics.player2.isWinner = false;\n\n this.scores[0] = 0;\n this.scores[1] = 0;\n this.view.game.drawScoresToScoreBoards(this.scores);\n\n this.physics.player1.initializeForNewRound();\n this.physics.player2.initializeForNewRound();\n this.physics.ball.initializeForNewRound(this.isPlayer2Serve);\n this.view.game.drawPlayersAndBall(this.physics);\n\n this.view.fadeInOut.setBlackAlphaTo(1); // set black screen\n this.audio.sounds.bgm.play();\n }\n\n this.view.game.drawGameStartMessage(\n this.frameCounter,\n this.frameTotal.startOfNewGame\n );\n this.view.game.drawCloudsAndWave();\n this.view.fadeInOut.changeBlackAlphaBy(-(1 / 17)); // fade in\n this.frameCounter++;\n\n if (this.frameCounter >= this.frameTotal.startOfNewGame) {\n this.frameCounter = 0;\n this.view.fadeInOut.setBlackAlphaTo(0);\n this.state = this.round;\n }\n }\n\n /**\n * Round: the players play volleyball in this game state\n * @type {GameState}\n */\n round() {\n const pressedPowerHit =\n this.keyboardArray[0].powerHit === 1 ||\n this.keyboardArray[1].powerHit === 1;\n\n if (\n this.physics.player1.isComputer === true &&\n this.physics.player2.isComputer === true &&\n pressedPowerHit\n ) {\n this.frameCounter = 0;\n this.view.game.visible = false;\n this.state = this.intro;\n return;\n }\n\n const isBallTouchingGround = this.physics.runEngineForNextFrame(\n this.keyboardArray\n );\n\n this.playSoundEffect();\n this.view.game.drawPlayersAndBall(this.physics);\n this.view.game.drawCloudsAndWave();\n\n if (this.gameEnded === true) {\n this.view.game.drawGameEndMessage(this.frameCounter);\n this.frameCounter++;\n if (\n this.frameCounter >= this.frameTotal.gameEnd ||\n (this.frameCounter >= 70 && pressedPowerHit)\n ) {\n this.frameCounter = 0;\n this.view.game.visible = false;\n this.state = this.intro;\n }\n return;\n }\n\n if (\n isBallTouchingGround &&\n this._isPracticeMode === false &&\n this.roundEnded === false &&\n this.gameEnded === false\n ) {\n if (this.physics.ball.punchEffectX < GROUND_HALF_WIDTH) {\n this.isPlayer2Serve = true;\n this.scores[1] += 1;\n if (this.scores[1] >= this.winningScore) {\n this.gameEnded = true;\n this.physics.player1.isWinner = false;\n this.physics.player2.isWinner = true;\n this.physics.player1.gameEnded = true;\n this.physics.player2.gameEnded = true;\n }\n } else {\n this.isPlayer2Serve = false;\n this.scores[0] += 1;\n if (this.scores[0] >= this.winningScore) {\n this.gameEnded = true;\n this.physics.player1.isWinner = true;\n this.physics.player2.isWinner = false;\n this.physics.player1.gameEnded = true;\n this.physics.player2.gameEnded = true;\n }\n }\n this.view.game.drawScoresToScoreBoards(this.scores);\n if (this.roundEnded === false && this.gameEnded === false) {\n this.slowMotionFramesLeft = this.SLOW_MOTION_FRAMES_NUM;\n }\n this.roundEnded = true;\n }\n\n if (this.roundEnded === true && this.gameEnded === false) {\n // if this is the last frame of this round, begin fade out\n if (this.slowMotionFramesLeft === 0) {\n this.view.fadeInOut.changeBlackAlphaBy(1 / 16); // fade out\n this.state = this.afterEndOfRound;\n }\n }\n }\n\n /**\n * Fade out after end of round\n * @type {GameState}\n */\n afterEndOfRound() {\n this.view.fadeInOut.changeBlackAlphaBy(1 / 16);\n this.frameCounter++;\n if (this.frameCounter >= this.frameTotal.afterEndOfRound) {\n this.frameCounter = 0;\n this.state = this.beforeStartOfNextRound;\n }\n }\n\n /**\n * Before start of next round, initialize ball and players, and print ready message\n * @type {GameState}\n */\n beforeStartOfNextRound() {\n if (this.frameCounter === 0) {\n this.view.fadeInOut.setBlackAlphaTo(1);\n this.view.game.drawReadyMessage(false);\n\n this.physics.player1.initializeForNewRound();\n this.physics.player2.initializeForNewRound();\n this.physics.ball.initializeForNewRound(this.isPlayer2Serve);\n this.view.game.drawPlayersAndBall(this.physics);\n }\n\n this.view.game.drawCloudsAndWave();\n this.view.fadeInOut.changeBlackAlphaBy(-(1 / 16));\n\n this.frameCounter++;\n if (this.frameCounter % 5 === 0) {\n this.view.game.toggleReadyMessage();\n }\n\n if (this.frameCounter >= this.frameTotal.beforeStartOfNextRound) {\n this.frameCounter = 0;\n this.view.game.drawReadyMessage(false);\n this.view.fadeInOut.setBlackAlphaTo(0);\n this.roundEnded = false;\n this.state = this.round;\n }\n }\n\n /**\n * Play sound effect on {@link round}\n */\n playSoundEffect() {\n const audio = this.audio;\n for (let i = 0; i < 2; i++) {\n const player = this.physics[`player${i + 1}`];\n const sound = player.sound;\n let leftOrCenterOrRight = 0;\n if (this.isStereoSound) {\n leftOrCenterOrRight = i === 0 ? -1 : 1;\n }\n if (sound.pipikachu === true) {\n audio.sounds.pipikachu.play(leftOrCenterOrRight);\n sound.pipikachu = false;\n }\n if (sound.pika === true) {\n audio.sounds.pika.play(leftOrCenterOrRight);\n sound.pika = false;\n }\n if (sound.chu === true) {\n audio.sounds.chu.play(leftOrCenterOrRight);\n sound.chu = false;\n }\n }\n const ball = this.physics.ball;\n const sound = ball.sound;\n let leftOrCenterOrRight = 0;\n if (this.isStereoSound) {\n if (ball.punchEffectX < GROUND_HALF_WIDTH) {\n leftOrCenterOrRight = -1;\n } else if (ball.punchEffectX > GROUND_HALF_WIDTH) {\n leftOrCenterOrRight = 1;\n }\n }\n if (sound.powerHit === true) {\n audio.sounds.powerHit.play(leftOrCenterOrRight);\n sound.powerHit = false;\n }\n if (sound.ballTouchesGround === true) {\n audio.sounds.ballTouchesGround.play(leftOrCenterOrRight);\n sound.ballTouchesGround = false;\n }\n }\n\n /**\n * Called if restart button clicked\n */\n restart() {\n this.frameCounter = 0;\n this.noInputFrameCounter = 0;\n this.slowMotionFramesLeft = 0;\n this.slowMotionNumOfSkippedFrames = 0;\n this.view.menu.visible = false;\n this.view.game.visible = false;\n this.state = this.intro;\n }\n\n /** @return {boolean} */\n get isPracticeMode() {\n return this._isPracticeMode;\n }\n\n /**\n * @param {boolean} bool true: turn on practice mode, false: turn off practice mode\n */\n set isPracticeMode(bool) {\n this._isPracticeMode = bool;\n this.view.game.scoreBoards[0].visible = !bool;\n this.view.game.scoreBoards[1].visible = !bool;\n }\n}\n","/**\n * Manages event listeners relevant to the UI (menu bar, buttons, etc.) of the web page\n */\n'use strict';\n\nimport { localStorageWrapper } from './utils/local_storage_wrapper.js';\n\n/** @typedef {import('./pikavolley.js').PikachuVolleyball} PikachuVolleyball */\n/** @typedef {import('@pixi/ticker').Ticker} Ticker */\n/** @typedef {{graphic?: string, bgm?: string, sfx?: string, speed?: string, winningScore?: string}} Options */\n\n/**\n * Enum for \"game paused by what?\".\n * The greater the number, the higher the precedence.\n *\n * @readonly\n * @enum {number}\n */\nconst PauseResumePrecedence = {\n pauseBtn: 3,\n messageBox: 2,\n dropdown: 1,\n notPaused: 0,\n};\n\n/**\n * Manages pausing and resuming of the game\n */\nconst pauseResumeManager = {\n /** @type {number} PauseResumePrecedence enum */\n _precedence: PauseResumePrecedence.notPaused,\n /**\n * Pause game\n * @param {PikachuVolleyball} pikaVolley\n * @param {number} precedence PauseResumePrecedence enum\n */\n pause: function (pikaVolley, precedence) {\n // @ts-ignore\n if (precedence > this._precedence) {\n pikaVolley.paused = true;\n this._precedence = precedence;\n }\n },\n /**\n * Resume game\n * @param {PikachuVolleyball} pikaVolley\n * @param {number} precedence PauseResumePrecedence enum\n */\n resume: function (pikaVolley, precedence) {\n if (precedence === this._precedence) {\n pikaVolley.paused = false;\n this._precedence = PauseResumePrecedence.notPaused;\n }\n },\n};\n\n/**\n * Set up the user interface: menu bar, buttons, dropdowns, submenus, etc.\n * @param {PikachuVolleyball} pikaVolley\n * @param {Ticker} ticker\n */\nexport function setUpUI(pikaVolley, ticker) {\n /**\n * Apply options\n * @param {Options} options\n */\n const applyOptions = (options) => {\n setSelectedOptionsBtn(options);\n switch (options.graphic) {\n case 'sharp':\n document.getElementById('game-canvas').classList.remove('graphic-soft');\n break;\n case 'soft':\n document.getElementById('game-canvas').classList.add('graphic-soft');\n break;\n }\n switch (options.bgm) {\n case 'on':\n pikaVolley.audio.turnBGMVolume(true);\n break;\n case 'off':\n pikaVolley.audio.turnBGMVolume(false);\n break;\n }\n switch (options.sfx) {\n case 'stereo':\n pikaVolley.audio.turnSFXVolume(true);\n pikaVolley.isStereoSound = true;\n break;\n case 'mono':\n pikaVolley.audio.turnSFXVolume(true);\n pikaVolley.isStereoSound = false;\n break;\n case 'off':\n pikaVolley.audio.turnSFXVolume(false);\n break;\n }\n switch (options.speed) {\n case 'slow':\n pikaVolley.normalFPS = 20;\n ticker.maxFPS = pikaVolley.normalFPS;\n break;\n case 'medium':\n pikaVolley.normalFPS = 25;\n ticker.maxFPS = pikaVolley.normalFPS;\n break;\n case 'fast':\n pikaVolley.normalFPS = 30;\n ticker.maxFPS = pikaVolley.normalFPS;\n break;\n }\n switch (options.winningScore) {\n case '5':\n pikaVolley.winningScore = 5;\n break;\n case '10':\n pikaVolley.winningScore = 10;\n break;\n case '15':\n pikaVolley.winningScore = 15;\n break;\n }\n };\n\n /**\n * Save options\n * @param {Options} options\n */\n const saveOptions = (options) => {\n setSelectedOptionsBtn(options);\n if (options.graphic) {\n localStorageWrapper.set('pv-offline-graphic', options.graphic);\n }\n if (options.bgm) {\n localStorageWrapper.set('pv-offline-bgm', options.bgm);\n }\n if (options.sfx) {\n localStorageWrapper.set('pv-offline-sfx', options.sfx);\n }\n if (options.speed) {\n localStorageWrapper.set('pv-offline-speed', options.speed);\n }\n if (options.winningScore) {\n localStorageWrapper.set('pv-offline-winningScore', options.winningScore);\n }\n };\n\n /**\n * Load options\n * @returns {Options}\n */\n const loadOptions = () => ({\n graphic: localStorageWrapper.get('pv-offline-graphic'),\n bgm: localStorageWrapper.get('pv-offline-bgm'),\n sfx: localStorageWrapper.get('pv-offline-sfx'),\n speed: localStorageWrapper.get('pv-offline-speed'),\n winningScore: localStorageWrapper.get('pv-offline-winningScore'),\n });\n\n /**\n * Apply and save options\n * @param {Options} options\n */\n const applyAndSaveOptions = (options) => {\n applyOptions(options);\n saveOptions(options);\n };\n\n // Load and apply saved options\n applyOptions(loadOptions());\n\n setUpBtns(pikaVolley, applyAndSaveOptions);\n setUpToShowDropdownsAndSubmenus(pikaVolley);\n\n // hide or show menubar if the user presses the \"esc\" key\n window.addEventListener('keydown', (event) => {\n if (event.code === 'Escape') {\n const menuBar = document.getElementById('menu-bar');\n if (menuBar.classList.contains('hidden')) {\n menuBar.classList.remove('hidden');\n } else {\n menuBar.classList.add('hidden');\n }\n event.preventDefault();\n } else if (event.code === 'Space') {\n const aboutBox = document.getElementById('about-box');\n if (aboutBox.classList.contains('hidden')) {\n event.preventDefault();\n }\n }\n });\n\n document.addEventListener('visibilitychange', function () {\n if (document.visibilityState === 'visible') {\n pikaVolley.audio.unmuteAll();\n } else {\n pikaVolley.audio.muteAll();\n }\n });\n}\n\n/**\n * Attach event listeners to the buttons\n * @param {PikachuVolleyball} pikaVolley\n * @param {(options: Options) => void} applyAndSaveOptions\n */\nfunction setUpBtns(pikaVolley, applyAndSaveOptions) {\n const gameDropdownBtn = document.getElementById('game-dropdown-btn');\n const optionsDropdownBtn = document.getElementById('options-dropdown-btn');\n const aboutBtn = document.getElementById('about-btn');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n // @ts-ignore\n aboutBtn.disabled = false;\n\n const pauseBtn = document.getElementById('pause-btn');\n pauseBtn.addEventListener('click', () => {\n if (pauseBtn.classList.contains('selected')) {\n pauseBtn.classList.remove('selected');\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.pauseBtn);\n } else {\n pauseBtn.classList.add('selected');\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.pauseBtn);\n }\n });\n\n const restartBtn = document.getElementById('restart-btn');\n restartBtn.addEventListener('click', () => {\n if (pauseBtn.classList.contains('selected')) {\n pauseBtn.classList.remove('selected');\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.pauseBtn);\n }\n pikaVolley.restart();\n });\n\n const graphicSharpBtn = document.getElementById('graphic-sharp-btn');\n const graphicSoftBtn = document.getElementById('graphic-soft-btn');\n graphicSharpBtn.addEventListener('click', () => {\n applyAndSaveOptions({ graphic: 'sharp' });\n });\n graphicSoftBtn.addEventListener('click', () => {\n applyAndSaveOptions({ graphic: 'soft' });\n });\n\n const bgmOnBtn = document.getElementById('bgm-on-btn');\n const bgmOffBtn = document.getElementById('bgm-off-btn');\n bgmOnBtn.addEventListener('click', () => {\n applyAndSaveOptions({ bgm: 'on' });\n });\n bgmOffBtn.addEventListener('click', () => {\n applyAndSaveOptions({ bgm: 'off' });\n });\n\n const stereoBtn = document.getElementById('stereo-btn');\n const monoBtn = document.getElementById('mono-btn');\n const sfxOffBtn = document.getElementById('sfx-off-btn');\n stereoBtn.addEventListener('click', () => {\n applyAndSaveOptions({ sfx: 'stereo' });\n });\n monoBtn.addEventListener('click', () => {\n applyAndSaveOptions({ sfx: 'mono' });\n });\n sfxOffBtn.addEventListener('click', () => {\n applyAndSaveOptions({ sfx: 'off' });\n });\n\n // Game speed:\n // slow: 1 frame per 50ms = 20 FPS\n // medium: 1 frame per 40ms = 25 FPS\n // fast: 1 frame per 33ms = 30.303030... FPS\n const slowSpeedBtn = document.getElementById('slow-speed-btn');\n const mediumSpeedBtn = document.getElementById('medium-speed-btn');\n const fastSpeedBtn = document.getElementById('fast-speed-btn');\n slowSpeedBtn.addEventListener('click', () => {\n applyAndSaveOptions({ speed: 'slow' });\n });\n mediumSpeedBtn.addEventListener('click', () => {\n applyAndSaveOptions({ speed: 'medium' });\n });\n fastSpeedBtn.addEventListener('click', () => {\n applyAndSaveOptions({ speed: 'fast' });\n });\n\n const winningScore5Btn = document.getElementById('winning-score-5-btn');\n const winningScore10Btn = document.getElementById('winning-score-10-btn');\n const winningScore15Btn = document.getElementById('winning-score-15-btn');\n const noticeBox1 = document.getElementById('notice-box-1');\n const noticeOKBtn1 = document.getElementById('notice-ok-btn-1');\n const winningScoreInNoticeBox1 = document.getElementById(\n 'winning-score-in-notice-box-1'\n );\n function isWinningScoreAlreadyReached(winningScore) {\n const isGamePlaying =\n pikaVolley.state === pikaVolley.round ||\n pikaVolley.state === pikaVolley.afterEndOfRound ||\n pikaVolley.state === pikaVolley.beforeStartOfNextRound;\n if (\n isGamePlaying &&\n (pikaVolley.scores[0] >= winningScore ||\n pikaVolley.scores[1] >= winningScore)\n ) {\n return true;\n }\n return false;\n }\n const noticeBox2 = document.getElementById('notice-box-2');\n const noticeOKBtn2 = document.getElementById('notice-ok-btn-2');\n winningScore5Btn.addEventListener('click', () => {\n if (winningScore5Btn.classList.contains('selected')) {\n return;\n }\n if (pikaVolley.isPracticeMode === true) {\n noticeBox2.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n if (isWinningScoreAlreadyReached(5)) {\n winningScoreInNoticeBox1.textContent = '5';\n noticeBox1.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n applyAndSaveOptions({ winningScore: '5' });\n });\n winningScore10Btn.addEventListener('click', () => {\n if (winningScore10Btn.classList.contains('selected')) {\n return;\n }\n if (pikaVolley.isPracticeMode === true) {\n noticeBox2.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n if (isWinningScoreAlreadyReached(10)) {\n winningScoreInNoticeBox1.textContent = '10';\n noticeBox1.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n applyAndSaveOptions({ winningScore: '10' });\n });\n winningScore15Btn.addEventListener('click', () => {\n if (winningScore15Btn.classList.contains('selected')) {\n return;\n }\n if (pikaVolley.isPracticeMode === true) {\n noticeBox2.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n if (isWinningScoreAlreadyReached(15)) {\n winningScoreInNoticeBox1.textContent = '15';\n noticeBox1.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n applyAndSaveOptions({ winningScore: '15' });\n });\n noticeOKBtn1.addEventListener('click', () => {\n if (!noticeBox1.classList.contains('hidden')) {\n noticeBox1.classList.add('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n // @ts-ignore\n aboutBtn.disabled = false;\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.messageBox);\n }\n });\n noticeOKBtn2.addEventListener('click', () => {\n if (!noticeBox2.classList.contains('hidden')) {\n noticeBox2.classList.add('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n // @ts-ignore\n aboutBtn.disabled = false;\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.messageBox);\n }\n });\n\n const practiceModeOnBtn = document.getElementById('practice-mode-on-btn');\n const practiceModeOffBtn = document.getElementById('practice-mode-off-btn');\n practiceModeOnBtn.addEventListener('click', () => {\n practiceModeOffBtn.classList.remove('selected');\n practiceModeOnBtn.classList.add('selected');\n pikaVolley.isPracticeMode = true;\n });\n practiceModeOffBtn.addEventListener('click', () => {\n practiceModeOnBtn.classList.remove('selected');\n practiceModeOffBtn.classList.add('selected');\n pikaVolley.isPracticeMode = false;\n });\n\n const aboutBox = document.getElementById('about-box');\n const closeAboutBtn = document.getElementById('close-about-btn');\n aboutBtn.addEventListener('click', () => {\n if (aboutBox.classList.contains('hidden')) {\n aboutBox.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n } else {\n aboutBox.classList.add('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.messageBox);\n }\n });\n closeAboutBtn.addEventListener('click', () => {\n if (!aboutBox.classList.contains('hidden')) {\n aboutBox.classList.add('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.messageBox);\n }\n });\n\n const resetToDefaultBtn = document.getElementById('reset-to-default-btn');\n resetToDefaultBtn.addEventListener('click', () => {\n // turn off practice mode\n practiceModeOffBtn.click();\n\n // and restore the reset options to default\n const defaultOptions = {\n graphic: 'sharp',\n bgm: 'on',\n sfx: 'stereo',\n speed: 'medium',\n winningScore: '15',\n };\n applyAndSaveOptions(defaultOptions);\n });\n}\n\n/**\n * Set selected (checked) options btn fit to options\n * @param {Options} options\n */\nfunction setSelectedOptionsBtn(options) {\n if (options.graphic) {\n const graphicSharpBtn = document.getElementById('graphic-sharp-btn');\n const graphicSoftBtn = document.getElementById('graphic-soft-btn');\n switch (options.graphic) {\n case 'sharp':\n graphicSoftBtn.classList.remove('selected');\n graphicSharpBtn.classList.add('selected');\n break;\n case 'soft':\n graphicSharpBtn.classList.remove('selected');\n graphicSoftBtn.classList.add('selected');\n break;\n }\n }\n if (options.bgm) {\n const bgmOnBtn = document.getElementById('bgm-on-btn');\n const bgmOffBtn = document.getElementById('bgm-off-btn');\n switch (options.bgm) {\n case 'on':\n bgmOffBtn.classList.remove('selected');\n bgmOnBtn.classList.add('selected');\n break;\n case 'off':\n bgmOnBtn.classList.remove('selected');\n bgmOffBtn.classList.add('selected');\n break;\n }\n }\n if (options.sfx) {\n const stereoBtn = document.getElementById('stereo-btn');\n const monoBtn = document.getElementById('mono-btn');\n const sfxOffBtn = document.getElementById('sfx-off-btn');\n switch (options.sfx) {\n case 'stereo':\n monoBtn.classList.remove('selected');\n sfxOffBtn.classList.remove('selected');\n stereoBtn.classList.add('selected');\n break;\n case 'mono':\n sfxOffBtn.classList.remove('selected');\n stereoBtn.classList.remove('selected');\n monoBtn.classList.add('selected');\n break;\n case 'off':\n stereoBtn.classList.remove('selected');\n monoBtn.classList.remove('selected');\n sfxOffBtn.classList.add('selected');\n break;\n }\n }\n if (options.speed) {\n const slowSpeedBtn = document.getElementById('slow-speed-btn');\n const mediumSpeedBtn = document.getElementById('medium-speed-btn');\n const fastSpeedBtn = document.getElementById('fast-speed-btn');\n switch (options.speed) {\n case 'slow':\n mediumSpeedBtn.classList.remove('selected');\n fastSpeedBtn.classList.remove('selected');\n slowSpeedBtn.classList.add('selected');\n break;\n case 'medium':\n fastSpeedBtn.classList.remove('selected');\n slowSpeedBtn.classList.remove('selected');\n mediumSpeedBtn.classList.add('selected');\n break;\n case 'fast':\n slowSpeedBtn.classList.remove('selected');\n mediumSpeedBtn.classList.remove('selected');\n fastSpeedBtn.classList.add('selected');\n break;\n }\n }\n if (options.winningScore) {\n const winningScore5Btn = document.getElementById('winning-score-5-btn');\n const winningScore10Btn = document.getElementById('winning-score-10-btn');\n const winningScore15Btn = document.getElementById('winning-score-15-btn');\n switch (options.winningScore) {\n case '5':\n winningScore10Btn.classList.remove('selected');\n winningScore15Btn.classList.remove('selected');\n winningScore5Btn.classList.add('selected');\n break;\n case '10':\n winningScore15Btn.classList.remove('selected');\n winningScore5Btn.classList.remove('selected');\n winningScore10Btn.classList.add('selected');\n break;\n case '15':\n winningScore5Btn.classList.remove('selected');\n winningScore10Btn.classList.remove('selected');\n winningScore15Btn.classList.add('selected');\n break;\n }\n }\n}\n\n/**\n * Attach event listeners to show dropdowns and submenus properly\n * @param {PikachuVolleyball} pikaVolley\n */\nfunction setUpToShowDropdownsAndSubmenus(pikaVolley) {\n // hide dropdowns and submenus if the user clicks outside of these\n window.addEventListener('click', (event) => {\n // @ts-ignore\n if (!event.target.matches('.dropdown-btn, .submenu-btn')) {\n hideSubmenus();\n hideDropdownsExcept('');\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.dropdown);\n }\n });\n\n // set up to show dropdowns\n document.getElementById('game-dropdown-btn').addEventListener('click', () => {\n toggleDropdown('game-dropdown', pikaVolley);\n });\n document\n .getElementById('options-dropdown-btn')\n .addEventListener('click', () => {\n toggleDropdown('options-dropdown', pikaVolley);\n });\n\n // set up to show submenus on mouseover event\n document\n .getElementById('graphic-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('graphic-submenu-btn', 'graphic-submenu');\n });\n document\n .getElementById('bgm-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('bgm-submenu-btn', 'bgm-submenu');\n });\n document\n .getElementById('sfx-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('sfx-submenu-btn', 'sfx-submenu');\n });\n document\n .getElementById('speed-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('speed-submenu-btn', 'speed-submenu');\n });\n document\n .getElementById('winning-score-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('winning-score-submenu-btn', 'winning-score-submenu');\n });\n document\n .getElementById('practice-mode-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('practice-mode-submenu-btn', 'practice-mode-submenu');\n });\n document\n .getElementById('reset-to-default-btn')\n .addEventListener('mouseover', () => {\n hideSubmenus();\n });\n\n // set up to show submenus on click event\n // (it is for touch device equipped with physical keyboard)\n document.getElementById('bgm-submenu-btn').addEventListener('click', () => {\n showSubmenu('bgm-submenu-btn', 'bgm-submenu');\n });\n document.getElementById('sfx-submenu-btn').addEventListener('click', () => {\n showSubmenu('sfx-submenu-btn', 'sfx-submenu');\n });\n document.getElementById('speed-submenu-btn').addEventListener('click', () => {\n showSubmenu('speed-submenu-btn', 'speed-submenu');\n });\n document\n .getElementById('winning-score-submenu-btn')\n .addEventListener('click', () => {\n showSubmenu('winning-score-submenu-btn', 'winning-score-submenu');\n });\n document\n .getElementById('practice-mode-submenu-btn')\n .addEventListener('click', () => {\n showSubmenu('practice-mode-submenu-btn', 'practice-mode-submenu');\n });\n document\n .getElementById('reset-to-default-btn')\n .addEventListener('click', () => {\n hideSubmenus();\n });\n}\n\n/**\n * Toggle (show or hide) the dropdown menu\n * @param {string} dropdownID html element id of the dropdown to toggle\n * @param {PikachuVolleyball} pikaVolley\n */\nfunction toggleDropdown(dropdownID, pikaVolley) {\n hideSubmenus();\n hideDropdownsExcept(dropdownID);\n const willShow = document.getElementById(dropdownID).classList.toggle('show');\n if (willShow) {\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.dropdown);\n } else {\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.dropdown);\n }\n}\n\n/**\n * Show the submenu\n * @param {string} submenuBtnID html element id of the submenu button whose submenu to show\n * @param {string} subMenuID html element id of the submenu to show\n */\nfunction showSubmenu(submenuBtnID, subMenuID) {\n hideSubmenus();\n document.getElementById(submenuBtnID).classList.add('open');\n document.getElementById(subMenuID).classList.add('show');\n}\n\n/**\n * Hide all other dropdowns except the dropdown\n * @param {string} dropdownID html element id of the dropdown\n */\nfunction hideDropdownsExcept(dropdownID) {\n const dropdowns = document.getElementsByClassName('dropdown');\n for (let i = 0; i < dropdowns.length; i++) {\n if (dropdowns[i].id !== dropdownID) {\n dropdowns[i].classList.remove('show');\n }\n }\n}\n\n/**\n * Hide all submenus\n */\nfunction hideSubmenus() {\n const submenus = document.getElementsByClassName('submenu');\n for (let i = 0; i < submenus.length; i++) {\n submenus[i].classList.remove('show');\n }\n const submenuBtns = document.getElementsByClassName('submenu-btn');\n for (let i = 0; i < submenuBtns.length; i++) {\n submenuBtns[i].classList.remove('open');\n }\n}\n","/**\n * This is the main script which executes the game.\n * General explanations for the all source code files of the game are following.\n *\n ********************************************************************************************************************\n * This web version of the Pikachu Volleyball is made by\n * reverse engineering the core part of the original Pikachu Volleyball game\n * which is developed by \"1997 (C) SACHI SOFT / SAWAYAKAN Programmers\" & \"1997 (C) Satoshi Takenouchi\".\n *\n * \"physics.js\", \"cloud_and_wave.js\", and some codes in \"view.js\" are the results of this reverse engineering.\n * Refer to the comments in each file for the machine code addresses of the original functions.\n ********************************************************************************************************************\n *\n * This web version game is mainly composed of three parts which follows MVC pattern.\n * 1) \"physics.js\" (Model): The physics engine which takes charge of the dynamics of the ball and the players (Pikachus).\n * It is gained by reverse engineering the machine code of the original game.\n * 2) \"view.js\" (View): The rendering part of the game which depends on pixi.js (https://www.pixijs.com/, https://github.com/pixijs/pixi.js) library.\n * Some codes in this part is gained by reverse engineering the original machine code.\n * 3) \"pikavolley.js\" (Controller): Make the game work by controlling the Model and the View according to the user input.\n *\n * And explanations for other source files are below.\n * - \"cloud_and_wave.js\": This is also a Model part which takes charge of the clouds and wave motion in the game. Of course, it is also rendered by \"view.js\".\n * It is also gained by reverse engineering the original machine code.\n * - \"keyboard.js\": Support the Controller(\"pikavolley.js\") to get a user input via keyboard.\n * - \"audio.js\": The game audio or sounds. It depends on pixi-sound (https://github.com/pixijs/pixi-sound) library.\n * - \"rand.js\": For the random function used in the Models (\"physics.js\", \"cloud_and_wave.js\").\n * - \"assets_path.js\": For the assets (image files, sound files) locations.\n * - \"ui.js\": For the user interface (menu bar, buttons etc.) of the html page.\n */\n'use strict';\nimport { settings } from '@pixi/settings';\nimport { SCALE_MODES } from '@pixi/constants';\nimport { Renderer, BatchRenderer, autoDetectRenderer } from '@pixi/core';\nimport { Prepare } from '@pixi/prepare';\nimport { Container } from '@pixi/display';\nimport { Loader } from '@pixi/loaders';\nimport { SpritesheetLoader } from '@pixi/spritesheet';\nimport { Ticker } from '@pixi/ticker';\nimport { CanvasRenderer } from '@pixi/canvas-renderer';\nimport { CanvasSpriteRenderer } from '@pixi/canvas-sprite';\nimport { CanvasPrepare } from '@pixi/canvas-prepare';\nimport '@pixi/canvas-display';\nimport { PikachuVolleyball } from './pikavolley.js';\nimport { ASSETS_PATH } from './assets_path.js';\nimport { setUpUI } from './ui.js';\n\n// Reference for how to use Renderer.registerPlugin:\n// https://github.com/pixijs/pixijs/blob/af3c0c6bb15aeb1049178c972e4a14bb4cabfce4/bundles/pixi.js/src/index.ts#L27-L34\nRenderer.registerPlugin('prepare', Prepare);\nRenderer.registerPlugin('batch', BatchRenderer);\n// Reference for how to use CanvasRenderer.registerPlugin:\n// https://github.com/pixijs/pixijs/blob/af3c0c6bb15aeb1049178c972e4a14bb4cabfce4/bundles/pixi.js-legacy/src/index.ts#L13-L19\nCanvasRenderer.registerPlugin('prepare', CanvasPrepare);\nCanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer);\nLoader.registerPlugin(SpritesheetLoader);\n\n// Set settings.RESOLUTION to 3 instead of 1 to make the game screen do not look\n// much blurry in case of the image rendering mode of 'image-rendering: auto',\n// which is like bilinear interpolation, which is used in \"soft\" game graphic option.\nsettings.RESOLUTION = 3;\nsettings.SCALE_MODE = SCALE_MODES.NEAREST;\nsettings.ROUND_PIXELS = true;\n\nconst renderer = autoDetectRenderer({\n width: 432,\n height: 304,\n antialias: false,\n backgroundColor: 0x000000,\n backgroundAlpha: 1,\n // Decided to use only Canvas for compatibility reason. One player had reported that\n // on their browser, where pixi chooses to use WebGL renderer, the graphics are not fine.\n // And the issue had been fixed by using Canvas renderer. And also for the sake of testing,\n // it is more comfortable just to stick with Canvas renderer so that it is unnecessary to switch\n // between WebGL renderer and Canvas renderer.\n forceCanvas: true,\n});\n\nconst stage = new Container();\nconst ticker = new Ticker();\nconst loader = new Loader();\n\nrenderer.view.setAttribute('id', 'game-canvas');\ndocument.getElementById('game-canvas-container').appendChild(renderer.view);\nrenderer.render(stage); // To make the initial canvas painting stable in the Firefox browser.\n\nloader.add(ASSETS_PATH.SPRITE_SHEET);\nfor (const prop in ASSETS_PATH.SOUNDS) {\n loader.add(ASSETS_PATH.SOUNDS[prop]);\n}\n\nsetUpInitialUI();\n\n/**\n * Set up the initial UI.\n */\nfunction setUpInitialUI() {\n const loadingBox = document.getElementById('loading-box');\n const progressBar = document.getElementById('progress-bar');\n loader.onProgress.add(() => {\n progressBar.style.width = `${loader.progress}%`;\n });\n loader.onComplete.add(() => {\n loadingBox.classList.add('hidden');\n });\n\n const aboutBox = document.getElementById('about-box');\n const aboutBtn = document.getElementById('about-btn');\n const closeAboutBtn = document.getElementById('close-about-btn');\n const gameDropdownBtn = document.getElementById('game-dropdown-btn');\n const optionsDropdownBtn = document.getElementById('options-dropdown-btn');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n const closeAboutBox = () => {\n if (!aboutBox.classList.contains('hidden')) {\n aboutBox.classList.add('hidden');\n // @ts-ignore\n aboutBtn.disabled = true;\n }\n aboutBtn.getElementsByClassName('text-play')[0].classList.add('hidden');\n aboutBtn.getElementsByClassName('text-about')[0].classList.remove('hidden');\n aboutBtn.classList.remove('glow');\n closeAboutBtn\n .getElementsByClassName('text-play')[0]\n .classList.add('hidden');\n closeAboutBtn\n .getElementsByClassName('text-close')[0]\n .classList.remove('hidden');\n closeAboutBtn.classList.remove('glow');\n\n loader.load(setup); // setup is called after loader finishes loading\n loadingBox.classList.remove('hidden');\n aboutBtn.removeEventListener('click', closeAboutBox);\n closeAboutBtn.removeEventListener('click', closeAboutBox);\n };\n aboutBtn.addEventListener('click', closeAboutBox);\n closeAboutBtn.addEventListener('click', closeAboutBox);\n}\n\n/**\n * Set up the game and the full UI, and start the game.\n */\nfunction setup() {\n const pikaVolley = new PikachuVolleyball(stage, loader.resources);\n setUpUI(pikaVolley, ticker);\n start(pikaVolley);\n}\n\n/**\n * Start the game.\n * @param {PikachuVolleyball} pikaVolley\n */\nfunction start(pikaVolley) {\n ticker.maxFPS = pikaVolley.normalFPS;\n ticker.add(() => {\n pikaVolley.gameLoop();\n renderer.render(stage);\n });\n ticker.start();\n}\n","export const localStorageWrapper = {\n /**\n * Get value corresponding to the key from localStorage\n * @param {string} key\n * @returns {string|null}\n */\n get: (key) => {\n let value = null;\n try {\n value = localStorage.getItem(key);\n } catch (err) {\n console.error(err);\n }\n return value;\n },\n\n /*\n * Set key-value pair to the localStorage\n * @param {string} key\n * @param {string} value\n */\n set: (key, value) => {\n try {\n localStorage.setItem(key, value);\n } catch (err) {\n console.error(err);\n }\n },\n};\n"],"names":["ASSETS_PATH","SPRITE_SHEET","TEXTURES","SOUNDS","PIKACHU","i","j","BALL","s","NUMBER","n","SKY_BLUE","MOUNTAIN","GROUND_RED","GROUND_LINE","GROUND_LINE_LEFT_MOST","GROUND_LINE_RIGHT_MOST","GROUND_YELLOW","NET_PILLAR_TOP","NET_PILLAR","SHADOW","BALL_HYPER","BALL_TRAIL","BALL_PUNCH","CLOUD","WAVE","BLACK","SACHISOFT","READY","GAME_END","MARK","POKEMON","PIKACHU_VOLLEYBALL","FIGHT","WITH_COMPUTER","WITH_FRIEND","GAME_START","SITTING_PIKACHU","BGM","PIPIKACHU","PIKA","CHU","PI","POWERHIT","BALLTOUCHESGROUND","rand","Math","floor","random","GROUND_WIDTH","GROUND_HALF_WIDTH","PLAYER_TOUCHING_GROUND_Y_COORD","BALL_TOUCHING_GROUND_Y_COORD","PikaPhysics","constructor","isPlayer1Computer","isPlayer2Computer","this","player1","Player","player2","ball","Ball","runEngineForNextFrame","userInputArray","isBallTouchingGround","previousPreviousX","previousX","previousPreviousY","previousY","x","y","futureFineRotation","fineRotation","xVelocity","rotation","futureBallX","futureBallY","yVelocity","abs","sound","ballTouchesGround","punchEffectX","punchEffectRadius","punchEffectY","processCollisionBetweenBallAndWorldAndSetBallPosition","player","theOtherPlayer","calculateExpectedLandingPointXFor","processPlayerMovementAndSetPlayerPosition","isCollisionBetweenBallAndPlayerHappened","isCollisionWithBallHappened","processCollisionBetweenBallAndPlayer","state","physicsEngine","isPlayer2","isComputer","initializeForNewRound","divingDirection","lyingDownDurationLeft","isWinner","gameEnded","computerWhereToStandBy","pipikachu","pika","chu","frameNumber","normalStatusArmSwingDirection","delayBeforeNextFrame","computerBoldness","isPlayer2Serve","expectedLandingPointX","powerHit","isPowerHit","playerX","playerY","diff","userInput","xDirection","yDirection","virtualExpectedLandingPointX","leftBoundary","Number","rightBoundary","willInputPowerHit","expectedLandingPointXWhenPowerHit","decideWhetherInputPowerHit","letComputerDecideUserInput","playerVelocityX","futurePlayerX","futurePlayerY","futureFrameNumber","processGameEndFrameFor","playerState","ballAbsYVelocity","copyBall","loopCounter","futureCopyBallX","userInputXDirection","userInputYDirection","Cloud","topLeftPointX","topLeftPointY","topLeftPointXVelocity","sizeDiffTurnNumber","sizeDiff","spriteTopLeftPointX","spriteTopLeftPointY","spriteWidth","spriteHeight","Wave","verticalCoord","verticalCoordVelocity","yCoords","push","IntroView","resources","textures","mark","makeSpriteWithAnchorXY","container","addChild","visible","bool","drawMark","frameCounter","alpha","min","max","MenuView","messages","pokemon","pikachuVolleyball","withWho","sachisoft","fight","sittingPikachuTilesContainer","texture","w","width","h","height","tile","addChildToParentAndSetLocalPosition","makeSittingPikachuTilesContainer","initializeVisibles","sittingPikachuTilesDisplacement","selectedWithWho","selectedWithWhoMessageSizeIncrement","prop","drawFightMessage","sizeArray","fightMessage","halfWidth","halfHeight","index","drawSachisoft","drawSittingPikachuTiles","getChildAt","drawPikachuVolleyballMessage","xDiff","drawPokemonMessage","drawWithWhoMessages","selected","halfWidthIncrement","halfHeightIncrement","selectWithWho","GameView","bgContainer","makeBGContainer","playerSprites","getPlayerTexture","playerTextureArray","player1AnimatedSprite","player2AnimatedSprite","anchor","makePlayerAnimatedSprites","getBallTexture","ballTextureArray","ballAnimatedSprite","makeBallAnimatedSprites","ballHyper","ballTrail","punch","scoreBoards","makeScoreBoardSprite","shadows","forPlayer1","forPlayer2","forBall","gameStart","ready","gameEnd","cloudContainer","cloud","makeCloudContainer","waveContainer","makeWaveContainer","cloudArray","wave","drawPlayersAndBall","physics","scale","frameNumber1","getFrameNumberForPlayerAnimatedSprite","frameNumber2","gotoAndStop","drawScoresToScoreBoards","scores","scoreBoard","score","unitsAnimatedSprite","tensAnimatedSprite","drawCloudsAndWave","cloudAndWaveEngine","cloudSprite","drawGameStartMessage","frameTotal","gameStartMessage","drawReadyMessage","toggleReadyMessage","drawGameEndMessage","gameEndMessage","FadeInOut","black","setBlackAlphaTo","changeBlackAlphaBy","alphaIncrement","path","anchorX","anchorY","sprite","numberTextureArray","numberAnimatedSprites","setChildIndex","parent","child","PikaKeyboard","left","right","up","down","downRight","super","powerHitKeyIsDownPrevious","leftKey","Key","rightKey","upKey","downKey","powerHitKey","downRightKey","getInput","isDown","subscribe","unsubscribe","value","isUp","downListener","downHandler","bind","upListener","upHandler","event","code","preventDefault","window","addEventListener","removeEventListener","PikaAudio","sounds","bgm","PikaStereoSound","pi","pikachu","loop","properBGMVolume","properSFXVolume","adjustVolume","volume","turnBGMVolume","turnOn","turnSFXVolume","muteAll","unmuteAll","center","url","centerPanning","leftPanning","rightPanning","filters","v","play","leftOrCenterOrRight","stop","PikachuVolleyball","stage","view","intro","menu","game","fadeInOut","audio","keyboardArray","normalFPS","slowMotionFPS","SLOW_MOTION_FRAMES_NUM","slowMotionFramesLeft","slowMotionNumOfSkippedFrames","winningScore","roundEnded","afterMenuSelection","beforeStartOfNewGame","startOfNewGame","afterEndOfRound","beforeStartOfNextRound","noInputFrameCounter","noInputFrameTotal","paused","isStereoSound","_isPracticeMode","gameLoop","round","pressedPowerHit","playSoundEffect","restart","isPracticeMode","pauseResumeManager","_precedence","pause","pikaVolley","precedence","resume","setSelectedOptionsBtn","options","graphic","graphicSharpBtn","document","getElementById","graphicSoftBtn","classList","remove","add","bgmOnBtn","bgmOffBtn","sfx","stereoBtn","monoBtn","sfxOffBtn","speed","slowSpeedBtn","mediumSpeedBtn","fastSpeedBtn","winningScore5Btn","winningScore10Btn","winningScore15Btn","toggleDropdown","dropdownID","hideSubmenus","hideDropdownsExcept","toggle","showSubmenu","submenuBtnID","subMenuID","dropdowns","getElementsByClassName","length","id","submenus","submenuBtns","settings","renderer","antialias","backgroundColor","backgroundAlpha","forceCanvas","loader","setAttribute","appendChild","render","setup","ticker","applyOptions","maxFPS","applyAndSaveOptions","gameDropdownBtn","optionsDropdownBtn","aboutBtn","disabled","pauseBtn","contains","noticeBox1","noticeOKBtn1","winningScoreInNoticeBox1","isWinningScoreAlreadyReached","noticeBox2","noticeOKBtn2","textContent","practiceModeOnBtn","practiceModeOffBtn","aboutBox","closeAboutBtn","click","setUpBtns","saveOptions","target","matches","setUpToShowDropdownsAndSubmenus","menuBar","visibilityState","setUpUI","start","loadingBox","progressBar","onProgress","style","progress","onComplete","closeAboutBox","load","setUpInitialUI","localStorageWrapper","get","key","localStorage","getItem","err","console","error","set","setItem"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"main.bundle.js","mappings":"uIAKO,MAAMA,EAAc,CACzBC,aAAc,+CACdC,SAAU,CAAC,EACXC,OAAQ,CAAC,GAGLD,EAAWF,EAAYE,SAC7BA,EAASE,QAAU,CAACC,EAAGC,IAAM,mBAAmBD,KAAKC,QACrDJ,EAASK,KAAQC,GAAM,aAAaA,QACpCN,EAASO,OAAUC,GAAM,iBAAiBA,QAE1CR,EAASS,SAAW,uBACpBT,EAASU,SAAW,uBACpBV,EAASW,WAAa,yBACtBX,EAASY,YAAc,0BACvBZ,EAASa,sBAAwB,mCACjCb,EAASc,uBAAyB,oCAClCd,EAASe,cAAgB,4BACzBf,EAASgB,eAAiB,6BAC1BhB,EAASiB,WAAa,yBACtBjB,EAASkB,OAAS,qBAClBlB,EAASmB,WAAa,sBACtBnB,EAASoB,WAAa,sBACtBpB,EAASqB,WAAa,sBACtBrB,EAASsB,MAAQ,oBACjBtB,EAASuB,KAAO,mBAChBvB,EAASwB,MAAQ,oBAEjBxB,EAASyB,UAAY,gCACrBzB,EAAS0B,MAAQ,4BACjB1B,EAAS2B,SAAW,+BAEpB3B,EAAS4B,KAAO,uBAChB5B,EAAS6B,QAAU,0BACnB7B,EAAS8B,mBAAqB,qCAC9B9B,EAAS+B,MAAQ,wBACjB/B,EAASgC,cAAgB,gCACzBhC,EAASiC,YAAc,8BACvBjC,EAASkC,WAAa,6BAEtBlC,EAASmC,gBAAkB,sBAE3B,MAAMlC,EAASH,EAAYG,OAC3BA,EAAOmC,IAAM,qCACbnC,EAAOoC,UAAY,2CACnBpC,EAAOqC,KAAO,2CACdrC,EAAOsC,IAAM,2CACbtC,EAAOuC,GAAK,2CACZvC,EAAOC,QAAU,2CACjBD,EAAOwC,SAAW,2CAClBxC,EAAOyC,kBAAoB,0C,6HChCpB,SAASC,IACd,OACSC,KAAKC,MAAM,MAAQD,KAAKE,SAGnC,CCIA,MAAMC,EAAe,IAERC,EAAoB,IAM3BC,EAAiC,IAIjCC,EAA+B,IAyB9B,MAAMC,EAMXC,YAAYC,EAAmBC,GAC7BC,KAAKC,QAAU,IAAIC,GAAO,EAAOJ,GACjCE,KAAKG,QAAU,IAAID,GAAO,EAAMH,GAChCC,KAAKI,KAAO,IAAIC,GAAK,EACvB,CAQAC,sBAAsBC,GACpB,MAAMC,EAsNV,SAAuBP,EAASE,EAASC,EAAMG,GAC7C,MAAMC,EA8FR,SAA+DJ,GAI7DA,EAAKK,kBAAoBL,EAAKM,UAC9BN,EAAKO,kBAAoBP,EAAKQ,UAC9BR,EAAKM,UAAYN,EAAKS,EACtBT,EAAKQ,UAAYR,EAAKU,EAGtB,IAAIC,EAAqBX,EAAKY,cAAiBZ,EAAKa,UAAY,EAAK,GAOjEF,EAAqB,EACvBA,GAAsB,GACbA,EAAqB,KAC9BA,IAAuB,IAEzBX,EAAKY,aAAeD,EACpBX,EAAKc,SAAYd,EAAKY,aAAe,GAAM,EAE3C,MAAMG,EAAcf,EAAKS,EAAIT,EAAKa,WAa9BE,EAzYc,IAyYeA,EAAc3B,KAC7CY,EAAKa,WAAab,EAAKa,WAGzB,IAAIG,EAAchB,EAAKU,EAAIV,EAAKiB,UA0BhC,OAxBID,EAAc,IAChBhB,EAAKiB,UAAY,GAKjBhC,KAAKiC,IAAIlB,EAAKS,EAAIpB,GAjZQ,IAkZ1BW,EAAKU,EAhZ0B,MAkZ3BV,EAAKU,GAhZyB,IAiZ5BV,EAAKiB,UAAY,IACnBjB,EAAKiB,WAAajB,EAAKiB,WAGrBjB,EAAKS,EAAIpB,EACXW,EAAKa,WAAa5B,KAAKiC,IAAIlB,EAAKa,WAEhCb,EAAKa,UAAY5B,KAAKiC,IAAIlB,EAAKa,YAKrCG,EAAchB,EAAKU,EAAIV,EAAKiB,UAExBD,EAAczB,GAMhBS,EAAKmB,MAAMC,mBAAoB,EAE/BpB,EAAKiB,WAAajB,EAAKiB,UACvBjB,EAAKqB,aAAerB,EAAKS,EACzBT,EAAKU,EAAInB,EACTS,EAAKsB,kBAlbW,GAmbhBtB,EAAKuB,aAAehC,KACb,IAETS,EAAKU,EAAIM,EACThB,EAAKS,EAAIT,EAAKS,EAAIT,EAAKa,UACvBb,EAAKiB,WAAa,GAEX,EACT,CArLIO,CAAsDxB,GAExD,IAAIyB,EACAC,EACJ,IAAK,IAAIlF,EAAI,EAAGA,EAAI,EAAGA,IACX,IAANA,GACFiF,EAAS5B,EACT6B,EAAiB3B,IAEjB0B,EAAS1B,EACT2B,EAAiB7B,GAQnB8B,EAAkC3B,GAElC4B,EACEH,EACAtB,EAAe3D,GACfkF,EACA1B,GAQJ,IAAK,IAAIxD,EAAI,EAAGA,EAAI,EAAGA,IAEnBiF,EADQ,IAANjF,EACOqD,EAEAE,GAUQ,IALA8B,EACjB7B,EACAyB,EAAOhB,EACPgB,EAAOf,IAGoC,IAAvCe,EAAOK,8BACTC,EACE/B,EACAyB,EAAOhB,EACPN,EAAe3D,GACfiF,EAAOO,OAETP,EAAOK,6BAA8B,GAGvCL,EAAOK,6BAA8B,EAQzC,OAAO1B,CACT,CA1RiC6B,CAC3BrC,KAAKC,QACLD,KAAKG,QACLH,KAAKI,KACLG,GAEF,OAAOC,CACT,EA4BF,MAAMN,EAMJL,YAAYyC,EAAWC,GAErBvC,KAAKsC,UAAYA,EAEjBtC,KAAKuC,WAAaA,EAClBvC,KAAKwC,wBAGLxC,KAAKyC,gBAAkB,EAEvBzC,KAAK0C,uBAAyB,EAE9B1C,KAAK2C,UAAW,EAEhB3C,KAAK4C,WAAY,EASjB5C,KAAK6C,uBAAyB,EAS9B7C,KAAKuB,MAAQ,CACXuB,WAAW,EACXC,MAAM,EACNC,KAAK,EAET,CAKAR,wBAEExC,KAAKa,EAAI,GACLb,KAAKsC,YACPtC,KAAKa,EAAIrB,KAGXQ,KAAKc,EAAIpB,EAETM,KAAKqB,UAAY,EAEjBrB,KAAKkC,6BAA8B,EASnClC,KAAKoC,MAAQ,EAEbpC,KAAKiD,YAAc,EAEnBjD,KAAKkD,8BAAgC,EAErClD,KAAKmD,qBAAuB,EAe5BnD,KAAKoD,iBAAmBhE,IAAS,CACnC,EAYF,MAAMiB,EAKJR,YAAYwD,GACVrD,KAAKwC,sBAAsBa,GAE3BrD,KAAKsD,sBAAwB,EAM7BtD,KAAKkB,SAAW,EAEhBlB,KAAKgB,aAAe,EAEpBhB,KAAKyB,aAAe,EAEpBzB,KAAK2B,aAAe,EAMpB3B,KAAKU,UAAY,EACjBV,KAAKS,kBAAoB,EACzBT,KAAKY,UAAY,EACjBZ,KAAKW,kBAAoB,EAQzBX,KAAKuB,MAAQ,CACXgC,UAAU,EACV/B,mBAAmB,EAEvB,CAMAgB,sBAAsBa,GAEpBrD,KAAKa,EAAI,IACc,IAAnBwC,IACFrD,KAAKa,EAAIrB,KAGXQ,KAAKc,EAAI,EAETd,KAAKiB,UAAY,EAEjBjB,KAAKqB,UAAY,EAEjBrB,KAAK0B,kBAAoB,EAEzB1B,KAAKwD,YAAa,CACpB,EA4FF,SAASvB,EAAwC7B,EAAMqD,EAASC,GAC9D,IAAIC,EAAOvD,EAAKS,EAAI4C,EACpB,OAAIpE,KAAKiC,IAAIqC,IAxVY,KAyVvBA,EAAOvD,EAAKU,EAAI4C,EACZrE,KAAKiC,IAAIqC,IA1VU,GA+V3B,CA0GA,SAAS3B,EACPH,EACA+B,EACA9B,EACA1B,GAOA,IAL0B,IAAtByB,EAAOU,YA6Sb,SAAoCV,EAAQzB,EAAM0B,EAAgB8B,GAChEA,EAAUC,WAAa,EACvBD,EAAUE,WAAa,EACvBF,EAAUL,SAAW,EAErB,IAAIQ,EAA+B3D,EAAKkD,sBACxC,GACEjE,KAAKiC,IAAIlB,EAAKS,EAAIgB,EAAOhB,GAAK,KAC9BxB,KAAKiC,IAAIlB,EAAKa,WAAaY,EAAOuB,iBAAmB,EACrD,CACA,MAAMY,EAAeC,OAAOpC,EAAOS,WAAa7C,GAE7CW,EAAKkD,uBAAyBU,GAC7B5D,EAAKkD,uBACHW,OAAOpC,EAAOS,WAAa9C,EAAeC,IACZ,IAAlCoC,EAAOgB,yBAGPkB,EACEC,EAAe,IAErB,CAeA,GAZE3E,KAAKiC,IAAIyC,EAA+BlC,EAAOhB,GAC/CgB,EAAOuB,iBAAmB,EAEtBvB,EAAOhB,EAAIkD,EACbH,EAAUC,WAAa,EAEvBD,EAAUC,YAAc,EAEjBzE,IAAS,IAAO,IACzByC,EAAOgB,uBAAyBzD,IAAS,GAGtB,IAAjByC,EAAOO,MAAa,CAEpB/C,KAAKiC,IAAIlB,EAAKa,WAAaY,EAAOuB,iBAAmB,GACrD/D,KAAKiC,IAAIlB,EAAKS,EAAIgB,EAAOhB,GAnyBJ,IAoyBrBT,EAAKU,GAAK,IACVV,EAAKU,EAAI,GAAKe,EAAOuB,iBAAmB,IACxChD,EAAKiB,UAAY,IAEjBuC,EAAUE,YAAc,GAG1B,MAAME,EAAeC,OAAOpC,EAAOS,WAAa7C,EAC1CyE,GAAiBD,OAAOpC,EAAOS,WAAa,GAAK7C,EAErDW,EAAKkD,sBAAwBU,GAC7B5D,EAAKkD,sBAAwBY,GAC7B7E,KAAKiC,IAAIlB,EAAKS,EAAIgB,EAAOhB,GACG,EAA1BgB,EAAOuB,iBAnzBO,IAozBhBhD,EAAKS,EAAImD,GACT5D,EAAKS,EAAIqD,GACT9D,EAAKU,EAAI,MAGT8C,EAAUL,SAAW,EACjB1B,EAAOhB,EAAIT,EAAKS,EAClB+C,EAAUC,WAAa,EAEvBD,EAAUC,YAAc,EAG9B,MAAO,IAAqB,IAAjBhC,EAAOO,OAAgC,IAAjBP,EAAOO,SAClC/C,KAAKiC,IAAIlB,EAAKS,EAAIgB,EAAOhB,GAAK,IAC5BgB,EAAOhB,EAAIT,EAAKS,EAClB+C,EAAUC,WAAa,EAEvBD,EAAUC,YAAc,GAGxBxE,KAAKiC,IAAIlB,EAAKS,EAAIgB,EAAOhB,GAAK,IAAMxB,KAAKiC,IAAIlB,EAAKU,EAAIe,EAAOf,GAAK,IAAI,CACxE,MAAMqD,EA8BZ,SAAoCtC,EAAQzB,EAAM0B,EAAgB8B,GAChE,GAAIxE,IAAS,GAAM,EACjB,IAAK,IAAIyE,EAAa,EAAGA,GAAc,EAAGA,IACxC,IAAK,IAAIC,GAAc,EAAGA,EAAa,EAAGA,IAAc,CACtD,MAAMR,EAAwBc,EAC5BP,EACAC,EACA1D,GAEF,IACGkD,GACCW,OAAOpC,EAAOS,WAAa7C,GAC3B6D,GACEW,OAAOpC,EAAOS,WAAa9C,EAAeC,IAC9CJ,KAAKiC,IAAIgC,EAAwBxB,EAAejB,GAr3BpC,GAy3BZ,OAFA+C,EAAUC,WAAaA,EACvBD,EAAUE,WAAaA,GAChB,CAEX,MAGF,IAAK,IAAID,EAAa,EAAGA,GAAc,EAAGA,IACxC,IAAK,IAAIC,EAAa,EAAGA,GAAc,EAAGA,IAAc,CACtD,MAAMR,EAAwBc,EAC5BP,EACAC,EACA1D,GAEF,IACGkD,GACCW,OAAOpC,EAAOS,WAAa7C,GAC3B6D,GACEW,OAAOpC,EAAOS,WAAa9C,EAAeC,IAC9CJ,KAAKiC,IAAIgC,EAAwBxB,EAAejB,GA14BpC,GA84BZ,OAFA+C,EAAUC,WAAaA,EACvBD,EAAUE,WAAaA,GAChB,CAEX,CAGJ,OAAO,CACT,CA3EgCO,CACxBxC,EACAzB,EACA0B,EACA8B,IAEwB,IAAtBO,IACFP,EAAUL,SAAW,EAEnBlE,KAAKiC,IAAIQ,EAAejB,EAAIgB,EAAOhB,GAAK,KACd,IAA1B+C,EAAUE,aAEVF,EAAUE,YAAc,GAG9B,CAEJ,CAxYIQ,CAA2BzC,EAAQzB,EAAM0B,EAAgB8B,GAItC,IAAjB/B,EAAOO,MAKT,OAJAP,EAAOa,wBAA0B,OAC7Bb,EAAOa,uBAAyB,IAClCb,EAAOO,MAAQ,IAMnB,IAAImC,EAAkB,EAClB1C,EAAOO,MAAQ,IAEfmC,EADE1C,EAAOO,MAAQ,EACwB,EAAvBwB,EAAUC,WAGe,EAAzBhC,EAAOY,iBAI7B,MAAM+B,EAAgB3C,EAAOhB,EAAI0D,EACjC1C,EAAOhB,EAAI2D,GAGc,IAArB3C,EAAOS,UAELkC,EA7emB,GA8erB3C,EAAOhB,EA9ec,GA+eZ2D,EAAgB/E,MACzBoC,EAAOhB,EAAIpB,KAIT+E,EAAgB/E,IAClBoC,EAAOhB,EAAIpB,IACF+E,EAAgBhF,MACzBqC,EAAOhB,EAAIrB,KAMbqC,EAAOO,MAAQ,IACW,IAA1BwB,EAAUE,YACVjC,EAAOf,IAAMpB,IAEbmC,EAAOR,WAAa,GACpBQ,EAAOO,MAAQ,EACfP,EAAOoB,YAAc,EAIrBpB,EAAON,MAAMyB,KAAM,GAIrB,MAAMyB,EAAgB5C,EAAOf,EAAIe,EAAOR,UA4CxC,GA3CAQ,EAAOf,EAAI2D,EACPA,EAAgB/E,EAClBmC,EAAOR,WAAa,EACXoD,EAAgB/E,IAEzBmC,EAAOR,UAAY,EACnBQ,EAAOf,EAAIpB,EACXmC,EAAOoB,YAAc,EACA,IAAjBpB,EAAOO,OAETP,EAAOO,MAAQ,EACfP,EAAOoB,YAAc,EACrBpB,EAAOa,sBAAwB,GAE/Bb,EAAOO,MAAQ,GAIQ,IAAvBwB,EAAUL,WACS,IAAjB1B,EAAOO,OAGTP,EAAOsB,qBAAuB,EAC9BtB,EAAOoB,YAAc,EACrBpB,EAAOO,MAAQ,EAKfP,EAAON,MAAMwB,MAAO,GACM,IAAjBlB,EAAOO,OAAwC,IAAzBwB,EAAUC,aAEzChC,EAAOO,MAAQ,EACfP,EAAOoB,YAAc,EACrBpB,EAAOY,gBAAkBmB,EAAUC,WACnChC,EAAOR,WAAa,EAIpBQ,EAAON,MAAMyB,KAAM,IAIF,IAAjBnB,EAAOO,MACTP,EAAOoB,aAAepB,EAAOoB,YAAc,GAAK,OAC3C,GAAqB,IAAjBpB,EAAOO,MACZP,EAAOsB,qBAAuB,GAChCtB,EAAOoB,aAAe,EAClBpB,EAAOoB,YAAc,IACvBpB,EAAOoB,YAAc,EACrBpB,EAAOO,MAAQ,IAGjBP,EAAOsB,sBAAwB,OAE5B,GAAqB,IAAjBtB,EAAOO,QAChBP,EAAOsB,sBAAwB,EAC3BtB,EAAOsB,qBAAuB,GAAG,CACnCtB,EAAOsB,qBAAuB,EAC9B,MAAMuB,EACJ7C,EAAOoB,YAAcpB,EAAOqB,+BAC1BwB,EAAoB,GAAKA,EAAoB,KAC/C7C,EAAOqB,+BACJrB,EAAOqB,+BAEZrB,EAAOoB,YACLpB,EAAOoB,YAAcpB,EAAOqB,6BAChC,EAGuB,IAArBrB,EAAOe,YACY,IAAjBf,EAAOO,SACe,IAApBP,EAAOc,UACTd,EAAOO,MAAQ,EAIfP,EAAON,MAAMuB,WAAY,GAEzBjB,EAAOO,MAAQ,EAEjBP,EAAOsB,qBAAuB,EAC9BtB,EAAOoB,YAAc,GAW3B,SAAgCpB,IACL,IAArBA,EAAOe,WAAsBf,EAAOoB,YAAc,IACpDpB,EAAOsB,sBAAwB,EAC3BtB,EAAOsB,qBAAuB,IAChCtB,EAAOsB,qBAAuB,EAC9BtB,EAAOoB,aAAe,GAG5B,CAjBI0B,CAAuB9C,GAE3B,CA6BA,SAASM,EACP/B,EACAqD,EACAG,EACAgB,GAMIxE,EAAKS,EAAI4C,EAGXrD,EAAKa,YAAe5B,KAAKiC,IAAIlB,EAAKS,EAAI4C,GAAW,EAAK,GAC7CrD,EAAKS,EAAI4C,IAClBrD,EAAKa,UAAa5B,KAAKiC,IAAIlB,EAAKS,EAAI4C,GAAW,EAAK,GAI/B,IAAnBrD,EAAKa,YACPb,EAAKa,UAAa7B,IAAS,EAAK,GAGlC,MAAMyF,EAAmBxF,KAAKiC,IAAIlB,EAAKiB,WACvCjB,EAAKiB,WAAawD,EAEdA,EAAmB,KACrBzE,EAAKiB,WAAa,IAIA,IAAhBuD,GACExE,EAAKS,EAAIpB,EACXW,EAAKa,UAAmD,IAAtC5B,KAAKiC,IAAIsC,EAAUC,YAAc,GAEnDzD,EAAKa,UAAoD,KAAtC5B,KAAKiC,IAAIsC,EAAUC,YAAc,GAEtDzD,EAAKqB,aAAerB,EAAKS,EACzBT,EAAKuB,aAAevB,EAAKU,EAEzBV,EAAKiB,UAAYhC,KAAKiC,IAAIlB,EAAKiB,WAAauC,EAAUE,WAAa,EACnE1D,EAAKsB,kBApqBW,GAwqBhBtB,EAAKmB,MAAMgC,UAAW,EAEtBnD,EAAKoD,YAAa,GAElBpD,EAAKoD,YAAa,EAGpBzB,EAAkC3B,EACpC,CAOA,SAAS2B,EAAkC3B,GACzC,MAAM0E,EAAW,CACfjE,EAAGT,EAAKS,EACRC,EAAGV,EAAKU,EACRG,UAAWb,EAAKa,UAChBI,UAAWjB,EAAKiB,WAElB,IAAI0D,EAAc,EAClB,OAAa,CACXA,IAEA,MAAMC,EAAkBF,EAAS7D,UAAY6D,EAASjE,EA6BtD,IA5BImE,EAnsBY,IAmsBqBA,EAAkBxF,KACrDsF,EAAS7D,WAAa6D,EAAS7D,WAE7B6D,EAAShE,EAAIgE,EAASzD,UAAY,IACpCyD,EAASzD,UAAY,GAKrBhC,KAAKiC,IAAIwD,EAASjE,EAAIpB,GAxsBE,IAysBxBqF,EAAShE,EAvsBoB,MA0sBzBgE,EAAShE,EAxsBmB,IAysB1BgE,EAASzD,UAAY,IACvByD,EAASzD,WAAayD,EAASzD,WAG7ByD,EAASjE,EAAIpB,EACfqF,EAAS7D,WAAa5B,KAAKiC,IAAIwD,EAAS7D,WAExC6D,EAAS7D,UAAY5B,KAAKiC,IAAIwD,EAAS7D,YAK7C6D,EAAShE,EAAIgE,EAAShE,EAAIgE,EAASzD,UAGjCyD,EAAShE,EAAInB,GACboF,GA5sBsB,IA8sBtB,MAEFD,EAASjE,EAAIiE,EAASjE,EAAIiE,EAAS7D,UACnC6D,EAASzD,WAAa,CACxB,CACAjB,EAAKkD,sBAAwBwB,EAASjE,CACxC,CAiLA,SAASuD,EACPa,EACAC,EACA9E,GAEA,MAAM0E,EAAW,CACfjE,EAAGT,EAAKS,EACRC,EAAGV,EAAKU,EACRG,UAAWb,EAAKa,UAChBI,UAAWjB,EAAKiB,WAEdyD,EAASjE,EAAIpB,EACfqF,EAAS7D,UAAkD,IAArC5B,KAAKiC,IAAI2D,GAAuB,GAEtDH,EAAS7D,UAAmD,KAArC5B,KAAKiC,IAAI2D,GAAuB,GAEzDH,EAASzD,UAAYhC,KAAKiC,IAAIwD,EAASzD,WAAa6D,EAAsB,EAE1E,IAAIH,EAAc,EAClB,OAAa,CACXA,IAEA,MAAMC,EAAkBF,EAASjE,EAAIiE,EAAS7D,UAoC9C,IAnCI+D,EAj7BY,IAi7BqBA,EAAkBxF,KACrDsF,EAAS7D,WAAa6D,EAAS7D,WAE7B6D,EAAShE,EAAIgE,EAASzD,UAAY,IACpCyD,EAASzD,UAAY,GAGrBhC,KAAKiC,IAAIwD,EAASjE,EAAIpB,GAp7BE,IAq7BxBqF,EAAShE,EAn7BoB,KA07BzBgE,EAASzD,UAAY,IACvByD,EAASzD,WAAayD,EAASzD,WAkBnCyD,EAAShE,EAAIgE,EAAShE,EAAIgE,EAASzD,UAEjCyD,EAAShE,EAAInB,GACboF,GAj8BsB,IAm8BtB,OAAOD,EAASjE,EAElBiE,EAASjE,EAAIiE,EAASjE,EAAIiE,EAAS7D,UACnC6D,EAASzD,WAAa,CACxB,CACF,C,qBCz/BO,MAAM8D,EACXtF,cACEG,KAAKoF,cAAuBhG,IAAS,IAAf,GACtBY,KAAKqF,cAAgBjG,IAAS,IAC9BY,KAAKsF,sBAAwB,EAAKlG,IAAS,EAC3CY,KAAKuF,mBAAqBnG,IAAS,EACrC,CAEIoG,eAEF,OAAO,EAAInG,KAAKiC,IAAItB,KAAKuF,mBAAqB,EAChD,CAEIE,0BACF,OAAOzF,KAAKoF,cAAgBpF,KAAKwF,QACnC,CAEIE,0BACF,OAAO1F,KAAKqF,cAAgBrF,KAAKwF,QACnC,CAEIG,kBACF,OAAO,GAAK,EAAI3F,KAAKwF,QACvB,CAEII,mBACF,OAAO,GAAK,EAAI5F,KAAKwF,QACvB,EAMK,MAAMK,EACXhG,cACEG,KAAK8F,cAAgB,EACrB9F,KAAK+F,sBAAwB,EAC7B/F,KAAKgG,QAAU,GACf,IAAK,IAAIpJ,EAAI,EAAGA,EAAI,GAAUA,IAC5BoD,KAAKgG,QAAQC,KAAK,IAEtB,E,aCtCF,MAAMxJ,EAAW,aAQV,MAAMyJ,EAKXrG,YAAYsG,GACV,MAAMC,EAAWD,EAAU,kBAA0BC,SAErDpG,KAAKqG,KAAOC,EAAuBF,EAAU3J,EAAS4B,KAAM,GAAK,IACjE2B,KAAKqG,KAAKxF,EAAI,IACdb,KAAKqG,KAAKvF,EAAI,IAEdd,KAAKuG,UAAY,IAAI,KACrBvG,KAAKuG,UAAUC,SAASxG,KAAKqG,KAC/B,CAGII,cACF,OAAOzG,KAAKuG,UAAUE,OACxB,CAGIA,YAAQC,GACV1G,KAAKuG,UAAUE,QAAUC,CAC3B,CAMAC,SAASC,GACP,MAAMP,EAAOrG,KAAKqG,KACG,IAAjBO,EAIAA,EAAe,IACjBP,EAAKQ,MAAQxH,KAAKyH,IAAI,EAAGT,EAAKQ,MAAQ,KAC7BD,GAAgB,MACzBP,EAAKQ,MAAQxH,KAAK0H,IAAI,EAAGV,EAAKQ,MAAQ,MANtCR,EAAKQ,MAAQ,CAQjB,EAMK,MAAMG,EAKXnH,YAAYsG,GACV,MAAMC,EAAWD,EAAU,kBAA0BC,SAErDpG,KAAKiH,SAAW,CACdC,QAASZ,EAAuBF,EAAU3J,EAAS6B,QAAS,EAAG,GAC/D6I,kBAAmBb,EACjBF,EACA3J,EAAS8B,mBACT,EACA,GAEF6I,QAAS,CACPd,EAAuBF,EAAU3J,EAASgC,cAAe,EAAG,GAC5D6H,EAAuBF,EAAU3J,EAASiC,YAAa,EAAG,IAE5D2I,UAAWf,EAAuBF,EAAU3J,EAASyB,UAAW,EAAG,GACnEoJ,MAAOhB,EAAuBF,EAAU3J,EAAS+B,MAAO,EAAG,IAE7DwB,KAAKuH,6BAomBT,SAA0CnB,GACxC,MAAMG,EAAY,IAAI,KAChBiB,EAAUpB,EAAS3J,EAASmC,iBAC5B6I,EAAID,EAAQE,MACZC,EAAIH,EAAQI,OAElB,IAAIC,EACJ,IAAK,IAAIhL,EAAI,EAAGA,EAAIwC,KAAKC,MAAM,IAAMqI,GAAK,EAAG9K,IAC3C,IAAK,IAAID,EAAI,EAAGA,EAAIyC,KAAKC,MAAM,IAAMmI,GAAK,EAAG7K,IAC3CiL,EAAO,IAAI,IAAOL,GAClBM,EAAoCvB,EAAWsB,EAAMJ,EAAI7K,EAAG+K,EAAI9K,GAIpE,OAAO0J,CACT,CAlnBMwB,CAAiC3B,GAGnCpG,KAAKiH,SAASI,UAAUxG,EAAI,IAAMb,KAAKiH,SAASI,UAAUG,QAAQE,MAAQ,EAC1E1H,KAAKiH,SAASI,UAAUvG,EAAI,IAG5Bd,KAAKiH,SAASE,kBAAkBtG,EAAI,IACpCb,KAAKiH,SAASE,kBAAkBrG,EAAI,GACpCd,KAAKiH,SAASC,QAAQrG,EAAI,IAC1Bb,KAAKiH,SAASC,QAAQpG,EAAI,GAE1Bd,KAAKuG,UAAY,IAAI,KACrBvG,KAAKuG,UAAUC,SAASxG,KAAKuH,8BAC7BvH,KAAKuG,UAAUC,SAASxG,KAAKiH,SAASC,SACtClH,KAAKuG,UAAUC,SAASxG,KAAKiH,SAASE,mBACtCnH,KAAKuG,UAAUC,SAASxG,KAAKiH,SAASG,QAAQ,IAC9CpH,KAAKuG,UAAUC,SAASxG,KAAKiH,SAASG,QAAQ,IAC9CpH,KAAKuG,UAAUC,SAASxG,KAAKiH,SAASI,WACtCrH,KAAKuG,UAAUC,SAASxG,KAAKiH,SAASK,OACtCtH,KAAKgI,qBAELhI,KAAKiI,gCAAkC,EACvCjI,KAAKkI,iBAAmB,EACxBlI,KAAKmI,oCAAsC,CAC7C,CAGI1B,cACF,OAAOzG,KAAKuG,UAAUE,OACxB,CAGIA,YAAQC,GACV1G,KAAKuG,UAAUE,QAAUC,GAGZ,IAATA,GACF1G,KAAKgI,oBAET,CAEAA,qBACE,IAAK,MAAMI,KAAQpI,KAAKiH,SACtBjH,KAAKiH,SAASmB,GAAM3B,SAAU,CAElC,CAOA4B,iBAAiBzB,GACf,MAAM0B,EAAY,CAAC,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAC7CC,EAAevI,KAAKiH,SAASK,MAC7BG,EAAIc,EAAaf,QAAQE,MACzBC,EAAIY,EAAaf,QAAQI,OAM/B,GAJqB,IAAjBhB,IACF2B,EAAa9B,SAAU,GAGrBG,EAAe,GAAI,CACrB,MAAM4B,EAAYnJ,KAAKC,MAAMD,KAAKC,MAAOsH,EAAea,EAAK,IAAM,GAC7DgB,EAAapJ,KAAKC,MAAMD,KAAKC,MAAOsH,EAAee,EAAK,IAAM,GACpEY,EAAab,MAAoB,EAAZc,EACrBD,EAAaX,OAAsB,EAAba,EACtBF,EAAa1H,EAAI,IAAM2H,EACvBD,EAAazH,EAAI,GAAK2H,CACxB,KAAO,CACL,MAAMC,GAAS9B,EAAe,GAAK,EAE7B4B,EAAYnJ,KAAKC,MAAMD,KAAKC,MAAOgJ,EAAUI,GAASjB,EAAK,IAAM,GACjEgB,EAAapJ,KAAKC,MACtBD,KAAKC,MAAOgJ,EAAUI,GAASf,EAAK,IAAM,GAE5CY,EAAab,MAAoB,EAAZc,EACrBD,EAAaX,OAAsB,EAAba,EACtBF,EAAazH,EAAI,GAAK2H,EACtBF,EAAa1H,EAAI,IAAM2H,CACzB,CACF,CAMAG,cAAc/B,GACS,IAAjBA,IACF5G,KAAKiH,SAASI,UAAUZ,SAAU,EAClCzG,KAAKiH,SAASI,UAAUR,MAAQ,GAElC7G,KAAKiH,SAASI,UAAUR,MAAQxH,KAAKyH,IACnC,EACA9G,KAAKiH,SAASI,UAAUR,MAAQ,KAG9BD,EAAe,KACjB5G,KAAKiH,SAASI,UAAUR,MAAQ,EAEpC,CAOA+B,wBAAwBhC,GACD,IAAjBA,IACF5G,KAAKuH,6BAA6Bd,SAAU,EAC5CzG,KAAKuH,6BAA6BV,MAAQ,GAK5C,MAAMc,EAAI3H,KAAKuH,6BAA6BsB,WAAW,GAAGrB,QAAQI,OAClE5H,KAAKiI,iCACFjI,KAAKiI,gCAAkC,GAAKN,EAC/C3H,KAAKuH,6BAA6B1G,GAAKb,KAAKiI,gCAC5CjI,KAAKuH,6BAA6BzG,GAAKd,KAAKiI,gCAExCrB,EAAe,KAEjB5G,KAAKuH,6BAA6BV,MAAQxH,KAAKyH,IAC7C,EACA9G,KAAKuH,6BAA6BV,MAAQ,MAI1CD,EAAe,KACjB5G,KAAKuH,6BAA6BV,MAAQ,EAE9C,CAOAiC,6BAA6BlC,GAC3B,GAAqB,IAAjBA,EASJ,GAJIA,EAAe,KACjB5G,KAAKiH,SAASE,kBAAkBV,SAAU,GAGxCG,EAAe,IAAMA,GAAgB,GAAI,CAC3C,MAAMmC,EAAQ,IAAM,IAAMnC,EAAe,IACzC5G,KAAKiH,SAASE,kBAAkBtG,EAAI,IAAMkI,CAC5C,MAAWnC,EAAe,IAAMA,GAAgB,IAC9C5G,KAAKiH,SAASE,kBAAkBtG,EAAI,IACpCb,KAAKiH,SAASE,kBAAkBO,MAAQ,IAAM,IAAMd,EAAe,KAC1DA,EAAe,IAAMA,GAAgB,IAC9C5G,KAAKiH,SAASE,kBAAkBtG,EAAI,IACpCb,KAAKiH,SAASE,kBAAkBO,MAAQ,GAAK,IAAMd,EAAe,KACzDA,EAAe,KACxB5G,KAAKiH,SAASE,kBAAkBtG,EAAI,IACpCb,KAAKiH,SAASE,kBAAkBO,MAC9B1H,KAAKiH,SAASE,kBAAkBK,QAAQE,YApB1C1H,KAAKiH,SAASE,kBAAkBV,SAAU,CAsB9C,CAOAuC,mBAAmBpC,GACI,IAAjBA,EAKAA,EAAe,KACjB5G,KAAKiH,SAASC,QAAQT,SAAU,GALhCzG,KAAKiH,SAASC,QAAQT,SAAU,CAOpC,CAOAwC,oBAAoBrC,GAClB,MAAMQ,EAAUpH,KAAKiH,SAASG,QACxBK,EAAIL,EAAQ,GAAGI,QAAQE,MACvBC,EAAIP,EAAQ,GAAGI,QAAQI,OAE7B,GAAqB,IAAjBhB,GAOJ,GAAIA,EAAe,GAAI,CACjB5G,KAAKmI,oCAAsC,KAC7CnI,KAAKmI,qCAAuC,GAE9C,IAAK,IAAIvL,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,MAAMsM,EAAWjF,OAAOjE,KAAKkI,kBAAoBtL,GAC3CuM,EACJD,GAAYlJ,KAAKmI,oCAAsC,GACnDiB,EACJF,EAAWlJ,KAAKmI,oCAElBf,EAAQxK,GAAG6J,SAAU,EACrBW,EAAQxK,GAAGiE,EAAI,IAAM4G,EAAI,EAAI0B,EAC7B/B,EAAQxK,GAAGkE,EAAI,IAAM,GAAKlE,EAAIwM,EAC9BhC,EAAQxK,GAAG8K,MAAQD,EAAI,EAAI0B,EAC3B/B,EAAQxK,GAAGgL,OAASD,EAAI,EAAIyB,CAC9B,CACF,OAvBE,IAAK,IAAIxM,EAAI,EAAGA,EAAI,EAAGA,IACrBwK,EAAQxK,GAAG6J,SAAU,CAuB3B,CAMA4C,cAAczM,GACZoD,KAAKkI,gBAAkBtL,EACvBoD,KAAKmI,oCAAsC,CAC7C,EAMK,MAAMmB,EAKXzJ,YAAYsG,GACV,MAAMC,EAAWD,EAAU,kBAA0BC,SAGrDpG,KAAKuJ,YAwYT,SAAyBnD,GACvB,MAAMmD,EAAc,IAAI,KAGxB,IAAI1B,EACAL,EAAUpB,EAAS3J,EAASS,UAChC,IAAK,IAAIL,EAAI,EAAGA,EAAI,GAAIA,IACtB,IAAK,IAAID,EAAI,EAAGA,EAAI,GAAUA,IAC5BiL,EAAO,IAAI,IAAOL,GAClBM,EAAoCyB,EAAa1B,EAAM,GAAKjL,EAAG,GAAKC,GAKxE2K,EAAUpB,EAAS3J,EAASU,UAC5B0K,EAAO,IAAI,IAAOL,GAClBM,EAAoCyB,EAAa1B,EAAM,EAAG,KAG1DL,EAAUpB,EAAS3J,EAASW,YAC5B,IAAK,IAAIR,EAAI,EAAGA,EAAI,GAAUA,IAC5BiL,EAAO,IAAI,IAAOL,GAClBM,EAAoCyB,EAAa1B,EAAM,GAAKjL,EAAG,KAIjE4K,EAAUpB,EAAS3J,EAASY,aAC5B,IAAK,IAAIT,EAAI,EAAGA,EAAI,GAAcA,IAChCiL,EAAO,IAAI,IAAOL,GAClBM,EAAoCyB,EAAa1B,EAAM,GAAKjL,EAAG,KAEjE4K,EAAUpB,EAAS3J,EAASa,uBAC5BuK,EAAO,IAAI,IAAOL,GAClBM,EAAoCyB,EAAa1B,EAAM,EAAG,KAC1DL,EAAUpB,EAAS3J,EAASc,wBAC5BsK,EAAO,IAAI,IAAOL,GAClBM,EAAoCyB,EAAa1B,EAAM,IAAU,KAGjEL,EAAUpB,EAAS3J,EAASe,eAC5B,IAAK,IAAIX,EAAI,EAAGA,EAAI,EAAGA,IACrB,IAAK,IAAID,EAAI,EAAGA,EAAI,GAAUA,IAC5BiL,EAAO,IAAI,IAAOL,GAClBM,EACEyB,EACA1B,EACA,GAAKjL,EACL,IAAM,GAAKC,GAMjB2K,EAAUpB,EAAS3J,EAASgB,gBAC5BoK,EAAO,IAAI,IAAOL,GAClBM,EAAoCyB,EAAa1B,EAAM,IAAK,KAC5DL,EAAUpB,EAAS3J,EAASiB,YAC5B,IAAK,IAAIb,EAAI,EAAGA,EAAI,GAAIA,IACtBgL,EAAO,IAAI,IAAOL,GAClBM,EAAoCyB,EAAa1B,EAAM,IAAK,IAAM,EAAIhL,GAGxE,OAAO0M,CACT,CAvcuBC,CAAgBpD,GACnC,MAAMqD,EA6cV,SAAmCrD,GACjC,MAAMsD,EAAmB,CAAC9M,EAAGC,IAAMuJ,EAAS3J,EAASE,QAAQC,EAAGC,IAC1D8M,EAAqB,GAC3B,IAAK,IAAI/M,EAAI,EAAGA,EAAI,EAAGA,IACrB,GAAU,IAANA,EACF+M,EAAmB1D,KAAKyD,EAAiB9M,EAAG,IAC5C+M,EAAmB1D,KAAKyD,EAAiB9M,EAAG,SACvC,GAAU,IAANA,EACT+M,EAAmB1D,KAAKyD,EAAiB9M,EAAG,SAE5C,IAAK,IAAIC,EAAI,EAAGA,EAAI,EAAGA,IACrB8M,EAAmB1D,KAAKyD,EAAiB9M,EAAGC,IAIlD,MAAM+M,EAAwB,IAAI,IAAeD,GAAoB,GAC/DE,EAAwB,IAAI,IAAeF,GAAoB,GAOrE,OALAC,EAAsBE,OAAOjJ,EAAI,GACjC+I,EAAsBE,OAAOhJ,EAAI,GACjC+I,EAAsBC,OAAOjJ,EAAI,GACjCgJ,EAAsBC,OAAOhJ,EAAI,GAE1B,CAAC8I,EAAuBC,EACjC,CAre0BE,CAA0B3D,GAChDpG,KAAKC,QAAUwJ,EAAc,GAC7BzJ,KAAKG,QAAUsJ,EAAc,GAC7BzJ,KAAKI,KAyeT,SAAiCgG,GAC/B,MAAM4D,EAAkBjN,GAAMqJ,EAAS3J,EAASK,KAAKC,IAC/CkN,EAAmB,CACvBD,EAAe,GACfA,EAAe,GACfA,EAAe,GACfA,EAAe,GACfA,EAAe,GACfA,EAAe,UAEXE,EAAqB,IAAI,IAAeD,GAAkB,GAKhE,OAHAC,EAAmBJ,OAAOjJ,EAAI,GAC9BqJ,EAAmBJ,OAAOhJ,EAAI,GAEvBoJ,CACT,CAzfgBC,CAAwB/D,GACpCpG,KAAKoK,UAAY9D,EACfF,EACA3J,EAASmB,WACT,GACA,IAEFoC,KAAKqK,UAAY/D,EACfF,EACA3J,EAASoB,WACT,GACA,IAEFmC,KAAKsK,MAAQhE,EACXF,EACA3J,EAASqB,WACT,GACA,IAIFkC,KAAKuK,YAAc,CACjBC,EAAqBpE,GACrBoE,EAAqBpE,IAGvBpG,KAAKyK,QAAU,CACbC,WAAYpE,EAAuBF,EAAU3J,EAASkB,OAAQ,GAAK,IACnEgN,WAAYrE,EAAuBF,EAAU3J,EAASkB,OAAQ,GAAK,IACnEiN,QAAStE,EAAuBF,EAAU3J,EAASkB,OAAQ,GAAK,KAGlEqC,KAAKiH,SAAW,CACd4D,UAAWvE,EAAuBF,EAAU3J,EAASkC,WAAY,EAAG,GACpEmM,MAAOxE,EAAuBF,EAAU3J,EAAS0B,MAAO,EAAG,GAC3D4M,QAASzE,EAAuBF,EAAU3J,EAAS2B,SAAU,EAAG,IAGlE4B,KAAKgL,eA4gBT,SAA4B5E,GAC1B,MAAM4E,EAAiB,IAAI,KACrBxD,EAAUpB,EAAS3J,EAASsB,OAClC,IAAK,IAAInB,EAAI,EAAGA,EAt3BI,GAs3BeA,IAAK,CACtC,MAAMqO,EAAQ,IAAI,IAAOzD,GACzByD,EAAMnB,OAAOjJ,EAAI,EACjBoK,EAAMnB,OAAOhJ,EAAI,EACjBkK,EAAexE,SAASyE,EAC1B,CAEA,OAAOD,CACT,CAvhB0BE,CAAmB9E,GACzCpG,KAAKmL,cA6hBT,SAA2B/E,GACzB,MAAM+E,EAAgB,IAAI,KACpB3D,EAAUpB,EAAS3J,EAASuB,MAClC,IAAK,IAAIpB,EAAI,EAAGA,EAAI,GAAUA,IAE5BkL,EAAoCqD,EADvB,IAAI,IAAO3D,GACiC,GAAK5K,EAAG,GAGnE,OAAOuO,CACT,CAtiByBC,CAAkBhF,GAKvCpG,KAAKuG,UAAY,IAAI,KACrBvG,KAAKuG,UAAUC,SAASxG,KAAKuJ,aAC7BvJ,KAAKuG,UAAUC,SAASxG,KAAKgL,gBAC7BhL,KAAKuG,UAAUC,SAASxG,KAAKmL,eAC7BnL,KAAKuG,UAAUC,SAASxG,KAAKyK,QAAQC,YACrC1K,KAAKuG,UAAUC,SAASxG,KAAKyK,QAAQE,YACrC3K,KAAKuG,UAAUC,SAASxG,KAAKyK,QAAQG,SACrC5K,KAAKuG,UAAUC,SAASxG,KAAKC,SAC7BD,KAAKuG,UAAUC,SAASxG,KAAKG,SAC7BH,KAAKuG,UAAUC,SAASxG,KAAKqK,WAC7BrK,KAAKuG,UAAUC,SAASxG,KAAKoK,WAC7BpK,KAAKuG,UAAUC,SAASxG,KAAKI,MAC7BJ,KAAKuG,UAAUC,SAASxG,KAAKsK,OAC7BtK,KAAKuG,UAAUC,SAASxG,KAAKuK,YAAY,IACzCvK,KAAKuG,UAAUC,SAASxG,KAAKuK,YAAY,IACzCvK,KAAKuG,UAAUC,SAASxG,KAAKiH,SAAS4D,WACtC7K,KAAKuG,UAAUC,SAASxG,KAAKiH,SAAS6D,OACtC9K,KAAKuG,UAAUC,SAASxG,KAAKiH,SAAS8D,SAGtC/K,KAAKuJ,YAAY1I,EAAI,EACrBb,KAAKuJ,YAAYzI,EAAI,EACrBd,KAAKgL,eAAenK,EAAI,EACxBb,KAAKgL,eAAelK,EAAI,EACxBd,KAAKmL,cAActK,EAAI,EACvBb,KAAKmL,cAAcrK,EAAI,EAEvBd,KAAKiH,SAAS6D,MAAMjK,EAAI,IACxBb,KAAKiH,SAAS6D,MAAMhK,EAAI,GACxBd,KAAKuK,YAAY,GAAG1J,EAAI,GACxBb,KAAKuK,YAAY,GAAGzJ,EAAI,GACxBd,KAAKuK,YAAY,GAAG1J,EAAI,IACxBb,KAAKuK,YAAY,GAAGzJ,EAAI,GAExBd,KAAKyK,QAAQC,WAAW5J,EAAI,IAC5Bd,KAAKyK,QAAQE,WAAW7J,EAAI,IAC5Bd,KAAKyK,QAAQG,QAAQ9J,EAAI,IAEzBd,KAAKgI,qBAKLhI,KAAKqL,WAAa,GAClB,IAAK,IAAIzO,EAAI,EAAGA,EAzZE,GAyZiBA,IACjCoD,KAAKqL,WAAWpF,KAAK,IAAId,GAE3BnF,KAAKsL,KAAO,IAAIzF,CAClB,CAGIY,cACF,OAAOzG,KAAKuG,UAAUE,OACxB,CAGIA,YAAQC,GACV1G,KAAKuG,UAAUE,QAAUC,GAGZ,IAATA,GACF1G,KAAKgI,oBAET,CAEAA,qBACE,IAAK,MAAMI,KAAQpI,KAAKiH,SACtBjH,KAAKiH,SAASmB,GAAM3B,SAAU,CAElC,CAOA8E,mBAAmBC,GACjB,MAAMvL,EAAUuL,EAAQvL,QAClBE,EAAUqL,EAAQrL,QAClBC,EAAOoL,EAAQpL,KAErBJ,KAAKC,QAAQY,EAAIZ,EAAQY,EACzBb,KAAKC,QAAQa,EAAIb,EAAQa,EACH,IAAlBb,EAAQmC,OAAiC,IAAlBnC,EAAQmC,MACjCpC,KAAKC,QAAQwL,MAAM5K,GAAiC,IAA7BZ,EAAQwC,iBAA0B,EAAI,EAE7DzC,KAAKC,QAAQwL,MAAM5K,EAAI,EAEzBb,KAAKyK,QAAQC,WAAW7J,EAAIZ,EAAQY,EAEpCb,KAAKG,QAAQU,EAAIV,EAAQU,EACzBb,KAAKG,QAAQW,EAAIX,EAAQW,EACH,IAAlBX,EAAQiC,OAAiC,IAAlBjC,EAAQiC,MACjCpC,KAAKG,QAAQsL,MAAM5K,EAAgC,IAA5BV,EAAQsC,gBAAwB,GAAK,EAE5DzC,KAAKG,QAAQsL,MAAM5K,GAAK,EAE1Bb,KAAKyK,QAAQE,WAAW9J,EAAIV,EAAQU,EAEpC,MAAM6K,EAAeC,EACnB1L,EAAQmC,MACRnC,EAAQgD,aAEJ2I,EAAeD,EACnBxL,EAAQiC,MACRjC,EAAQ8C,aAEVjD,KAAKC,QAAQ4L,YAAYH,GACzB1L,KAAKG,QAAQ0L,YAAYD,GAEzB5L,KAAKI,KAAKS,EAAIT,EAAKS,EACnBb,KAAKI,KAAKU,EAAIV,EAAKU,EACnBd,KAAKyK,QAAQG,QAAQ/J,EAAIT,EAAKS,EAC9Bb,KAAKI,KAAKyL,YAAYzL,EAAKc,UAGvBd,EAAKsB,kBAAoB,GAC3BtB,EAAKsB,mBAAqB,EAC1B1B,KAAKsK,MAAM5C,MAAQ,EAAItH,EAAKsB,kBAC5B1B,KAAKsK,MAAM1C,OAAS,EAAIxH,EAAKsB,kBAC7B1B,KAAKsK,MAAMzJ,EAAIT,EAAKqB,aACpBzB,KAAKsK,MAAMxJ,EAAIV,EAAKuB,aACpB3B,KAAKsK,MAAM7D,SAAU,GAErBzG,KAAKsK,MAAM7D,SAAU,GAGC,IAApBrG,EAAKoD,YACPxD,KAAKoK,UAAUvJ,EAAIT,EAAKM,UACxBV,KAAKoK,UAAUtJ,EAAIV,EAAKQ,UACxBZ,KAAKqK,UAAUxJ,EAAIT,EAAKK,kBACxBT,KAAKqK,UAAUvJ,EAAIV,EAAKO,kBAExBX,KAAKoK,UAAU3D,SAAU,EACzBzG,KAAKqK,UAAU5D,SAAU,IAEzBzG,KAAKoK,UAAU3D,SAAU,EACzBzG,KAAKqK,UAAU5D,SAAU,EAE7B,CAMAqF,wBAAwBC,GACtB,IAAK,IAAInP,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,MAAMoP,EAAahM,KAAKuK,YAAY3N,GAC9BqP,EAAQF,EAAOnP,GACfsP,EAAsBF,EAAWnD,WAAW,GAC5CsD,EAAqBH,EAAWnD,WAAW,GAEjDqD,EAAoBL,YAAYI,EAAQ,IAExCE,EAAmBN,YAAYxM,KAAKC,MAAM2M,EAAQ,IAAM,IAEtDE,EAAmB1F,QADjBwF,GAAS,EAKf,CACF,CAKAG,oBACE,MAAMf,EAAarL,KAAKqL,WAClBC,EAAOtL,KAAKsL,MDzef,SAA4BD,EAAYC,GAC7C,IAAK,IAAI1O,EAAI,EAAGA,EAAI,GAAIA,IACtByO,EAAWzO,GAAGwI,eAAiBiG,EAAWzO,GAAG0I,sBACzC+F,EAAWzO,GAAGwI,cAAgB,MAChCiG,EAAWzO,GAAGwI,eAAiB,GAC/BiG,EAAWzO,GAAGyI,cAAgBjG,IAAS,IACvCiM,EAAWzO,GAAG0I,sBAAwB,EAAKlG,IAAS,GAEtDiM,EAAWzO,GAAG2I,oBACX8F,EAAWzO,GAAG2I,mBAAqB,GAAK,GAG7C+F,EAAKxF,eAAiBwF,EAAKvF,sBACvBuF,EAAKxF,cAAgB,IACvBwF,EAAKxF,cAAgB,GACrBwF,EAAKvF,uBAAyB,GACrBuF,EAAKxF,cAAgB,GAAKwF,EAAKvF,sBAAwB,IAChEuF,EAAKvF,sBAAwB,EAC7BuF,EAAKxF,eAAkB1G,IAAS,IAGlC,IAAK,IAAIxC,EAAI,EAAGA,EAAI,GAAUA,IAC5B0O,EAAKtF,QAAQpJ,GAAK,IAAM0O,EAAKxF,cAAiB1G,IAAS,CAE3D,CCmdIiN,CAAmBhB,EAAYC,GAE/B,IAAK,IAAI1O,EAAI,EAAGA,EAzhBE,GAyhBiBA,IAAK,CACtC,MAAMqO,EAAQI,EAAWzO,GACnB0P,EAActM,KAAKgL,eAAenC,WAAWjM,GACnD0P,EAAYzL,EAAIoK,EAAMxF,oBACtB6G,EAAYxL,EAAImK,EAAMvF,oBAEtB4G,EAAY5E,MAAQuD,EAAMtF,YAE1B2G,EAAY1E,OAASqD,EAAMrF,YAC7B,CAEA,IAAK,IAAIhJ,EAAI,EAAGA,EAAI,GAAUA,IACToD,KAAKmL,cAActC,WAAWjM,GACtCkE,EAAIwK,EAAKtF,QAAQpJ,EAEhC,CAQA2P,qBAAqB3F,EAAc4F,GACjC,GAAqB,IAAjB5F,EACF5G,KAAKiH,SAAS4D,UAAUpE,SAAU,OAC7B,GAAIG,GAAgB4F,EAAa,EAEtC,YADAxM,KAAKiH,SAAS4D,UAAUpE,SAAU,GAIpC,MAAMgG,EAAmBzM,KAAKiH,SAAS4D,UAEjCpD,EAAIgF,EAAiBjF,QAAQE,MAC7BC,EAAI8E,EAAiBjF,QAAQI,OAC7BY,EAAYnJ,KAAKC,MAAOmI,EAAIb,EAAgB,IAC5C6B,EAAapJ,KAAKC,MAAOqI,EAAIf,EAAgB,IACnD6F,EAAiB5L,EAAI,IAAM2H,EAC3BiE,EAAiB3L,EAAI,GAAK,EAAI2H,EAC9BgE,EAAiB/E,MAAQ,EAAIc,EAC7BiE,EAAiB7E,OAAS,EAAIa,CAChC,CAMAiE,iBAAiBhG,GACf1G,KAAKiH,SAAS6D,MAAMrE,QAAUC,CAChC,CAMAiG,qBACE3M,KAAKiH,SAAS6D,MAAMrE,SAAWzG,KAAKiH,SAAS6D,MAAMrE,OACrD,CAOAmG,mBAAmBhG,GACjB,MAAMiG,EAAiB7M,KAAKiH,SAAS8D,QAC/BtD,EAAIoF,EAAerF,QAAQE,MAC3BC,EAAIkF,EAAerF,QAAQI,OAKjC,GAHqB,IAAjBhB,IACFiG,EAAepG,SAAU,GAEvBG,EAAe,GAAI,CACrB,MAAMuC,EAAqB,EAAI9J,KAAKC,OAAQ,GAAKsH,GAAgBa,EAAK,IAChE2B,EACJ,EAAI/J,KAAKC,OAAQ,GAAKsH,GAAgBe,EAAK,IAE7CkF,EAAehM,EAAI,IAAM4G,EAAI,EAAI0B,EACjC0D,EAAe/L,EAAI,GAAKsI,EACxByD,EAAenF,MAAQD,EAAI,EAAI0B,EAC/B0D,EAAejF,OAASD,EAAI,EAAIyB,CAClC,MACEyD,EAAehM,EAAI,IAAM4G,EAAI,EAC7BoF,EAAe/L,EAAI,GACnB+L,EAAenF,MAAQD,EACvBoF,EAAejF,OAASD,CAE5B,EAMK,MAAMmF,EACXjN,YAAYsG,GACV,MAAMC,EAAWD,EAAU,kBAA0BC,SACrDpG,KAAK+M,MAAQzG,EAAuBF,EAAU3J,EAASwB,MAAO,EAAG,GACjE+B,KAAK+M,MAAMrF,MAAQ,IACnB1H,KAAK+M,MAAMnF,OAAS,IACpB5H,KAAK+M,MAAMlM,EAAI,EACfb,KAAK+M,MAAMjM,EAAI,EACfd,KAAK+M,MAAMlG,MAAQ,CACrB,CAGIJ,cACF,OAAOzG,KAAK+M,MAAMtG,OACpB,CAGIA,YAAQC,GACV1G,KAAK+M,MAAMtG,QAAUC,CACvB,CAMAsG,gBAAgBnG,GACd7G,KAAK+M,MAAMlG,MAAQA,EACM,IAArB7G,KAAK+M,MAAMlG,MACb7G,KAAK+M,MAAMtG,SAAU,EAErBzG,KAAK+M,MAAMtG,SAAU,CAEzB,CAMAwG,mBAAmBC,GAEflN,KAAK+M,MAAMlG,MADTqG,GAAkB,EACD7N,KAAKyH,IAAI,EAAG9G,KAAK+M,MAAMlG,MAAQqG,GAE/B7N,KAAK0H,IAAI,EAAG/G,KAAK+M,MAAMlG,MAAQqG,GAE3B,IAArBlN,KAAK+M,MAAMlG,MACb7G,KAAK+M,MAAMtG,SAAU,EAErBzG,KAAK+M,MAAMtG,SAAU,CAEzB,EA6JF,SAASH,EAAuBF,EAAU+G,EAAMC,EAASC,GACvD,MAAMC,EAAS,IAAI,IAAOlH,EAAS+G,IAGnC,OAFAG,EAAOxD,OAAOjJ,EAAIuM,EAClBE,EAAOxD,OAAOhJ,EAAIuM,EACXC,CACT,CAOA,SAAS9C,EAAqBpE,GAC5B,MACMmH,EAAqB,GAC3B,IAAK,IAAI3Q,EAAI,EAAGA,EAAI,GAAIA,IACtB2Q,EAAmBtH,MAHKhJ,EAGiBL,EAHXwJ,EAAS3J,EAASO,OAAOC,MAAhC,IAACA,EAK1B,MAAMuQ,EAAwB,CAAC,KAAM,MACrCA,EAAsB,GAAK,IAAI,IAAeD,GAAoB,GAClEC,EAAsB,GAAK,IAAI,IAAeD,GAAoB,GAElE,MAAMvB,EAAa,IAAI,KAiBvB,OAhBAlE,EACEkE,EACAwB,EAAsB,GACtB,GACA,GAEF1F,EACEkE,EACAwB,EAAsB,GACtB,EACA,GAGFxB,EAAWyB,cAAcD,EAAsB,GAAI,GACnDxB,EAAWyB,cAAcD,EAAsB,GAAI,GAE5CxB,CACT,CA2CA,SAASlE,EAAoC4F,EAAQC,EAAO9M,EAAGC,GAC7D4M,EAAOlH,SAASmH,GAChBA,EAAM7D,OAAOjJ,EAAI,EACjB8M,EAAM7D,OAAOhJ,EAAI,EACjB6M,EAAM9M,EAAIA,EACV8M,EAAM7M,EAAIA,CACZ,CAYA,SAAS6K,EAAsCvJ,EAAOa,GACpD,OAAIb,EAAQ,EACH,EAAIA,EAAQa,EACA,IAAVb,EACF,GAAKa,EACHb,EAAQ,EACV,GAAK,GAAKA,EAAQ,GAAKa,OADzB,CAGT,CC57BO,MAAM2K,UH4FN,MACL/N,cAEEG,KAAK6D,WAAa,EAElB7D,KAAK8D,WAAa,EAElB9D,KAAKuD,SAAW,CAClB,GGtFA1D,YAAYgO,EAAMC,EAAOC,EAAIC,EAAMzK,EAAU0K,EAAY,MACvDC,QAGAlO,KAAKmO,2BAA4B,EAGjCnO,KAAKoO,QAAU,IAAIC,EAAIR,GAEvB7N,KAAKsO,SAAW,IAAID,EAAIP,GAExB9N,KAAKuO,MAAQ,IAAIF,EAAIN,GAErB/N,KAAKwO,QAAU,IAAIH,EAAIL,GAEvBhO,KAAKyO,YAAc,IAAIJ,EAAI9K,GAE3BvD,KAAK0O,aAAe,IAAIL,EAAIJ,EAC9B,CAMAU,WACM3O,KAAKoO,QAAQQ,OACf5O,KAAK6D,YAAc,EAEnB7D,KAAKsO,SAASM,QACb5O,KAAK0O,cAAgB1O,KAAK0O,aAAaE,OAExC5O,KAAK6D,WAAa,EAElB7D,KAAK6D,WAAa,EAGhB7D,KAAKuO,MAAMK,OACb5O,KAAK8D,YAAc,EAEnB9D,KAAKwO,QAAQI,QACZ5O,KAAK0O,cAAgB1O,KAAK0O,aAAaE,OAExC5O,KAAK8D,WAAa,EAElB9D,KAAK8D,WAAa,EAGpB,MAAM8K,EAAS5O,KAAKyO,YAAYG,QAC3B5O,KAAKmO,2BAA6BS,EACrC5O,KAAKuD,SAAW,EAEhBvD,KAAKuD,SAAW,EAElBvD,KAAKmO,0BAA4BS,CACnC,CAKAC,YACE7O,KAAKoO,QAAQS,YACb7O,KAAKsO,SAASO,YACd7O,KAAKuO,MAAMM,YACX7O,KAAKwO,QAAQK,YACb7O,KAAKyO,YAAYI,YACjB7O,KAAK0O,aAAaG,WACpB,CAKAC,cACE9O,KAAKoO,QAAQU,cACb9O,KAAKsO,SAASQ,cACd9O,KAAKuO,MAAMO,cACX9O,KAAKwO,QAAQM,cACb9O,KAAKyO,YAAYK,cACjB9O,KAAK0O,aAAaI,aACpB,EAOF,MAAMT,EAMJxO,YAAYkP,GACV/O,KAAK+O,MAAQA,EACb/O,KAAK4O,QAAS,EACd5O,KAAKgP,MAAO,EAEZhP,KAAKiP,aAAejP,KAAKkP,YAAYC,KAAKnP,MAC1CA,KAAKoP,WAAapP,KAAKqP,UAAUF,KAAKnP,MACtCA,KAAK6O,WACP,CAMAK,YAAYI,GACNA,EAAMC,OAASvP,KAAK+O,QACtB/O,KAAK4O,QAAS,EACd5O,KAAKgP,MAAO,EACZM,EAAME,iBAEV,CAMAH,UAAUC,GACJA,EAAMC,OAASvP,KAAK+O,QACtB/O,KAAK4O,QAAS,EACd5O,KAAKgP,MAAO,EACZM,EAAME,iBAEV,CAKAX,YAOEY,OAAOC,iBAAiB,QAAS1P,KAAKoP,YACtCK,OAAOC,iBAAiB,UAAW1P,KAAKiP,aAC1C,CAKAH,cACEW,OAAOE,oBAAoB,UAAW3P,KAAKiP,cAC3CQ,OAAOE,oBAAoB,QAAS3P,KAAKoP,YACzCpP,KAAK4O,QAAS,EACd5O,KAAKgP,MAAO,CACd,E,aCnKF,MAAMtS,EAAS,WAOR,MAAMkT,EAKX/P,YAAYsG,GAEVnG,KAAK6P,OAAS,CACZC,IAAK,IAAIC,EAAgB5J,EAAUzJ,EAAOmC,KAAK0C,OAC/CuB,UAAW,IAAIiN,EAAgB5J,EAAUzJ,EAAOoC,WAAWyC,OAC3DwB,KAAM,IAAIgN,EAAgB5J,EAAUzJ,EAAOqC,MAAMwC,OACjDyB,IAAK,IAAI+M,EAAgB5J,EAAUzJ,EAAOsC,KAAKuC,OAC/CyO,GAAI,IAAID,EAAgB5J,EAAUzJ,EAAOuC,IAAIsC,OAC7C0O,QAAS,IAAIF,EAAgB5J,EAAUzJ,EAAOC,SAAS4E,OACvDgC,SAAU,IAAIwM,EAAgB5J,EAAUzJ,EAAOwC,UAAUqC,OACzDC,kBAAmB,IAAIuO,EACrB5J,EAAUzJ,EAAOyC,mBAAmBoC,QAIxCvB,KAAK6P,OAAOC,IAAII,MAAO,EAEvBlQ,KAAKmQ,gBAAkB,GAEvBnQ,KAAKoQ,gBAAkB,IACvBpQ,KAAKqQ,cACP,CAKAA,eACE,IAAK,MAAMjI,KAAQpI,KAAK6P,OAEpB7P,KAAK6P,OAAOzH,GAAMkI,OADP,QAATlI,EACyBpI,KAAKmQ,gBAELnQ,KAAKoQ,eAGtC,CAMAG,cAAcC,GACZ,IAAIF,EAEFA,EADEE,EACOxQ,KAAKmQ,gBAEL,EAEXnQ,KAAK6P,OAAOC,IAAIQ,OAASA,CAC3B,CAMAG,cAAcD,GACZ,IAAIF,EAEFA,EADEE,EACOxQ,KAAKoQ,gBAEL,EAEX,IAAK,MAAMhI,KAAQpI,KAAK6P,OACT,QAATzH,IACFpI,KAAK6P,OAAOzH,GAAMkI,OAASA,EAGjC,CAEAI,UACE,cACF,CAEAC,YACE,gBACF,EAMF,MAAMZ,EAKJlQ,YAAY0B,GACVvB,KAAK4Q,OAASrP,EACdvB,KAAK6N,KAAO,UAAWtM,EAAMsP,KAC7B7Q,KAAK8N,MAAQ,UAAWvM,EAAMsP,KAE9B,MAAMC,EAAgB,IAAI,kBAAqB,GACzCC,EAAc,IAAI,mBAAsB,KACxCC,EAAe,IAAI,kBAAqB,KAC9ChR,KAAK4Q,OAAOK,QAAU,CAACH,GACvB9Q,KAAK6N,KAAKoD,QAAU,CAACF,GACrB/Q,KAAK8N,MAAMmD,QAAU,CAACD,EACxB,CAKIV,WAAOY,GACTlR,KAAK4Q,OAAON,OAASY,EACrBlR,KAAK6N,KAAKyC,OAASY,EACnBlR,KAAK8N,MAAMwC,OAASY,CACtB,CAKIhB,SAAKxJ,GACP1G,KAAK4Q,OAAOV,KAAOxJ,EACnB1G,KAAK6N,KAAKqC,KAAOxJ,EACjB1G,KAAK8N,MAAMoC,KAAOxJ,CACpB,CAMAyK,KAAKC,EAAsB,GACG,IAAxBA,EACFpR,KAAK4Q,OAAOO,QACsB,IAAzBC,EACTpR,KAAK6N,KAAKsD,OACuB,IAAxBC,GACTpR,KAAK8N,MAAMqD,MAEf,CAKAE,OACErR,KAAK4Q,OAAOS,OACZrR,KAAK6N,KAAKwD,OACVrR,KAAK8N,MAAMuD,MACb,EC3IK,MAAMC,EAMXzR,YAAY0R,EAAOpL,GACjBnG,KAAKwR,KAAO,CACVC,MAAO,IAAIvL,EAAUC,GACrBuL,KAAM,IAAI1K,EAASb,GACnBwL,KAAM,IAAIrI,EAASnD,GACnByL,UAAW,IAAI9E,EAAU3G,IAE3BoL,EAAM/K,SAASxG,KAAKwR,KAAKC,MAAMlL,WAC/BgL,EAAM/K,SAASxG,KAAKwR,KAAKE,KAAKnL,WAC9BgL,EAAM/K,SAASxG,KAAKwR,KAAKG,KAAKpL,WAC9BgL,EAAM/K,SAASxG,KAAKwR,KAAKI,UAAU7E,OACnC/M,KAAKwR,KAAKC,MAAMhL,SAAU,EAC1BzG,KAAKwR,KAAKE,KAAKjL,SAAU,EACzBzG,KAAKwR,KAAKG,KAAKlL,SAAU,EACzBzG,KAAKwR,KAAKI,UAAUnL,SAAU,EAE9BzG,KAAK6R,MAAQ,IAAIjC,EAAUzJ,GAC3BnG,KAAKwL,QAAU,IAAI5L,GAAY,GAAM,GACrCI,KAAK8R,cAAgB,CACnB,IAAIlE,EAAa,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,QACzD,IAAIA,EACF,YACA,aACA,UACA,YACA,UAKJ5N,KAAK+R,UAAY,GAEjB/R,KAAKgS,cAAgB,EAGrBhS,KAAKiS,uBAAyB,EAE9BjS,KAAKkS,qBAAuB,EAE5BlS,KAAKmS,6BAA+B,EAGpCnS,KAAKkI,gBAAkB,EAGvBlI,KAAK+L,OAAS,CAAC,EAAG,GAElB/L,KAAKoS,aAAe,GAGpBpS,KAAK4C,WAAY,EAEjB5C,KAAKqS,YAAa,EAElBrS,KAAKqD,gBAAiB,EAGtBrD,KAAK4G,aAAe,EAEpB5G,KAAKwM,WAAa,CAChBiF,MAAO,IACPa,mBAAoB,GACpBC,qBAAsB,GACtBC,eAAgB,GAChBC,gBAAiB,EACjBC,uBAAwB,GACxB3H,QAAS,KAIX/K,KAAK2S,oBAAsB,EAE3B3S,KAAK4S,kBAAoB,CACvBlB,KAAM,KAIR1R,KAAK6S,QAAS,EAGd7S,KAAK8S,eAAgB,EAGrB9S,KAAK+S,iBAAkB,EAMvB/S,KAAKoC,MAAQpC,KAAKyR,KACpB,CAMAuB,WACE,IAAoB,IAAhBhT,KAAK6S,OAAT,CAGA,GAAI7S,KAAKkS,qBAAuB,EAAG,CAEjC,GADAlS,KAAKmS,+BAEHnS,KAAKmS,6BACH9S,KAAK4T,MAAMjT,KAAK+R,UAAY/R,KAAKgS,gBACnC,EAEA,OAEFhS,KAAKkS,uBACLlS,KAAKmS,6BAA+B,CACtC,CAEAnS,KAAK8R,cAAc,GAAGnD,WACtB3O,KAAK8R,cAAc,GAAGnD,WACtB3O,KAAKoC,OAhBL,CAiBF,CAMAqP,QAC4B,IAAtBzR,KAAK4G,eACP5G,KAAKwR,KAAKC,MAAMhL,SAAU,EAC1BzG,KAAKwR,KAAKI,UAAU5E,gBAAgB,GACpChN,KAAK6R,MAAMhC,OAAOC,IAAIuB,QAExBrR,KAAKwR,KAAKC,MAAM9K,SAAS3G,KAAK4G,cAC9B5G,KAAK4G,eAGgC,IAAnC5G,KAAK8R,cAAc,GAAGvO,UACa,IAAnCvD,KAAK8R,cAAc,GAAGvO,WAEtBvD,KAAK4G,aAAe,EACpB5G,KAAKwR,KAAKC,MAAMhL,SAAU,EAC1BzG,KAAKoC,MAAQpC,KAAK0R,MAGhB1R,KAAK4G,cAAgB5G,KAAKwM,WAAWiF,QACvCzR,KAAK4G,aAAe,EACpB5G,KAAKwR,KAAKC,MAAMhL,SAAU,EAC1BzG,KAAKoC,MAAQpC,KAAK0R,KAEtB,CAMAA,OAeE,GAd0B,IAAtB1R,KAAK4G,eACP5G,KAAKwR,KAAKE,KAAKjL,SAAU,EACzBzG,KAAKwR,KAAKI,UAAU5E,gBAAgB,GACpChN,KAAKkI,gBAAkB,EACvBlI,KAAKwR,KAAKE,KAAKrI,cAAcrJ,KAAKkI,kBAEpClI,KAAKwR,KAAKE,KAAKrJ,iBAAiBrI,KAAK4G,cACrC5G,KAAKwR,KAAKE,KAAK/I,cAAc3I,KAAK4G,cAClC5G,KAAKwR,KAAKE,KAAK9I,wBAAwB5I,KAAK4G,cAC5C5G,KAAKwR,KAAKE,KAAK5I,6BAA6B9I,KAAK4G,cACjD5G,KAAKwR,KAAKE,KAAK1I,mBAAmBhJ,KAAK4G,cACvC5G,KAAKwR,KAAKE,KAAKzI,oBAAoBjJ,KAAK4G,cACxC5G,KAAK4G,eAGH5G,KAAK4G,aAAe,KACgB,IAAnC5G,KAAK8R,cAAc,GAAGvO,UACc,IAAnCvD,KAAK8R,cAAc,GAAGvO,UAExBvD,KAAK4G,aAAe,QAItB,KAAI5G,KAAK4G,cAAgB,IAAzB,CA0BA,IArByC,IAAtC5G,KAAK8R,cAAc,GAAGhO,aACiB,IAAtC9D,KAAK8R,cAAc,GAAGhO,YACC,IAAzB9D,KAAKkI,gBAOiC,IAArClI,KAAK8R,cAAc,GAAGhO,YACgB,IAArC9D,KAAK8R,cAAc,GAAGhO,YACC,IAAzB9D,KAAKkI,gBAOLlI,KAAK2S,uBALL3S,KAAK2S,oBAAsB,EAC3B3S,KAAKkI,gBAAkB,EACvBlI,KAAKwR,KAAKE,KAAKrI,cAAcrJ,KAAKkI,iBAClClI,KAAK6R,MAAMhC,OAAOG,GAAGmB,SAZrBnR,KAAK2S,oBAAsB,EAC3B3S,KAAKkI,gBAAkB,EACvBlI,KAAKwR,KAAKE,KAAKrI,cAAcrJ,KAAKkI,iBAClClI,KAAK6R,MAAMhC,OAAOG,GAAGmB,QAec,IAAnCnR,KAAK8R,cAAc,GAAGvO,UACa,IAAnCvD,KAAK8R,cAAc,GAAGvO,SAkBtB,OAhB6B,IAAzBvD,KAAKkI,iBACPlI,KAAKwL,QAAQvL,QAAQsC,YAAa,EAClCvC,KAAKwL,QAAQrL,QAAQoC,YAAa,GAEK,IAAnCvC,KAAK8R,cAAc,GAAGvO,UACxBvD,KAAKwL,QAAQvL,QAAQsC,YAAa,EAClCvC,KAAKwL,QAAQrL,QAAQoC,YAAa,GACU,IAAnCvC,KAAK8R,cAAc,GAAGvO,WAC/BvD,KAAKwL,QAAQvL,QAAQsC,YAAa,EAClCvC,KAAKwL,QAAQrL,QAAQoC,YAAa,GAGtCvC,KAAK6R,MAAMhC,OAAOI,QAAQkB,OAC1BnR,KAAK4G,aAAe,EACpB5G,KAAK2S,oBAAsB,OAC3B3S,KAAKoC,MAAQpC,KAAKsS,oBAIhBtS,KAAK2S,qBAAuB3S,KAAK4S,kBAAkBlB,OACrD1R,KAAKwL,QAAQvL,QAAQsC,YAAa,EAClCvC,KAAKwL,QAAQrL,QAAQoC,YAAa,EAClCvC,KAAK4G,aAAe,EACpB5G,KAAK2S,oBAAsB,EAC3B3S,KAAKoC,MAAQpC,KAAKsS,mBApDpB,CAsDF,CAMAA,qBACEtS,KAAKwR,KAAKI,UAAU3E,mBAAmB,EAAI,IAC3CjN,KAAK4G,eACD5G,KAAK4G,cAAgB5G,KAAKwM,WAAW8F,qBACvCtS,KAAK4G,aAAe,EACpB5G,KAAKoC,MAAQpC,KAAKuS,qBAEtB,CAMAA,uBACEvS,KAAK4G,eACD5G,KAAK4G,cAAgB5G,KAAKwM,WAAW+F,uBACvCvS,KAAK4G,aAAe,EACpB5G,KAAKwR,KAAKE,KAAKjL,SAAU,EACzBzG,KAAKoC,MAAQpC,KAAKwS,eAEtB,CAMAA,iBAC4B,IAAtBxS,KAAK4G,eACP5G,KAAKwR,KAAKG,KAAKlL,SAAU,EACzBzG,KAAK4C,WAAY,EACjB5C,KAAKqS,YAAa,EAClBrS,KAAKqD,gBAAiB,EACtBrD,KAAKwL,QAAQvL,QAAQ2C,WAAY,EACjC5C,KAAKwL,QAAQvL,QAAQ0C,UAAW,EAChC3C,KAAKwL,QAAQrL,QAAQyC,WAAY,EACjC5C,KAAKwL,QAAQrL,QAAQwC,UAAW,EAEhC3C,KAAK+L,OAAO,GAAK,EACjB/L,KAAK+L,OAAO,GAAK,EACjB/L,KAAKwR,KAAKG,KAAK7F,wBAAwB9L,KAAK+L,QAE5C/L,KAAKwL,QAAQvL,QAAQuC,wBACrBxC,KAAKwL,QAAQrL,QAAQqC,wBACrBxC,KAAKwL,QAAQpL,KAAKoC,sBAAsBxC,KAAKqD,gBAC7CrD,KAAKwR,KAAKG,KAAKpG,mBAAmBvL,KAAKwL,SAEvCxL,KAAKwR,KAAKI,UAAU5E,gBAAgB,GACpChN,KAAK6R,MAAMhC,OAAOC,IAAIqB,QAGxBnR,KAAKwR,KAAKG,KAAKpF,qBACbvM,KAAK4G,aACL5G,KAAKwM,WAAWgG,gBAElBxS,KAAKwR,KAAKG,KAAKvF,oBACfpM,KAAKwR,KAAKI,UAAU3E,oBAAqB,EAAI,IAC7CjN,KAAK4G,eAED5G,KAAK4G,cAAgB5G,KAAKwM,WAAWgG,iBACvCxS,KAAK4G,aAAe,EACpB5G,KAAKwR,KAAKI,UAAU5E,gBAAgB,GACpChN,KAAKoC,MAAQpC,KAAKiT,MAEtB,CAMAA,QACE,MAAMC,EAC+B,IAAnClT,KAAK8R,cAAc,GAAGvO,UACa,IAAnCvD,KAAK8R,cAAc,GAAGvO,SAExB,IACsC,IAApCvD,KAAKwL,QAAQvL,QAAQsC,aACe,IAApCvC,KAAKwL,QAAQrL,QAAQoC,YACrB2Q,EAKA,OAHAlT,KAAK4G,aAAe,EACpB5G,KAAKwR,KAAKG,KAAKlL,SAAU,OACzBzG,KAAKoC,MAAQpC,KAAKyR,OAIpB,MAAMjR,EAAuBR,KAAKwL,QAAQlL,sBACxCN,KAAK8R,eAOP,GAJA9R,KAAKmT,kBACLnT,KAAKwR,KAAKG,KAAKpG,mBAAmBvL,KAAKwL,SACvCxL,KAAKwR,KAAKG,KAAKvF,qBAEQ,IAAnBpM,KAAK4C,UAWP,OAVA5C,KAAKwR,KAAKG,KAAK/E,mBAAmB5M,KAAK4G,cACvC5G,KAAK4G,qBAEH5G,KAAK4G,cAAgB5G,KAAKwM,WAAWzB,SACpC/K,KAAK4G,cAAgB,IAAMsM,KAE5BlT,KAAK4G,aAAe,EACpB5G,KAAKwR,KAAKG,KAAKlL,SAAU,EACzBzG,KAAKoC,MAAQpC,KAAKyR,QAMpBjR,IACyB,IAAzBR,KAAK+S,kBACe,IAApB/S,KAAKqS,aACc,IAAnBrS,KAAK4C,YAED5C,KAAKwL,QAAQpL,KAAKqB,aAAehC,GACnCO,KAAKqD,gBAAiB,EACtBrD,KAAK+L,OAAO,IAAM,EACd/L,KAAK+L,OAAO,IAAM/L,KAAKoS,eACzBpS,KAAK4C,WAAY,EACjB5C,KAAKwL,QAAQvL,QAAQ0C,UAAW,EAChC3C,KAAKwL,QAAQrL,QAAQwC,UAAW,EAChC3C,KAAKwL,QAAQvL,QAAQ2C,WAAY,EACjC5C,KAAKwL,QAAQrL,QAAQyC,WAAY,KAGnC5C,KAAKqD,gBAAiB,EACtBrD,KAAK+L,OAAO,IAAM,EACd/L,KAAK+L,OAAO,IAAM/L,KAAKoS,eACzBpS,KAAK4C,WAAY,EACjB5C,KAAKwL,QAAQvL,QAAQ0C,UAAW,EAChC3C,KAAKwL,QAAQrL,QAAQwC,UAAW,EAChC3C,KAAKwL,QAAQvL,QAAQ2C,WAAY,EACjC5C,KAAKwL,QAAQrL,QAAQyC,WAAY,IAGrC5C,KAAKwR,KAAKG,KAAK7F,wBAAwB9L,KAAK+L,SACpB,IAApB/L,KAAKqS,aAA2C,IAAnBrS,KAAK4C,YACpC5C,KAAKkS,qBAAuBlS,KAAKiS,wBAEnCjS,KAAKqS,YAAa,IAGI,IAApBrS,KAAKqS,aAA0C,IAAnBrS,KAAK4C,WAED,IAA9B5C,KAAKkS,uBACPlS,KAAKwR,KAAKI,UAAU3E,mBAAmB,EAAI,IAC3CjN,KAAKoC,MAAQpC,KAAKyS,gBAGxB,CAMAA,kBACEzS,KAAKwR,KAAKI,UAAU3E,mBAAmB,EAAI,IAC3CjN,KAAK4G,eACD5G,KAAK4G,cAAgB5G,KAAKwM,WAAWiG,kBACvCzS,KAAK4G,aAAe,EACpB5G,KAAKoC,MAAQpC,KAAK0S,uBAEtB,CAMAA,yBAC4B,IAAtB1S,KAAK4G,eACP5G,KAAKwR,KAAKI,UAAU5E,gBAAgB,GACpChN,KAAKwR,KAAKG,KAAKjF,kBAAiB,GAEhC1M,KAAKwL,QAAQvL,QAAQuC,wBACrBxC,KAAKwL,QAAQrL,QAAQqC,wBACrBxC,KAAKwL,QAAQpL,KAAKoC,sBAAsBxC,KAAKqD,gBAC7CrD,KAAKwR,KAAKG,KAAKpG,mBAAmBvL,KAAKwL,UAGzCxL,KAAKwR,KAAKG,KAAKvF,oBACfpM,KAAKwR,KAAKI,UAAU3E,oBAAqB,EAAI,IAE7CjN,KAAK4G,eACD5G,KAAK4G,aAAe,GAAM,GAC5B5G,KAAKwR,KAAKG,KAAKhF,qBAGb3M,KAAK4G,cAAgB5G,KAAKwM,WAAWkG,yBACvC1S,KAAK4G,aAAe,EACpB5G,KAAKwR,KAAKG,KAAKjF,kBAAiB,GAChC1M,KAAKwR,KAAKI,UAAU5E,gBAAgB,GACpChN,KAAKqS,YAAa,EAClBrS,KAAKoC,MAAQpC,KAAKiT,MAEtB,CAKAE,kBACE,MAAMtB,EAAQ7R,KAAK6R,MACnB,IAAK,IAAIjV,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,MACM2E,EADSvB,KAAKwL,QAAQ,SAAS5O,EAAI,KACpB2E,MACrB,IAAI6P,EAAsB,EACtBpR,KAAK8S,gBACP1B,EAA4B,IAANxU,GAAW,EAAI,IAEf,IAApB2E,EAAMuB,YACR+O,EAAMhC,OAAO/M,UAAUqO,KAAKC,GAC5B7P,EAAMuB,WAAY,IAED,IAAfvB,EAAMwB,OACR8O,EAAMhC,OAAO9M,KAAKoO,KAAKC,GACvB7P,EAAMwB,MAAO,IAEG,IAAdxB,EAAMyB,MACR6O,EAAMhC,OAAO7M,IAAImO,KAAKC,GACtB7P,EAAMyB,KAAM,EAEhB,CACA,MAAM5C,EAAOJ,KAAKwL,QAAQpL,KACpBmB,EAAQnB,EAAKmB,MACnB,IAAI6P,EAAsB,EACtBpR,KAAK8S,gBACH1S,EAAKqB,aAAehC,EACtB2R,GAAuB,EACdhR,EAAKqB,aAAehC,IAC7B2R,EAAsB,KAGH,IAAnB7P,EAAMgC,WACRsO,EAAMhC,OAAOtM,SAAS4N,KAAKC,GAC3B7P,EAAMgC,UAAW,IAEa,IAA5BhC,EAAMC,oBACRqQ,EAAMhC,OAAOrO,kBAAkB2P,KAAKC,GACpC7P,EAAMC,mBAAoB,EAE9B,CAKA4R,UACEpT,KAAK4G,aAAe,EACpB5G,KAAK2S,oBAAsB,EAC3B3S,KAAKkS,qBAAuB,EAC5BlS,KAAKmS,6BAA+B,EACpCnS,KAAKwR,KAAKE,KAAKjL,SAAU,EACzBzG,KAAKwR,KAAKG,KAAKlL,SAAU,EACzBzG,KAAKoC,MAAQpC,KAAKyR,KACpB,CAGI4B,qBACF,OAAOrT,KAAK+S,eACd,CAKIM,mBAAe3M,GACjB1G,KAAK+S,gBAAkBrM,EACvB1G,KAAKwR,KAAKG,KAAKpH,YAAY,GAAG9D,SAAWC,EACzC1G,KAAKwR,KAAKG,KAAKpH,YAAY,GAAG9D,SAAWC,CAC3C,E,aC3fF,MAUM4M,EAAqB,CAEzBC,YARW,EAcXC,MAAO,SAAUC,EAAYC,GAEvBA,EAAa1T,KAAKuT,cACpBE,EAAWZ,QAAS,EACpB7S,KAAKuT,YAAcG,EAEvB,EAMAC,OAAQ,SAAUF,EAAYC,GACxBA,IAAe1T,KAAKuT,cACtBE,EAAWZ,QAAS,EACpB7S,KAAKuT,YA7BE,EA+BX,GAgbF,SAASK,EAAsBC,GAC7B,GAAIA,EAAQC,QAAS,CACnB,MAAMC,EAAkBC,SAASC,eAAe,qBAC1CC,EAAiBF,SAASC,eAAe,oBAC/C,OAAQJ,EAAQC,SACd,IAAK,QACHI,EAAeC,UAAUC,OAAO,YAChCL,EAAgBI,UAAUE,IAAI,YAC9B,MACF,IAAK,OACHN,EAAgBI,UAAUC,OAAO,YACjCF,EAAeC,UAAUE,IAAI,YAGnC,CACA,GAAIR,EAAQ/D,IAAK,CACf,MAAMwE,EAAWN,SAASC,eAAe,cACnCM,EAAYP,SAASC,eAAe,eAC1C,OAAQJ,EAAQ/D,KACd,IAAK,KACHyE,EAAUJ,UAAUC,OAAO,YAC3BE,EAASH,UAAUE,IAAI,YACvB,MACF,IAAK,MACHC,EAASH,UAAUC,OAAO,YAC1BG,EAAUJ,UAAUE,IAAI,YAG9B,CACA,GAAIR,EAAQW,IAAK,CACf,MAAMC,EAAYT,SAASC,eAAe,cACpCS,EAAUV,SAASC,eAAe,YAClCU,EAAYX,SAASC,eAAe,eAC1C,OAAQJ,EAAQW,KACd,IAAK,SACHE,EAAQP,UAAUC,OAAO,YACzBO,EAAUR,UAAUC,OAAO,YAC3BK,EAAUN,UAAUE,IAAI,YACxB,MACF,IAAK,OACHM,EAAUR,UAAUC,OAAO,YAC3BK,EAAUN,UAAUC,OAAO,YAC3BM,EAAQP,UAAUE,IAAI,YACtB,MACF,IAAK,MACHI,EAAUN,UAAUC,OAAO,YAC3BM,EAAQP,UAAUC,OAAO,YACzBO,EAAUR,UAAUE,IAAI,YAG9B,CACA,GAAIR,EAAQe,MAAO,CACjB,MAAMC,EAAeb,SAASC,eAAe,kBACvCa,EAAiBd,SAASC,eAAe,oBACzCc,EAAef,SAASC,eAAe,kBAC7C,OAAQJ,EAAQe,OACd,IAAK,OACHE,EAAeX,UAAUC,OAAO,YAChCW,EAAaZ,UAAUC,OAAO,YAC9BS,EAAaV,UAAUE,IAAI,YAC3B,MACF,IAAK,SACHU,EAAaZ,UAAUC,OAAO,YAC9BS,EAAaV,UAAUC,OAAO,YAC9BU,EAAeX,UAAUE,IAAI,YAC7B,MACF,IAAK,OACHQ,EAAaV,UAAUC,OAAO,YAC9BU,EAAeX,UAAUC,OAAO,YAChCW,EAAaZ,UAAUE,IAAI,YAGjC,CACA,GAAIR,EAAQzB,aAAc,CACxB,MAAM4C,EAAmBhB,SAASC,eAAe,uBAC3CgB,EAAoBjB,SAASC,eAAe,wBAC5CiB,EAAoBlB,SAASC,eAAe,wBAClD,OAAQJ,EAAQzB,cACd,IAAK,IACH6C,EAAkBd,UAAUC,OAAO,YACnCc,EAAkBf,UAAUC,OAAO,YACnCY,EAAiBb,UAAUE,IAAI,YAC/B,MACF,IAAK,KACHa,EAAkBf,UAAUC,OAAO,YACnCY,EAAiBb,UAAUC,OAAO,YAClCa,EAAkBd,UAAUE,IAAI,YAChC,MACF,IAAK,KACHW,EAAiBb,UAAUC,OAAO,YAClCa,EAAkBd,UAAUC,OAAO,YACnCc,EAAkBf,UAAUE,IAAI,YAGtC,CACF,CAiGA,SAASc,EAAeC,EAAY3B,GAClC4B,KACAC,EAAoBF,GACHpB,SAASC,eAAemB,GAAYjB,UAAUoB,OAAO,QAEpEjC,EAAmBE,MAAMC,EArpBjB,GAupBRH,EAAmBK,OAAOF,EAvpBlB,EAypBZ,CAOA,SAAS+B,EAAYC,EAAcC,GACjCL,KACArB,SAASC,eAAewB,GAActB,UAAUE,IAAI,QACpDL,SAASC,eAAeyB,GAAWvB,UAAUE,IAAI,OACnD,CAMA,SAASiB,EAAoBF,GAC3B,MAAMO,EAAY3B,SAAS4B,uBAAuB,YAClD,IAAK,IAAIhZ,EAAI,EAAGA,EAAI+Y,EAAUE,OAAQjZ,IAChC+Y,EAAU/Y,GAAGkZ,KAAOV,GACtBO,EAAU/Y,GAAGuX,UAAUC,OAAO,OAGpC,CAKA,SAASiB,KACP,MAAMU,EAAW/B,SAAS4B,uBAAuB,WACjD,IAAK,IAAIhZ,EAAI,EAAGA,EAAImZ,EAASF,OAAQjZ,IACnCmZ,EAASnZ,GAAGuX,UAAUC,OAAO,QAE/B,MAAM4B,EAAchC,SAAS4B,uBAAuB,eACpD,IAAK,IAAIhZ,EAAI,EAAGA,EAAIoZ,EAAYH,OAAQjZ,IACtCoZ,EAAYpZ,GAAGuX,UAAUC,OAAO,OAEpC,CCpqBA,oBAAwB,UAAW,MACnC,oBAAwB,QAAS,MAGjC,oBAA8B,UAAW,KACzC,oBAA8B,SAAU,KACxC,oBAAsB,KAKtB6B,EAAA,aAAsB,EACtBA,EAAA,aAAsB,aACtBA,EAAA,gBAAwB,EAExB,MAAMC,IAAW,QAAmB,CAClCxO,MAAO,IACPE,OAAQ,IACRuO,WAAW,EACXC,gBAAiB,EACjBC,gBAAiB,EAMjBC,aAAa,IAGT/E,GAAQ,IAAI,KACZ,GAAS,IAAI,KACbgF,GAAS,IAAI,KAEnBL,GAAS1E,KAAKgF,aAAa,KAAM,eACjCxC,SAASC,eAAe,yBAAyBwC,YAAYP,GAAS1E,MACtE0E,GAASQ,OAAOnF,IAEhBgF,GAAOlC,IAAI,kBACX,IAAK,MAAMjM,KAAQ,WACjBmO,GAAOlC,IAAI,WAAmBjM,IAwDhC,SAASuO,KACP,MAAMlD,EAAa,IAAInC,EAAkBC,GAAOgF,GAAOpQ,YDnFlD,SAAiBsN,EAAYmD,GAKlC,MAAMC,EAAgBhD,IAEpB,OADAD,EAAsBC,GACdA,EAAQC,SACd,IAAK,QACHE,SAASC,eAAe,eAAeE,UAAUC,OAAO,gBACxD,MACF,IAAK,OACHJ,SAASC,eAAe,eAAeE,UAAUE,IAAI,gBAGzD,OAAQR,EAAQ/D,KACd,IAAK,KACH2D,EAAW5B,MAAMtB,eAAc,GAC/B,MACF,IAAK,MACHkD,EAAW5B,MAAMtB,eAAc,GAGnC,OAAQsD,EAAQW,KACd,IAAK,SACHf,EAAW5B,MAAMpB,eAAc,GAC/BgD,EAAWX,eAAgB,EAC3B,MACF,IAAK,OACHW,EAAW5B,MAAMpB,eAAc,GAC/BgD,EAAWX,eAAgB,EAC3B,MACF,IAAK,MACHW,EAAW5B,MAAMpB,eAAc,GAGnC,OAAQoD,EAAQe,OACd,IAAK,OACHnB,EAAW1B,UAAY,GACvB6E,EAAOE,OAASrD,EAAW1B,UAC3B,MACF,IAAK,SACH0B,EAAW1B,UAAY,GACvB6E,EAAOE,OAASrD,EAAW1B,UAC3B,MACF,IAAK,OACH0B,EAAW1B,UAAY,GACvB6E,EAAOE,OAASrD,EAAW1B,UAG/B,OAAQ8B,EAAQzB,cACd,IAAK,IACHqB,EAAWrB,aAAe,EAC1B,MACF,IAAK,KACHqB,EAAWrB,aAAe,GAC1B,MACF,IAAK,KACHqB,EAAWrB,aAAe,GAE9B,EAgDFyE,EAlB0B,CACxB/C,QAAS,QAAwB,sBACjChE,IAAK,QAAwB,kBAC7B0E,IAAK,QAAwB,kBAC7BI,MAAO,QAAwB,oBAC/BxC,aAAc,QAAwB,6BAkD1C,SAAmBqB,EAAYsD,GAC7B,MAAMC,EAAkBhD,SAASC,eAAe,qBAC1CgD,EAAqBjD,SAASC,eAAe,wBAC7CiD,EAAWlD,SAASC,eAAe,aAEzC+C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,EAEpB,MAAMC,EAAWpD,SAASC,eAAe,aACzCmD,EAAS1H,iBAAiB,SAAS,KAC7B0H,EAASjD,UAAUkD,SAAS,aAC9BD,EAASjD,UAAUC,OAAO,YAC1Bd,EAAmBK,OAAOF,EA1MpB,KA4MN2D,EAASjD,UAAUE,IAAI,YACvBf,EAAmBE,MAAMC,EA7MnB,GA8MR,IAGiBO,SAASC,eAAe,eAChCvE,iBAAiB,SAAS,KAC/B0H,EAASjD,UAAUkD,SAAS,cAC9BD,EAASjD,UAAUC,OAAO,YAC1Bd,EAAmBK,OAAOF,EArNpB,IAuNRA,EAAWL,SAAS,IAGtB,MAAMW,EAAkBC,SAASC,eAAe,qBAC1CC,EAAiBF,SAASC,eAAe,oBAC/CF,EAAgBrE,iBAAiB,SAAS,KACxCqH,EAAoB,CAAEjD,QAAS,SAAU,IAE3CI,EAAexE,iBAAiB,SAAS,KACvCqH,EAAoB,CAAEjD,QAAS,QAAS,IAG1C,MAAMQ,EAAWN,SAASC,eAAe,cACnCM,EAAYP,SAASC,eAAe,eAC1CK,EAAS5E,iBAAiB,SAAS,KACjCqH,EAAoB,CAAEjH,IAAK,MAAO,IAEpCyE,EAAU7E,iBAAiB,SAAS,KAClCqH,EAAoB,CAAEjH,IAAK,OAAQ,IAGrC,MAAM2E,EAAYT,SAASC,eAAe,cACpCS,EAAUV,SAASC,eAAe,YAClCU,EAAYX,SAASC,eAAe,eAC1CQ,EAAU/E,iBAAiB,SAAS,KAClCqH,EAAoB,CAAEvC,IAAK,UAAW,IAExCE,EAAQhF,iBAAiB,SAAS,KAChCqH,EAAoB,CAAEvC,IAAK,QAAS,IAEtCG,EAAUjF,iBAAiB,SAAS,KAClCqH,EAAoB,CAAEvC,IAAK,OAAQ,IAOrC,MAAMK,EAAeb,SAASC,eAAe,kBACvCa,EAAiBd,SAASC,eAAe,oBACzCc,EAAef,SAASC,eAAe,kBAC7CY,EAAanF,iBAAiB,SAAS,KACrCqH,EAAoB,CAAEnC,MAAO,QAAS,IAExCE,EAAepF,iBAAiB,SAAS,KACvCqH,EAAoB,CAAEnC,MAAO,UAAW,IAE1CG,EAAarF,iBAAiB,SAAS,KACrCqH,EAAoB,CAAEnC,MAAO,QAAS,IAGxC,MAAMI,EAAmBhB,SAASC,eAAe,uBAC3CgB,EAAoBjB,SAASC,eAAe,wBAC5CiB,EAAoBlB,SAASC,eAAe,wBAC5CqD,EAAatD,SAASC,eAAe,gBACrCsD,EAAevD,SAASC,eAAe,mBACvCuD,EAA2BxD,SAASC,eACxC,iCAEF,SAASwD,EAA6BrF,GAKpC,QAHEqB,EAAWrR,QAAUqR,EAAWR,OAChCQ,EAAWrR,QAAUqR,EAAWhB,iBAChCgB,EAAWrR,QAAUqR,EAAWf,0BAG/Be,EAAW1H,OAAO,IAAMqG,GACvBqB,EAAW1H,OAAO,IAAMqG,GAK9B,CACA,MAAMsF,EAAa1D,SAASC,eAAe,gBACrC0D,EAAe3D,SAASC,eAAe,mBAC7Ce,EAAiBtF,iBAAiB,SAAS,KACzC,IAAIsF,EAAiBb,UAAUkD,SAAS,YAGxC,OAAkC,IAA9B5D,EAAWJ,gBACbqE,EAAWvD,UAAUC,OAAO,UAE5B4C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,OACpB7D,EAAmBE,MAAMC,EA7SjB,IAgTNgE,EAA6B,IAC/BD,EAAyBI,YAAc,IACvCN,EAAWnD,UAAUC,OAAO,UAE5B4C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,OACpB7D,EAAmBE,MAAMC,EAzTjB,SA4TVsD,EAAoB,CAAE3E,aAAc,KAAM,IAE5C6C,EAAkBvF,iBAAiB,SAAS,KAC1C,IAAIuF,EAAkBd,UAAUkD,SAAS,YAGzC,OAAkC,IAA9B5D,EAAWJ,gBACbqE,EAAWvD,UAAUC,OAAO,UAE5B4C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,OACpB7D,EAAmBE,MAAMC,EA1UjB,IA6UNgE,EAA6B,KAC/BD,EAAyBI,YAAc,KACvCN,EAAWnD,UAAUC,OAAO,UAE5B4C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,OACpB7D,EAAmBE,MAAMC,EAtVjB,SAyVVsD,EAAoB,CAAE3E,aAAc,MAAO,IAE7C8C,EAAkBxF,iBAAiB,SAAS,KAC1C,IAAIwF,EAAkBf,UAAUkD,SAAS,YAGzC,OAAkC,IAA9B5D,EAAWJ,gBACbqE,EAAWvD,UAAUC,OAAO,UAE5B4C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,OACpB7D,EAAmBE,MAAMC,EAvWjB,IA0WNgE,EAA6B,KAC/BD,EAAyBI,YAAc,KACvCN,EAAWnD,UAAUC,OAAO,UAE5B4C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,OACpB7D,EAAmBE,MAAMC,EAnXjB,SAsXVsD,EAAoB,CAAE3E,aAAc,MAAO,IAE7CmF,EAAa7H,iBAAiB,SAAS,KAChC4H,EAAWnD,UAAUkD,SAAS,YACjCC,EAAWnD,UAAUE,IAAI,UAEzB2C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,EACpB7D,EAAmBK,OAAOF,EAjYlB,GAkYV,IAEFkE,EAAajI,iBAAiB,SAAS,KAChCgI,EAAWvD,UAAUkD,SAAS,YACjCK,EAAWvD,UAAUE,IAAI,UAEzB2C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAE9BD,EAASC,UAAW,EACpB7D,EAAmBK,OAAOF,EA7YlB,GA8YV,IAGF,MAAMoE,EAAoB7D,SAASC,eAAe,wBAC5C6D,EAAqB9D,SAASC,eAAe,yBACnD4D,EAAkBnI,iBAAiB,SAAS,KAC1CoI,EAAmB3D,UAAUC,OAAO,YACpCyD,EAAkB1D,UAAUE,IAAI,YAChCZ,EAAWJ,gBAAiB,CAAI,IAElCyE,EAAmBpI,iBAAiB,SAAS,KAC3CmI,EAAkB1D,UAAUC,OAAO,YACnC0D,EAAmB3D,UAAUE,IAAI,YACjCZ,EAAWJ,gBAAiB,CAAK,IAGnC,MAAM0E,EAAW/D,SAASC,eAAe,aACnC+D,EAAgBhE,SAASC,eAAe,mBAC9CiD,EAASxH,iBAAiB,SAAS,KAC7BqI,EAAS5D,UAAUkD,SAAS,WAC9BU,EAAS5D,UAAUC,OAAO,UAE1B4C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAC9B7D,EAAmBE,MAAMC,EAvajB,KAyaRsE,EAAS5D,UAAUE,IAAI,UAEvB2C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAC9B7D,EAAmBK,OAAOF,EA9alB,GA+aV,IAEFuE,EAActI,iBAAiB,SAAS,KACjCqI,EAAS5D,UAAUkD,SAAS,YAC/BU,EAAS5D,UAAUE,IAAI,UAEvB2C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAC9B7D,EAAmBK,OAAOF,EAxblB,GAybV,IAGwBO,SAASC,eAAe,wBAChCvE,iBAAiB,SAAS,KAE1CoI,EAAmBG,QAUnBlB,EAPuB,CACrBjD,QAAS,QACThE,IAAK,KACL0E,IAAK,SACLI,MAAO,SACPxC,aAAc,MAEmB,GAEvC,CApTE8F,CAAUzE,GARmBI,IAC3BgD,EAAahD,GApCK,CAACA,IACnBD,EAAsBC,GAClBA,EAAQC,SACV,QAAwB,qBAAsBD,EAAQC,SAEpDD,EAAQ/D,KACV,QAAwB,iBAAkB+D,EAAQ/D,KAEhD+D,EAAQW,KACV,QAAwB,iBAAkBX,EAAQW,KAEhDX,EAAQe,OACV,QAAwB,mBAAoBf,EAAQe,OAElDf,EAAQzB,cACV,QAAwB,0BAA2ByB,EAAQzB,aAC7D,EAqBA+F,CAAYtE,EAAQ,IAqaxB,SAAyCJ,GAEvChE,OAAOC,iBAAiB,SAAUJ,IAE3BA,EAAM8I,OAAOC,QAAQ,iCACxBhD,KACAC,EAAoB,IACpBhC,EAAmBK,OAAOF,EA5jBpB,GA6jBR,IAIFO,SAASC,eAAe,qBAAqBvE,iBAAiB,SAAS,KACrEyF,EAAe,gBAAiB1B,EAAW,IAE7CO,SACGC,eAAe,wBACfvE,iBAAiB,SAAS,KACzByF,EAAe,mBAAoB1B,EAAW,IAIlDO,SACGC,eAAe,uBACfvE,iBAAiB,aAAa,KAC7B8F,EAAY,sBAAuB,kBAAkB,IAEzDxB,SACGC,eAAe,mBACfvE,iBAAiB,aAAa,KAC7B8F,EAAY,kBAAmB,cAAc,IAEjDxB,SACGC,eAAe,mBACfvE,iBAAiB,aAAa,KAC7B8F,EAAY,kBAAmB,cAAc,IAEjDxB,SACGC,eAAe,qBACfvE,iBAAiB,aAAa,KAC7B8F,EAAY,oBAAqB,gBAAgB,IAErDxB,SACGC,eAAe,6BACfvE,iBAAiB,aAAa,KAC7B8F,EAAY,4BAA6B,wBAAwB,IAErExB,SACGC,eAAe,6BACfvE,iBAAiB,aAAa,KAC7B8F,EAAY,4BAA6B,wBAAwB,IAErExB,SACGC,eAAe,wBACfvE,iBAAiB,aAAa,KAC7B2F,IAAc,IAKlBrB,SAASC,eAAe,mBAAmBvE,iBAAiB,SAAS,KACnE8F,EAAY,kBAAmB,cAAc,IAE/CxB,SAASC,eAAe,mBAAmBvE,iBAAiB,SAAS,KACnE8F,EAAY,kBAAmB,cAAc,IAE/CxB,SAASC,eAAe,qBAAqBvE,iBAAiB,SAAS,KACrE8F,EAAY,oBAAqB,gBAAgB,IAEnDxB,SACGC,eAAe,6BACfvE,iBAAiB,SAAS,KACzB8F,EAAY,4BAA6B,wBAAwB,IAErExB,SACGC,eAAe,6BACfvE,iBAAiB,SAAS,KACzB8F,EAAY,4BAA6B,wBAAwB,IAErExB,SACGC,eAAe,wBACfvE,iBAAiB,SAAS,KACzB2F,IAAc,GAEpB,CAlfEiD,CAAgC7E,GAGhChE,OAAOC,iBAAiB,WAAYJ,IAClC,GAAmB,WAAfA,EAAMC,KAAmB,CAC3B,MAAMgJ,EAAUvE,SAASC,eAAe,YACpCsE,EAAQpE,UAAUkD,SAAS,UAC7BkB,EAAQpE,UAAUC,OAAO,UAEzBmE,EAAQpE,UAAUE,IAAI,UAExB/E,EAAME,gBACR,KAA0B,UAAfF,EAAMC,MACEyE,SAASC,eAAe,aAC5BE,UAAUkD,SAAS,WAC9B/H,EAAME,gBAEV,IAGFwE,SAAStE,iBAAiB,oBAAoB,WACX,YAA7BsE,SAASwE,gBACX/E,EAAW5B,MAAMlB,YAEjB8C,EAAW5B,MAAMnB,SAErB,GACF,ECtDE+H,CAAQhF,EAAY,IAQtB,SAAeA,GACb,GAAOqD,OAASrD,EAAW1B,UAC3B,GAAOsC,KAAI,KACTZ,EAAWT,WACXkD,GAASQ,OAAOnF,GAAM,IAExB,GAAOmH,OACT,CAdEA,CAAMjF,EACR,EApDA,WACE,MAAMkF,EAAa3E,SAASC,eAAe,eACrC2E,EAAc5E,SAASC,eAAe,gBAC5CsC,GAAOsC,WAAWxE,KAAI,KACpBuE,EAAYE,MAAMpR,MAAQ,GAAG6O,GAAOwC,WAAW,IAEjDxC,GAAOyC,WAAW3E,KAAI,KACpBsE,EAAWxE,UAAUE,IAAI,SAAS,IAGpC,MAAM0D,EAAW/D,SAASC,eAAe,aACnCiD,EAAWlD,SAASC,eAAe,aACnC+D,EAAgBhE,SAASC,eAAe,mBACxC+C,EAAkBhD,SAASC,eAAe,qBAC1CgD,EAAqBjD,SAASC,eAAe,wBAEnD+C,EAAgBG,UAAW,EAE3BF,EAAmBE,UAAW,EAC9B,MAAM8B,EAAgB,KACflB,EAAS5D,UAAUkD,SAAS,YAC/BU,EAAS5D,UAAUE,IAAI,UAEvB6C,EAASC,UAAW,GAEtBD,EAAStB,uBAAuB,aAAa,GAAGzB,UAAUE,IAAI,UAC9D6C,EAAStB,uBAAuB,cAAc,GAAGzB,UAAUC,OAAO,UAClE8C,EAAS/C,UAAUC,OAAO,QAC1B4D,EACGpC,uBAAuB,aAAa,GACpCzB,UAAUE,IAAI,UACjB2D,EACGpC,uBAAuB,cAAc,GACrCzB,UAAUC,OAAO,UACpB4D,EAAc7D,UAAUC,OAAO,QAE/BmC,GAAO2C,KAAKvC,IACZgC,EAAWxE,UAAUC,OAAO,UAC5B8C,EAASvH,oBAAoB,QAASsJ,GACtCjB,EAAcrI,oBAAoB,QAASsJ,EAAc,EAE3D/B,EAASxH,iBAAiB,QAASuJ,GACnCjB,EAActI,iBAAiB,QAASuJ,EAC1C,CAhDAE,E,iCC1FO,MAAMC,EAAsB,CAMjCC,IAAMC,IACJ,IAAIvK,EAAQ,KACZ,IACEA,EAAQwK,aAAaC,QAAQF,EAG/B,CAFE,MAAOG,GACPC,QAAQC,MAAMF,EAChB,CACA,OAAO1K,CAAK,EAQd6K,IAAK,CAACN,EAAKvK,KACT,IACEwK,aAAaM,QAAQP,EAAKvK,EAG5B,CAFE,MAAO0K,GACPC,QAAQC,MAAMF,EAChB,G","sources":["webpack://pikachu-volleyball/./src/resources/js/assets_path.js","webpack://pikachu-volleyball/./src/resources/js/rand.js","webpack://pikachu-volleyball/./src/resources/js/physics.js","webpack://pikachu-volleyball/./src/resources/js/cloud_and_wave.js","webpack://pikachu-volleyball/./src/resources/js/view.js","webpack://pikachu-volleyball/./src/resources/js/keyboard.js","webpack://pikachu-volleyball/./src/resources/js/audio.js","webpack://pikachu-volleyball/./src/resources/js/pikavolley.js","webpack://pikachu-volleyball/./src/resources/js/ui.js","webpack://pikachu-volleyball/./src/resources/js/main.js","webpack://pikachu-volleyball/./src/resources/js/utils/local_storage_wrapper.js"],"sourcesContent":["/**\n * Manages the paths (file locations) of the game assets.\n */\n'use strict';\n\nexport const ASSETS_PATH = {\n SPRITE_SHEET: '../resources/assets/images/sprite_sheet.json',\n TEXTURES: {},\n SOUNDS: {},\n};\n\nconst TEXTURES = ASSETS_PATH.TEXTURES;\nTEXTURES.PIKACHU = (i, j) => `pikachu/pikachu_${i}_${j}.png`;\nTEXTURES.BALL = (s) => `ball/ball_${s}.png`;\nTEXTURES.NUMBER = (n) => `number/number_${n}.png`;\n\nTEXTURES.SKY_BLUE = 'objects/sky_blue.png';\nTEXTURES.MOUNTAIN = 'objects/mountain.png';\nTEXTURES.GROUND_RED = 'objects/ground_red.png';\nTEXTURES.GROUND_LINE = 'objects/ground_line.png';\nTEXTURES.GROUND_LINE_LEFT_MOST = 'objects/ground_line_leftmost.png';\nTEXTURES.GROUND_LINE_RIGHT_MOST = 'objects/ground_line_rightmost.png';\nTEXTURES.GROUND_YELLOW = 'objects/ground_yellow.png';\nTEXTURES.NET_PILLAR_TOP = 'objects/net_pillar_top.png';\nTEXTURES.NET_PILLAR = 'objects/net_pillar.png';\nTEXTURES.SHADOW = 'objects/shadow.png';\nTEXTURES.BALL_HYPER = 'ball/ball_hyper.png';\nTEXTURES.BALL_TRAIL = 'ball/ball_trail.png';\nTEXTURES.BALL_PUNCH = 'ball/ball_punch.png';\nTEXTURES.CLOUD = 'objects/cloud.png';\nTEXTURES.WAVE = 'objects/wave.png';\nTEXTURES.BLACK = 'objects/black.png';\n\nTEXTURES.SACHISOFT = 'messages/common/sachisoft.png';\nTEXTURES.READY = 'messages/common/ready.png';\nTEXTURES.GAME_END = 'messages/common/game_end.png';\n\nTEXTURES.MARK = 'messages/ja/mark.png';\nTEXTURES.POKEMON = 'messages/ja/pokemon.png';\nTEXTURES.PIKACHU_VOLLEYBALL = 'messages/ja/pikachu_volleyball.png';\nTEXTURES.FIGHT = 'messages/ja/fight.png';\nTEXTURES.WITH_COMPUTER = 'messages/ja/with_computer.png';\nTEXTURES.WITH_FRIEND = 'messages/ja/with_friend.png';\nTEXTURES.GAME_START = 'messages/ja/game_start.png';\n\nTEXTURES.SITTING_PIKACHU = 'sitting_pikachu.png';\n\nconst SOUNDS = ASSETS_PATH.SOUNDS;\nSOUNDS.BGM = '../resources/assets/sounds/bgm.mp3';\nSOUNDS.PIPIKACHU = '../resources/assets/sounds/WAVE140_1.wav';\nSOUNDS.PIKA = '../resources/assets/sounds/WAVE141_1.wav';\nSOUNDS.CHU = '../resources/assets/sounds/WAVE142_1.wav';\nSOUNDS.PI = '../resources/assets/sounds/WAVE143_1.wav';\nSOUNDS.PIKACHU = '../resources/assets/sounds/WAVE144_1.wav';\nSOUNDS.POWERHIT = '../resources/assets/sounds/WAVE145_1.wav';\nSOUNDS.BALLTOUCHESGROUND = '../resources/assets/sounds/WAVE146_1.wav';\n","/**\n * This module contains random number generator used for the game\n */\n'use strict';\n/** @typedef {function():number} RNG */\n\n/** @type {RNG} custom RNG (random number generator) function which generates a random number in [0, 1] */\nlet customRng = null;\n\n/**\n * Return random integer in [0, 32767]\n *\n * The machine code of the original game use \"_rand()\" function in Visual Studio 1988 Library.\n * I could't find out how this function works exactly.\n * But, anyhow, it should be a function that generate a random number.\n * I decided to use custom rand function which generates random integer in [0, 32767]\n * which follows rand() function in Visual Studio 2017 Library.\n *\n * By default, it uses the function \"Math.random\" for generating a random number.\n * A custom RNG function can used by setting the \"customRng\" as the custom RNG function.\n *\n * @return {number} random integer\n */\nexport function rand() {\n if (customRng === null) {\n return Math.floor(32768 * Math.random());\n }\n return Math.floor(32768 * customRng());\n}\n\n/**\n * Set custom RNG function\n * @param {RNG} rng\n */\nexport function setCustomRng(rng) {\n customRng = rng;\n}\n","/**\n * The Model part in the MVC pattern\n *\n * It is the core module which acts as a physics engine.\n * This physics engine calculates the movements of the ball and the players (Pikachus).\n *\n * It was gained by reverse engineering the original game.\n * The address of each function in the original machine code is specified at the comment above each function.\n * ex) FUN_00403dd0 means the original function at the address 00403dd0.\n *\n *\n * ** Some useful infos below **\n *\n * Ground width: 432 = 0x1B0\n * Ground height: 304 = 0x130\n *\n * X position coordinate: [0, 432], right-direction increasing\n * Y position coordinate: [0, 304], down-direction increasing\n *\n * Ball radius: 20 = 0x14\n * Ball diameter: 40 = 0x28\n *\n * Player half-width: 32 = 0x20\n * Player half-height: 32 = 0x20\n * Player width: 64 = 0x40\n * Player height: 64 = 0x40\n *\n */\n'use strict';\nimport { rand } from './rand.js';\n\n/** @constant @type {number} ground width */\nconst GROUND_WIDTH = 432;\n/** @constant @type {number} ground half-width, it is also the net pillar x coordinate */\nexport const GROUND_HALF_WIDTH = (GROUND_WIDTH / 2) | 0; // integer division\n/** @constant @type {number} player (Pikachu) length: width = height = 64 */\nconst PLAYER_LENGTH = 64;\n/** @constant @type {number} player half length */\nconst PLAYER_HALF_LENGTH = (PLAYER_LENGTH / 2) | 0; // integer division\n/** @constant @type {number} player's y coordinate when they are touching ground */\nconst PLAYER_TOUCHING_GROUND_Y_COORD = 244;\n/** @constant @type {number} ball's radius */\nconst BALL_RADIUS = 20;\n/** @constant @type {number} ball's y coordinate when it is touching ground */\nconst BALL_TOUCHING_GROUND_Y_COORD = 252;\n/** @constant @type {number} net pillar's half width (this value is on this physics engine only, not on the sprite pixel size) */\nconst NET_PILLAR_HALF_WIDTH = 25;\n/** @constant @type {number} net pillar top's top side y coordinate */\nconst NET_PILLAR_TOP_TOP_Y_COORD = 176;\n/** @constant @type {number} net pillar top's bottom side y coordinate (this value is on this physics engine only) */\nconst NET_PILLAR_TOP_BOTTOM_Y_COORD = 192;\n\n/**\n * It's for to limit the looping number of the infinite loops.\n * This constant is not in the original machine code. (The original machine code does not limit the looping number.)\n *\n * In the original ball x coord range setting (ball x coord in [20, 432]), the infinite loops in\n * {@link calculateExpectedLandingPointXFor} function and {@link expectedLandingPointXWhenPowerHit} function seems to be always terminated soon.\n * But if the ball x coord range is edited, for example, to [20, 432 - 20] for left-right symmetry,\n * it is observed that the infinite loop in {@link expectedLandingPointXWhenPowerHit} does not terminate.\n * So for safety, this infinite loop limit is included for the infinite loops mentioned above.\n * @constant @type {number}\n */\nconst INFINITE_LOOP_LIMIT = 1000;\n\n/**\n * Class representing a pack of physical objects i.e. players and ball\n * whose physical values are calculated and set by {@link physicsEngine} function\n */\nexport class PikaPhysics {\n /**\n * Create a physics pack\n * @param {boolean} isPlayer1Computer Is player on the left (player 1) controlled by computer?\n * @param {boolean} isPlayer2Computer Is player on the right (player 2) controlled by computer?\n */\n constructor(isPlayer1Computer, isPlayer2Computer) {\n this.player1 = new Player(false, isPlayer1Computer);\n this.player2 = new Player(true, isPlayer2Computer);\n this.ball = new Ball(false);\n }\n\n /**\n * run {@link physicsEngine} function with this physics object and user input\n *\n * @param {PikaUserInput[]} userInputArray userInputArray[0]: PikaUserInput object for player 1, userInputArray[1]: PikaUserInput object for player 2\n * @return {boolean} Is ball touching ground?\n */\n runEngineForNextFrame(userInputArray) {\n const isBallTouchingGround = physicsEngine(\n this.player1,\n this.player2,\n this.ball,\n userInputArray\n );\n return isBallTouchingGround;\n }\n}\n\n/**\n * Class (or precisely, Interface) representing user input (from keyboard or joystick, whatever)\n */\nexport class PikaUserInput {\n constructor() {\n /** @type {number} 0: no horizontal-direction input, -1: left-direction input, 1: right-direction input */\n this.xDirection = 0;\n /** @type {number} 0: no vertical-direction input, -1: up-direction input, 1: down-direction input */\n this.yDirection = 0;\n /** @type {number} 0: auto-repeated or no power hit input, 1: not auto-repeated power hit input */\n this.powerHit = 0;\n }\n}\n\n/**\n * Class representing a player\n *\n * Player 1 property address: 00411F28 -> +28 -> +10 -> +C -> ...\n * Player 2 property address: 00411F28 -> +28 -> +10 -> +10 -> ...\n * The \"...\" part is written on the line comment at the right side of each property.\n * e.g. address to player1.isPlayer: 00411F28 -> +28 -> +10 -> +C -> +A0\n * e.g. address to player2.isComputer: 00411F28 -> +28 -> +10 -> +10 -> +A4\n *\n * For initial values: refer to FUN_000403a90 && FUN_00401f40\n */\nclass Player {\n /**\n * create a player\n * @param {boolean} isPlayer2 Is this player on the right side?\n * @param {boolean} isComputer Is this player controlled by computer?\n */\n constructor(isPlayer2, isComputer) {\n /** @type {boolean} Is this player on the right side? */\n this.isPlayer2 = isPlayer2; // 0xA0\n /** @type {boolean} Is controlled by computer? */\n this.isComputer = isComputer; // 0xA4\n this.initializeForNewRound();\n\n /** @type {number} -1: left, 0: no diving, 1: right */\n this.divingDirection = 0; // 0xB4\n /** @type {number} */\n this.lyingDownDurationLeft = -1; // 0xB8\n /** @type {boolean} */\n this.isWinner = false; // 0xD0\n /** @type {boolean} */\n this.gameEnded = false; // 0xD4\n\n /**\n * It flips randomly to 0 or 1 by the {@link letComputerDecideUserInput} function (FUN_00402360)\n * when ball is hanging around on the other player's side.\n * If it is 0, computer player stands by around the middle point of their side.\n * If it is 1, computer player stands by adjacent to the net.\n * @type {number} 0 or 1\n */\n this.computerWhereToStandBy = 0; // 0xDC\n\n /**\n * This property is not in the player pointers of the original source code.\n * But for sound effect (especially for stereo sound),\n * it is convenient way to give sound property to a Player.\n * The original name is stereo sound.\n * @type {Object.}\n */\n this.sound = {\n pipikachu: false,\n pika: false,\n chu: false,\n };\n }\n\n /**\n * initialize for new round\n */\n initializeForNewRound() {\n /** @type {number} x coord */\n this.x = 36; // 0xA8 // initialized to 36 (player1) or 396 (player2)\n if (this.isPlayer2) {\n this.x = GROUND_WIDTH - 36;\n }\n /** @type {number} y coord */\n this.y = PLAYER_TOUCHING_GROUND_Y_COORD; // 0xAC // initialized to 244\n /** @type {number} y direction velocity */\n this.yVelocity = 0; // 0xB0 // initialized to 0\n /** @type {boolean} */\n this.isCollisionWithBallHappened = false; // 0xBC // initialized to 0 i.e false\n\n /**\n * Player's state\n * 0: normal, 1: jumping, 2: jumping_and_power_hitting, 3: diving\n * 4: lying_down_after_diving\n * 5: win!, 6: lost..\n * @type {number} 0, 1, 2, 3, 4, 5 or 6\n */\n this.state = 0; // 0xC0 // initialized to 0\n /** @type {number} */\n this.frameNumber = 0; // 0xC4 // initialized to 0\n /** @type {number} */\n this.normalStatusArmSwingDirection = 1; // 0xC8 // initialized to 1\n /** @type {number} */\n this.delayBeforeNextFrame = 0; // 0xCC // initialized to 0\n\n /**\n * This value is initialized to (_rand() % 5) before the start of every round.\n * The greater the number, the bolder the computer player.\n *\n * If computer has higher boldness,\n * judges more the ball is hanging around the other player's side,\n * has greater distance to the expected landing point of the ball,\n * jumps more,\n * and dives less.\n * See the source code of the {@link letComputerDecideUserInput} function (FUN_00402360).\n *\n * @type {number} 0, 1, 2, 3 or 4\n */\n this.computerBoldness = rand() % 5; // 0xD8 // initialized to (_rand() % 5)\n }\n}\n\n/**\n * Class representing a ball\n *\n * Ball property address: 00411F28 -> +28 -> +10 -> +14 -> ...\n * The \"...\" part is written on the line comment at the right side of each property.\n * e.g. address to ball.fineRotation: 00411F28 -> +28 -> +10 -> +14 -> +48\n *\n * For initial Values: refer to FUN_000403a90 && FUN_00402d60\n */\nclass Ball {\n /**\n * Create a ball\n * @param {boolean} isPlayer2Serve Will player 2 serve on this new round?\n */\n constructor(isPlayer2Serve) {\n this.initializeForNewRound(isPlayer2Serve);\n /** @type {number} x coord of expected lang point */\n this.expectedLandingPointX = 0; // 0x40\n /**\n * ball rotation frame number selector\n * During the period where it continues to be 5, hyper ball glitch occur.\n * @type {number} 0, 1, 2, 3, 4 or 5\n * */\n this.rotation = 0; // 0x44\n /** @type {number} */\n this.fineRotation = 0; // 0x48\n /** @type {number} x coord for punch effect */\n this.punchEffectX = 0; // 0x50\n /** @type {number} y coord for punch effect */\n this.punchEffectY = 0; // 0x54\n\n /**\n * Following previous values are for trailing effect for power hit\n * @type {number}\n */\n this.previousX = 0; // 0x58\n this.previousPreviousX = 0; // 0x5c\n this.previousY = 0; // 0x60\n this.previousPreviousY = 0; // 0x64\n\n /**\n * this property is not in the ball pointer of the original source code.\n * But for sound effect (especially for stereo sound),\n * it is convenient way to give sound property to a Ball.\n * The original name is stereo sound.\n */\n this.sound = {\n powerHit: false,\n ballTouchesGround: false,\n };\n }\n\n /**\n * Initialize for new round\n * @param {boolean} isPlayer2Serve will player on the right side serve on this new round?\n */\n initializeForNewRound(isPlayer2Serve) {\n /** @type {number} x coord */\n this.x = 56; // 0x30 // initialized to 56 or 376\n if (isPlayer2Serve === true) {\n this.x = GROUND_WIDTH - 56;\n }\n /** @type {number} y coord */\n this.y = 0; // 0x34 // initialized to 0\n /** @type {number} x direction velocity */\n this.xVelocity = 0; // 0x38 // initialized to 0\n /** @type {number} y direction velocity */\n this.yVelocity = 1; // 0x3C // initialized to 1\n /** @type {number} punch effect radius */\n this.punchEffectRadius = 0; // 0x4c // initialized to 0\n /** @type {boolean} is power hit */\n this.isPowerHit = false; // 0x68 // initialized to 0 i.e. false\n }\n}\n\n/**\n * FUN_00403dd0\n * This is the Pikachu Volleyball physics engine!\n * This physics engine calculates and set the physics values for the next frame.\n *\n * @param {Player} player1 player on the left side\n * @param {Player} player2 player on the right side\n * @param {Ball} ball ball\n * @param {PikaUserInput[]} userInputArray userInputArray[0]: user input for player 1, userInputArray[1]: user input for player 2\n * @return {boolean} Is ball touching ground?\n */\nfunction physicsEngine(player1, player2, ball, userInputArray) {\n const isBallTouchingGround =\n processCollisionBetweenBallAndWorldAndSetBallPosition(ball);\n\n let player;\n let theOtherPlayer;\n for (let i = 0; i < 2; i++) {\n if (i === 0) {\n player = player1;\n theOtherPlayer = player2;\n } else {\n player = player2;\n theOtherPlayer = player1;\n }\n\n // FUN_00402d90 omitted\n // FUN_00402810 omitted\n // this javascript code is refactored not to need above two function except for\n // a part of FUN_00402d90:\n // FUN_00402d90 include FUN_004031b0(calculateExpectedLandingPointXFor)\n calculateExpectedLandingPointXFor(ball); // calculate expected_X;\n\n processPlayerMovementAndSetPlayerPosition(\n player,\n userInputArray[i],\n theOtherPlayer,\n ball\n );\n\n // FUN_00402830 omitted\n // FUN_00406020 omitted\n // These two functions omitted above maybe participate in graphic drawing for a player\n }\n\n for (let i = 0; i < 2; i++) {\n if (i === 0) {\n player = player1;\n } else {\n player = player2;\n }\n\n // FUN_00402810 omitted: this javascript code is refactored not to need this function\n\n const isHappened = isCollisionBetweenBallAndPlayerHappened(\n ball,\n player.x,\n player.y\n );\n if (isHappened === true) {\n if (player.isCollisionWithBallHappened === false) {\n processCollisionBetweenBallAndPlayer(\n ball,\n player.x,\n userInputArray[i],\n player.state\n );\n player.isCollisionWithBallHappened = true;\n }\n } else {\n player.isCollisionWithBallHappened = false;\n }\n }\n\n // FUN_00403040\n // FUN_00406020\n // These two functions omitted above maybe participate in graphic drawing for a player\n\n return isBallTouchingGround;\n}\n\n/**\n * FUN_00403070\n * Is collision between ball and player happened?\n * @param {Ball} ball\n * @param {Player[\"x\"]} playerX player.x\n * @param {Player[\"y\"]} playerY player.y\n * @return {boolean}\n */\nfunction isCollisionBetweenBallAndPlayerHappened(ball, playerX, playerY) {\n let diff = ball.x - playerX;\n if (Math.abs(diff) <= PLAYER_HALF_LENGTH) {\n diff = ball.y - playerY;\n if (Math.abs(diff) <= PLAYER_HALF_LENGTH) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * FUN_00402dc0\n * Process collision between ball and world and set ball position\n * @param {Ball} ball\n * @return {boolean} Is ball touching ground?\n */\nfunction processCollisionBetweenBallAndWorldAndSetBallPosition(ball) {\n // This is not part of this function in the original assembly code.\n // In the original assembly code, it is processed in other function (FUN_00402ee0)\n // But it is proper to process here.\n ball.previousPreviousX = ball.previousX;\n ball.previousPreviousY = ball.previousY;\n ball.previousX = ball.x;\n ball.previousY = ball.y;\n\n // \"(ball.xVelocity / 2) | 0\" is integer division by 2\n let futureFineRotation = ball.fineRotation + ((ball.xVelocity / 2) | 0);\n // If futureFineRotation === 50, it skips next if statement finely.\n // Then ball.fineRotation = 50, and then ball.rotation = 5 (which designates hyper ball sprite!).\n // In this way, hyper ball glitch occur!\n // If this happen at the end of round,\n // since ball.xVelocity is 0-initialized at each start of round,\n // hyper ball sprite is rendered continuously until a collision happens.\n if (futureFineRotation < 0) {\n futureFineRotation += 50;\n } else if (futureFineRotation > 50) {\n futureFineRotation += -50;\n }\n ball.fineRotation = futureFineRotation;\n ball.rotation = (ball.fineRotation / 10) | 0; // integer division\n\n const futureBallX = ball.x + ball.xVelocity;\n /*\n If the center of ball would get out of left world bound or right world bound, bounce back.\n \n In this if statement, when considering left-right symmetry,\n \"futureBallX > GROUND_WIDTH\" should be changed to \"futureBallX > (GROUND_WIDTH - BALL_RADIUS)\",\n or \"futureBallX < BALL_RADIUS\" should be changed to \"futureBallX < 0\".\n Maybe the former one is more proper when seeing Pikachu player's x-direction boundary.\n Is this a mistake of the author of the original game?\n Or, was it set to this value to resolve infinite loop problem? (See comments on the constant INFINITE_LOOP_LIMIT.)\n If apply (futureBallX > (GROUND_WIDTH - BALL_RADIUS)), and if the maximum number of loop is not limited,\n it is observed that infinite loop in the function expectedLandingPointXWhenPowerHit does not terminate.\n */\n if (futureBallX < BALL_RADIUS || futureBallX > GROUND_WIDTH) {\n ball.xVelocity = -ball.xVelocity;\n }\n\n let futureBallY = ball.y + ball.yVelocity;\n // if the center of ball would get out of upper world bound\n if (futureBallY < 0) {\n ball.yVelocity = 1;\n }\n\n // If ball touches net\n if (\n Math.abs(ball.x - GROUND_HALF_WIDTH) < NET_PILLAR_HALF_WIDTH &&\n ball.y > NET_PILLAR_TOP_TOP_Y_COORD\n ) {\n if (ball.y <= NET_PILLAR_TOP_BOTTOM_Y_COORD) {\n if (ball.yVelocity > 0) {\n ball.yVelocity = -ball.yVelocity;\n }\n } else {\n if (ball.x < GROUND_HALF_WIDTH) {\n ball.xVelocity = -Math.abs(ball.xVelocity);\n } else {\n ball.xVelocity = Math.abs(ball.xVelocity);\n }\n }\n }\n\n futureBallY = ball.y + ball.yVelocity;\n // if ball would touch ground\n if (futureBallY > BALL_TOUCHING_GROUND_Y_COORD) {\n // FUN_00408470 omitted\n // the function omitted above receives 100 * (ball.x - 216),\n // i.e. horizontal displacement from net maybe for stereo sound?\n // code function (ballpointer + 0x28 + 0x10)? omitted\n // the omitted two functions maybe do a part of sound playback role.\n ball.sound.ballTouchesGround = true;\n\n ball.yVelocity = -ball.yVelocity;\n ball.punchEffectX = ball.x;\n ball.y = BALL_TOUCHING_GROUND_Y_COORD;\n ball.punchEffectRadius = BALL_RADIUS;\n ball.punchEffectY = BALL_TOUCHING_GROUND_Y_COORD + BALL_RADIUS;\n return true;\n }\n ball.y = futureBallY;\n ball.x = ball.x + ball.xVelocity;\n ball.yVelocity += 1;\n\n return false;\n}\n\n/**\n * FUN_00401fc0\n * Process player movement according to user input and set player position\n * @param {Player} player\n * @param {PikaUserInput} userInput\n * @param {Player} theOtherPlayer\n * @param {Ball} ball\n */\nfunction processPlayerMovementAndSetPlayerPosition(\n player,\n userInput,\n theOtherPlayer,\n ball\n) {\n if (player.isComputer === true) {\n letComputerDecideUserInput(player, ball, theOtherPlayer, userInput);\n }\n\n // if player is lying down.. don't move\n if (player.state === 4) {\n player.lyingDownDurationLeft += -1;\n if (player.lyingDownDurationLeft < -1) {\n player.state = 0;\n }\n return;\n }\n\n // process x-direction movement\n let playerVelocityX = 0;\n if (player.state < 5) {\n if (player.state < 3) {\n playerVelocityX = userInput.xDirection * 6;\n } else {\n // player.state === 3 i.e. player is diving..\n playerVelocityX = player.divingDirection * 8;\n }\n }\n\n const futurePlayerX = player.x + playerVelocityX;\n player.x = futurePlayerX;\n\n // process player's x-direction world boundary\n if (player.isPlayer2 === false) {\n // if player is player1\n if (futurePlayerX < PLAYER_HALF_LENGTH) {\n player.x = PLAYER_HALF_LENGTH;\n } else if (futurePlayerX > GROUND_HALF_WIDTH - PLAYER_HALF_LENGTH) {\n player.x = GROUND_HALF_WIDTH - PLAYER_HALF_LENGTH;\n }\n } else {\n // if player is player2\n if (futurePlayerX < GROUND_HALF_WIDTH + PLAYER_HALF_LENGTH) {\n player.x = GROUND_HALF_WIDTH + PLAYER_HALF_LENGTH;\n } else if (futurePlayerX > GROUND_WIDTH - PLAYER_HALF_LENGTH) {\n player.x = GROUND_WIDTH - PLAYER_HALF_LENGTH;\n }\n }\n\n // jump\n if (\n player.state < 3 &&\n userInput.yDirection === -1 && // up-direction input\n player.y === PLAYER_TOUCHING_GROUND_Y_COORD // player is touching on the ground\n ) {\n player.yVelocity = -16;\n player.state = 1;\n player.frameNumber = 0;\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-sound code function (playerpointer + 0x90 + 0x10)? omitted\n player.sound.chu = true;\n }\n\n // gravity\n const futurePlayerY = player.y + player.yVelocity;\n player.y = futurePlayerY;\n if (futurePlayerY < PLAYER_TOUCHING_GROUND_Y_COORD) {\n player.yVelocity += 1;\n } else if (futurePlayerY > PLAYER_TOUCHING_GROUND_Y_COORD) {\n // if player is landing..\n player.yVelocity = 0;\n player.y = PLAYER_TOUCHING_GROUND_Y_COORD;\n player.frameNumber = 0;\n if (player.state === 3) {\n // if player is diving..\n player.state = 4;\n player.frameNumber = 0;\n player.lyingDownDurationLeft = 3;\n } else {\n player.state = 0;\n }\n }\n\n if (userInput.powerHit === 1) {\n if (player.state === 1) {\n // if player is jumping..\n // then player do power hit!\n player.delayBeforeNextFrame = 5;\n player.frameNumber = 0;\n player.state = 2;\n // maybe-sound function (playerpointer + 0x90 + 0x18)? omitted\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-sound function (playerpointer + 0x90 + 0x14)? omitted\n player.sound.pika = true;\n } else if (player.state === 0 && userInput.xDirection !== 0) {\n // then player do diving!\n player.state = 3;\n player.frameNumber = 0;\n player.divingDirection = userInput.xDirection;\n player.yVelocity = -5;\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-sound code function (playerpointer + 0x90 + 0x10)? omitted\n player.sound.chu = true;\n }\n }\n\n if (player.state === 1) {\n player.frameNumber = (player.frameNumber + 1) % 3;\n } else if (player.state === 2) {\n if (player.delayBeforeNextFrame < 1) {\n player.frameNumber += 1;\n if (player.frameNumber > 4) {\n player.frameNumber = 0;\n player.state = 1;\n }\n } else {\n player.delayBeforeNextFrame -= 1;\n }\n } else if (player.state === 0) {\n player.delayBeforeNextFrame += 1;\n if (player.delayBeforeNextFrame > 3) {\n player.delayBeforeNextFrame = 0;\n const futureFrameNumber =\n player.frameNumber + player.normalStatusArmSwingDirection;\n if (futureFrameNumber < 0 || futureFrameNumber > 4) {\n player.normalStatusArmSwingDirection =\n -player.normalStatusArmSwingDirection;\n }\n player.frameNumber =\n player.frameNumber + player.normalStatusArmSwingDirection;\n }\n }\n\n if (player.gameEnded === true) {\n if (player.state === 0) {\n if (player.isWinner === true) {\n player.state = 5;\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-sound code function (0x98 + 0x10) omitted\n player.sound.pipikachu = true;\n } else {\n player.state = 6;\n }\n player.delayBeforeNextFrame = 0;\n player.frameNumber = 0;\n }\n processGameEndFrameFor(player);\n }\n}\n\n/**\n * FUN_004025e0\n * Process game end frame (for winner and loser motions) for the given player\n * @param {Player} player\n */\nfunction processGameEndFrameFor(player) {\n if (player.gameEnded === true && player.frameNumber < 4) {\n player.delayBeforeNextFrame += 1;\n if (player.delayBeforeNextFrame > 4) {\n player.delayBeforeNextFrame = 0;\n player.frameNumber += 1;\n }\n }\n}\n\n/**\n * FUN_004030a0\n * Process collision between ball and player.\n * This function only sets velocity of ball and expected landing point x of ball.\n * This function does not set position of ball.\n * The ball position is set by {@link processCollisionBetweenBallAndWorldAndSetBallPosition} function\n *\n * @param {Ball} ball\n * @param {Player[\"x\"]} playerX\n * @param {PikaUserInput} userInput\n * @param {Player[\"state\"]} playerState\n */\nfunction processCollisionBetweenBallAndPlayer(\n ball,\n playerX,\n userInput,\n playerState\n) {\n // playerX is maybe pika's x position\n // if collision occur,\n // greater the x position difference between pika and ball,\n // greater the x velocity of the ball.\n if (ball.x < playerX) {\n // Since javascript division is float division by default,\n // Here we use \"| 0\" to do integer division (refer to: https://stackoverflow.com/a/17218003/8581025)\n ball.xVelocity = -((Math.abs(ball.x - playerX) / 3) | 0);\n } else if (ball.x > playerX) {\n ball.xVelocity = (Math.abs(ball.x - playerX) / 3) | 0;\n }\n\n // If ball velocity x is 0, randomly choose one of -1, 0, 1.\n if (ball.xVelocity === 0) {\n ball.xVelocity = (rand() % 3) - 1;\n }\n\n const ballAbsYVelocity = Math.abs(ball.yVelocity);\n ball.yVelocity = -ballAbsYVelocity;\n\n if (ballAbsYVelocity < 15) {\n ball.yVelocity = -15;\n }\n\n // player is jumping and power hitting\n if (playerState === 2) {\n if (ball.x < GROUND_HALF_WIDTH) {\n ball.xVelocity = (Math.abs(userInput.xDirection) + 1) * 10;\n } else {\n ball.xVelocity = -(Math.abs(userInput.xDirection) + 1) * 10;\n }\n ball.punchEffectX = ball.x;\n ball.punchEffectY = ball.y;\n\n ball.yVelocity = Math.abs(ball.yVelocity) * userInput.yDirection * 2;\n ball.punchEffectRadius = BALL_RADIUS;\n // maybe-stereo-sound function FUN_00408470 (0x90) omitted:\n // refer to a detailed comment above about this function\n // maybe-soundcode function (ballpointer + 0x24 + 0x10) omitted:\n ball.sound.powerHit = true;\n\n ball.isPowerHit = true;\n } else {\n ball.isPowerHit = false;\n }\n\n calculateExpectedLandingPointXFor(ball);\n}\n\n/**\n * FUN_004031b0\n * Calculate x coordinate of expected landing point of the ball\n * @param {Ball} ball\n */\nfunction calculateExpectedLandingPointXFor(ball) {\n const copyBall = {\n x: ball.x,\n y: ball.y,\n xVelocity: ball.xVelocity,\n yVelocity: ball.yVelocity,\n };\n let loopCounter = 0;\n while (true) {\n loopCounter++;\n\n const futureCopyBallX = copyBall.xVelocity + copyBall.x;\n if (futureCopyBallX < BALL_RADIUS || futureCopyBallX > GROUND_WIDTH) {\n copyBall.xVelocity = -copyBall.xVelocity;\n }\n if (copyBall.y + copyBall.yVelocity < 0) {\n copyBall.yVelocity = 1;\n }\n\n // If copy ball touches net\n if (\n Math.abs(copyBall.x - GROUND_HALF_WIDTH) < NET_PILLAR_HALF_WIDTH &&\n copyBall.y > NET_PILLAR_TOP_TOP_Y_COORD\n ) {\n // It maybe should be <= NET_PILLAR_TOP_BOTTOM_Y_COORD as in FUN_00402dc0, is it the original game author's mistake?\n if (copyBall.y < NET_PILLAR_TOP_BOTTOM_Y_COORD) {\n if (copyBall.yVelocity > 0) {\n copyBall.yVelocity = -copyBall.yVelocity;\n }\n } else {\n if (copyBall.x < GROUND_HALF_WIDTH) {\n copyBall.xVelocity = -Math.abs(copyBall.xVelocity);\n } else {\n copyBall.xVelocity = Math.abs(copyBall.xVelocity);\n }\n }\n }\n\n copyBall.y = copyBall.y + copyBall.yVelocity;\n // if copyBall would touch ground\n if (\n copyBall.y > BALL_TOUCHING_GROUND_Y_COORD ||\n loopCounter >= INFINITE_LOOP_LIMIT\n ) {\n break;\n }\n copyBall.x = copyBall.x + copyBall.xVelocity;\n copyBall.yVelocity += 1;\n }\n ball.expectedLandingPointX = copyBall.x;\n}\n\n/**\n * FUN_00402360\n * Computer controls its player by this function.\n * Computer decides the user input for the player it controls,\n * according to the game situation it figures out\n * by the given parameters (player, ball and theOtherPlayer),\n * and reflects these to the given user input object.\n *\n * @param {Player} player The player whom computer controls\n * @param {Ball} ball ball\n * @param {Player} theOtherPlayer The other player\n * @param {PikaUserInput} userInput user input of the player whom computer controls\n */\nfunction letComputerDecideUserInput(player, ball, theOtherPlayer, userInput) {\n userInput.xDirection = 0;\n userInput.yDirection = 0;\n userInput.powerHit = 0;\n\n let virtualExpectedLandingPointX = ball.expectedLandingPointX;\n if (\n Math.abs(ball.x - player.x) > 100 &&\n Math.abs(ball.xVelocity) < player.computerBoldness + 5\n ) {\n const leftBoundary = Number(player.isPlayer2) * GROUND_HALF_WIDTH;\n if (\n (ball.expectedLandingPointX <= leftBoundary ||\n ball.expectedLandingPointX >=\n Number(player.isPlayer2) * GROUND_WIDTH + GROUND_HALF_WIDTH) &&\n player.computerWhereToStandBy === 0\n ) {\n // If conditions above met, the computer estimates the proper location to stay as the middle point of their side\n virtualExpectedLandingPointX =\n leftBoundary + ((GROUND_HALF_WIDTH / 2) | 0);\n }\n }\n\n if (\n Math.abs(virtualExpectedLandingPointX - player.x) >\n player.computerBoldness + 8\n ) {\n if (player.x < virtualExpectedLandingPointX) {\n userInput.xDirection = 1;\n } else {\n userInput.xDirection = -1;\n }\n } else if (rand() % 20 === 0) {\n player.computerWhereToStandBy = rand() % 2;\n }\n\n if (player.state === 0) {\n if (\n Math.abs(ball.xVelocity) < player.computerBoldness + 3 &&\n Math.abs(ball.x - player.x) < PLAYER_HALF_LENGTH &&\n ball.y > -36 &&\n ball.y < 10 * player.computerBoldness + 84 &&\n ball.yVelocity > 0\n ) {\n userInput.yDirection = -1;\n }\n\n const leftBoundary = Number(player.isPlayer2) * GROUND_HALF_WIDTH;\n const rightBoundary = (Number(player.isPlayer2) + 1) * GROUND_HALF_WIDTH;\n if (\n ball.expectedLandingPointX > leftBoundary &&\n ball.expectedLandingPointX < rightBoundary &&\n Math.abs(ball.x - player.x) >\n player.computerBoldness * 5 + PLAYER_LENGTH &&\n ball.x > leftBoundary &&\n ball.x < rightBoundary &&\n ball.y > 174\n ) {\n // If conditions above met, the computer decides to dive!\n userInput.powerHit = 1;\n if (player.x < ball.x) {\n userInput.xDirection = 1;\n } else {\n userInput.xDirection = -1;\n }\n }\n } else if (player.state === 1 || player.state === 2) {\n if (Math.abs(ball.x - player.x) > 8) {\n if (player.x < ball.x) {\n userInput.xDirection = 1;\n } else {\n userInput.xDirection = -1;\n }\n }\n if (Math.abs(ball.x - player.x) < 48 && Math.abs(ball.y - player.y) < 48) {\n const willInputPowerHit = decideWhetherInputPowerHit(\n player,\n ball,\n theOtherPlayer,\n userInput\n );\n if (willInputPowerHit === true) {\n userInput.powerHit = 1;\n if (\n Math.abs(theOtherPlayer.x - player.x) < 80 &&\n userInput.yDirection !== -1\n ) {\n userInput.yDirection = -1;\n }\n }\n }\n }\n}\n\n/**\n * FUN_00402630\n * This function is called by {@link letComputerDecideUserInput},\n * and also sets x and y direction user input so that it participate in\n * the decision of the direction of power hit.\n * @param {Player} player the player whom computer controls\n * @param {Ball} ball ball\n * @param {Player} theOtherPlayer The other player\n * @param {PikaUserInput} userInput user input for the player whom computer controls\n * @return {boolean} Will input power hit?\n */\nfunction decideWhetherInputPowerHit(player, ball, theOtherPlayer, userInput) {\n if (rand() % 2 === 0) {\n for (let xDirection = 1; xDirection > -1; xDirection--) {\n for (let yDirection = -1; yDirection < 2; yDirection++) {\n const expectedLandingPointX = expectedLandingPointXWhenPowerHit(\n xDirection,\n yDirection,\n ball\n );\n if (\n (expectedLandingPointX <=\n Number(player.isPlayer2) * GROUND_HALF_WIDTH ||\n expectedLandingPointX >=\n Number(player.isPlayer2) * GROUND_WIDTH + GROUND_HALF_WIDTH) &&\n Math.abs(expectedLandingPointX - theOtherPlayer.x) > PLAYER_LENGTH\n ) {\n userInput.xDirection = xDirection;\n userInput.yDirection = yDirection;\n return true;\n }\n }\n }\n } else {\n for (let xDirection = 1; xDirection > -1; xDirection--) {\n for (let yDirection = 1; yDirection > -2; yDirection--) {\n const expectedLandingPointX = expectedLandingPointXWhenPowerHit(\n xDirection,\n yDirection,\n ball\n );\n if (\n (expectedLandingPointX <=\n Number(player.isPlayer2) * GROUND_HALF_WIDTH ||\n expectedLandingPointX >=\n Number(player.isPlayer2) * GROUND_WIDTH + GROUND_HALF_WIDTH) &&\n Math.abs(expectedLandingPointX - theOtherPlayer.x) > PLAYER_LENGTH\n ) {\n userInput.xDirection = xDirection;\n userInput.yDirection = yDirection;\n return true;\n }\n }\n }\n }\n return false;\n}\n\n/**\n * FUN_00402870\n * This function is called by {@link decideWhetherInputPowerHit},\n * and calculates the expected x coordinate of the landing point of the ball\n * when power hit\n * @param {PikaUserInput[\"xDirection\"]} userInputXDirection\n * @param {PikaUserInput[\"yDirection\"]} userInputYDirection\n * @param {Ball} ball\n * @return {number} x coord of expected landing point when power hit the ball\n */\nfunction expectedLandingPointXWhenPowerHit(\n userInputXDirection,\n userInputYDirection,\n ball\n) {\n const copyBall = {\n x: ball.x,\n y: ball.y,\n xVelocity: ball.xVelocity,\n yVelocity: ball.yVelocity,\n };\n if (copyBall.x < GROUND_HALF_WIDTH) {\n copyBall.xVelocity = (Math.abs(userInputXDirection) + 1) * 10;\n } else {\n copyBall.xVelocity = -(Math.abs(userInputXDirection) + 1) * 10;\n }\n copyBall.yVelocity = Math.abs(copyBall.yVelocity) * userInputYDirection * 2;\n\n let loopCounter = 0;\n while (true) {\n loopCounter++;\n\n const futureCopyBallX = copyBall.x + copyBall.xVelocity;\n if (futureCopyBallX < BALL_RADIUS || futureCopyBallX > GROUND_WIDTH) {\n copyBall.xVelocity = -copyBall.xVelocity;\n }\n if (copyBall.y + copyBall.yVelocity < 0) {\n copyBall.yVelocity = 1;\n }\n if (\n Math.abs(copyBall.x - GROUND_HALF_WIDTH) < NET_PILLAR_HALF_WIDTH &&\n copyBall.y > NET_PILLAR_TOP_TOP_Y_COORD\n ) {\n /*\n The code below maybe is intended to make computer do mistakes.\n The player controlled by computer occasionally power hit ball that is bounced back by the net pillar,\n since code below do not anticipate the bounce back.\n */\n if (copyBall.yVelocity > 0) {\n copyBall.yVelocity = -copyBall.yVelocity;\n }\n /*\n An alternative code for making the computer not do those mistakes is as below.\n\n if (copyBall.y <= NET_PILLAR_TOP_BOTTOM_Y_COORD) {\n if (copyBall.yVelocity > 0) {\n copyBall.yVelocity = -copyBall.yVelocity;\n }\n } else {\n if (copyBall.x < GROUND_HALF_WIDTH) {\n copyBall.xVelocity = -Math.abs(copyBall.xVelocity);\n } else {\n copyBall.xVelocity = Math.abs(copyBall.xVelocity);\n }\n }\n */\n }\n copyBall.y = copyBall.y + copyBall.yVelocity;\n if (\n copyBall.y > BALL_TOUCHING_GROUND_Y_COORD ||\n loopCounter >= INFINITE_LOOP_LIMIT\n ) {\n return copyBall.x;\n }\n copyBall.x = copyBall.x + copyBall.xVelocity;\n copyBall.yVelocity += 1;\n }\n}\n","/**\n * This module takes charge of the physical motion of clouds (on the sky) and wave (on the bottom of game screen) in the game.\n * It is also a Model in MVC pattern and also rendered by \"view.js\".\n *\n * It is gained by reverse engineering the original game.\n * The address of the original function is in the comment.\n * ex) FUN_00404770 means the function at the address 00404770 in the machine code.\n */\n'use strict';\nimport { rand } from './rand.js';\n\n/**\n * Class represents a cloud\n */\nexport class Cloud {\n constructor() {\n this.topLeftPointX = -68 + (rand() % (432 + 68));\n this.topLeftPointY = rand() % 152;\n this.topLeftPointXVelocity = 1 + (rand() % 2);\n this.sizeDiffTurnNumber = rand() % 11;\n }\n\n get sizeDiff() {\n // this same as return [0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0][this.sizeDiffTurnNumber]\n return 5 - Math.abs(this.sizeDiffTurnNumber - 5);\n }\n\n get spriteTopLeftPointX() {\n return this.topLeftPointX - this.sizeDiff;\n }\n\n get spriteTopLeftPointY() {\n return this.topLeftPointY - this.sizeDiff;\n }\n\n get spriteWidth() {\n return 48 + 2 * this.sizeDiff;\n }\n\n get spriteHeight() {\n return 24 + 2 * this.sizeDiff;\n }\n}\n\n/**\n * Class representing wave\n */\nexport class Wave {\n constructor() {\n this.verticalCoord = 0;\n this.verticalCoordVelocity = 2;\n this.yCoords = [];\n for (let i = 0; i < 432 / 16; i++) {\n this.yCoords.push(314);\n }\n }\n}\n\n/**\n * FUN_00404770\n * Move clouds and wave\n * @param {Cloud[]} cloudArray\n * @param {Wave} wave\n */\nexport function cloudAndWaveEngine(cloudArray, wave) {\n for (let i = 0; i < 10; i++) {\n cloudArray[i].topLeftPointX += cloudArray[i].topLeftPointXVelocity;\n if (cloudArray[i].topLeftPointX > 432) {\n cloudArray[i].topLeftPointX = -68;\n cloudArray[i].topLeftPointY = rand() % 152;\n cloudArray[i].topLeftPointXVelocity = 1 + (rand() % 2);\n }\n cloudArray[i].sizeDiffTurnNumber =\n (cloudArray[i].sizeDiffTurnNumber + 1) % 11;\n }\n\n wave.verticalCoord += wave.verticalCoordVelocity;\n if (wave.verticalCoord > 32) {\n wave.verticalCoord = 32;\n wave.verticalCoordVelocity = -1;\n } else if (wave.verticalCoord < 0 && wave.verticalCoordVelocity < 0) {\n wave.verticalCoordVelocity = 2;\n wave.verticalCoord = -(rand() % 40);\n }\n\n for (let i = 0; i < 432 / 16; i++) {\n wave.yCoords[i] = 314 - wave.verticalCoord + (rand() % 3);\n }\n}\n","/**\n * The View part in the MVC pattern\n *\n * Some codes in this module were gained by reverse engineering the original machine code.\n * The codes gained by reverse engineering are commented by the address of the function referred to in the machine code.\n * ex) FUN_00405d50 means the function at the address 00405d50 in the machine code.\n */\n'use strict';\nimport { AnimatedSprite } from '@pixi/sprite-animated';\nimport { Sprite } from '@pixi/sprite';\nimport { Container } from '@pixi/display';\nimport { Cloud, Wave, cloudAndWaveEngine } from './cloud_and_wave.js';\nimport { ASSETS_PATH } from './assets_path.js';\n\n/** @typedef {import('@pixi/loaders').LoaderResource} LoaderResource */\n/** @typedef {import('@pixi/core').Texture} Texture */\n\nconst TEXTURES = ASSETS_PATH.TEXTURES;\n\n/** @constant @type {number} number of clouds to be rendered */\nconst NUM_OF_CLOUDS = 10;\n\n/**\n * Class representing intro view where the man with a briefcase mark appears\n */\nexport class IntroView {\n /**\n * Create an IntroView object\n * @param {Object.} resources loader.resources\n */\n constructor(resources) {\n const textures = resources[ASSETS_PATH.SPRITE_SHEET].textures;\n\n this.mark = makeSpriteWithAnchorXY(textures, TEXTURES.MARK, 0.5, 0.5);\n this.mark.x = 432 / 2;\n this.mark.y = 304 / 2;\n\n this.container = new Container();\n this.container.addChild(this.mark);\n }\n\n /** @return {boolean} Is visible? */\n get visible() {\n return this.container.visible;\n }\n\n /** @param {boolean} bool Is visible? */\n set visible(bool) {\n this.container.visible = bool;\n }\n\n /**\n * draw \"a man with a briefcase\" mark\n * @param {number} frameCounter\n */\n drawMark(frameCounter) {\n const mark = this.mark;\n if (frameCounter === 0) {\n mark.alpha = 0;\n return;\n }\n if (frameCounter < 100) {\n mark.alpha = Math.min(1, mark.alpha + 1 / 25);\n } else if (frameCounter >= 100) {\n mark.alpha = Math.max(0, mark.alpha - 1 / 25);\n }\n }\n}\n\n/**\n * Class representing menu view where you can select \"play with computer\" or \"play with friend\"\n */\nexport class MenuView {\n /**\n * Create a MenuView object\n * @param {Object.} resources loader.resources\n */\n constructor(resources) {\n const textures = resources[ASSETS_PATH.SPRITE_SHEET].textures;\n\n this.messages = {\n pokemon: makeSpriteWithAnchorXY(textures, TEXTURES.POKEMON, 0, 0),\n pikachuVolleyball: makeSpriteWithAnchorXY(\n textures,\n TEXTURES.PIKACHU_VOLLEYBALL,\n 0,\n 0\n ),\n withWho: [\n makeSpriteWithAnchorXY(textures, TEXTURES.WITH_COMPUTER, 0, 0),\n makeSpriteWithAnchorXY(textures, TEXTURES.WITH_FRIEND, 0, 0),\n ],\n sachisoft: makeSpriteWithAnchorXY(textures, TEXTURES.SACHISOFT, 0, 0),\n fight: makeSpriteWithAnchorXY(textures, TEXTURES.FIGHT, 0, 0),\n };\n this.sittingPikachuTilesContainer =\n makeSittingPikachuTilesContainer(textures);\n\n // referred to FUN_004059f0\n this.messages.sachisoft.x = 216 - this.messages.sachisoft.texture.width / 2;\n this.messages.sachisoft.y = 264;\n\n // referred to FUN_00405b70\n this.messages.pikachuVolleyball.x = 140;\n this.messages.pikachuVolleyball.y = 80;\n this.messages.pokemon.x = 170;\n this.messages.pokemon.y = 40;\n\n this.container = new Container();\n this.container.addChild(this.sittingPikachuTilesContainer);\n this.container.addChild(this.messages.pokemon);\n this.container.addChild(this.messages.pikachuVolleyball);\n this.container.addChild(this.messages.withWho[0]);\n this.container.addChild(this.messages.withWho[1]);\n this.container.addChild(this.messages.sachisoft);\n this.container.addChild(this.messages.fight);\n this.initializeVisibles();\n\n this.sittingPikachuTilesDisplacement = 0;\n this.selectedWithWho = -1; // 0: with computer, 1: with friend, -1: not selected\n this.selectedWithWhoMessageSizeIncrement = 2;\n }\n\n /** @return {boolean} Is visible? */\n get visible() {\n return this.container.visible;\n }\n\n /** @param {boolean} bool Is visible? */\n set visible(bool) {\n this.container.visible = bool;\n\n // when turn off view, initialize visibilities of sprites in this view\n if (bool === false) {\n this.initializeVisibles();\n }\n }\n\n initializeVisibles() {\n for (const prop in this.messages) {\n this.messages[prop].visible = false;\n }\n }\n\n /**\n * referred to FUN_00405d50\n * Draw \"fight!\" message which get bigger and smaller as frame goes\n * @param {number} frameCounter\n */\n drawFightMessage(frameCounter) {\n const sizeArray = [20, 22, 25, 27, 30, 27, 25, 22, 20];\n const fightMessage = this.messages.fight;\n const w = fightMessage.texture.width;\n const h = fightMessage.texture.height;\n\n if (frameCounter === 0) {\n fightMessage.visible = true;\n }\n\n if (frameCounter < 30) {\n const halfWidth = Math.floor(Math.floor((frameCounter * w) / 30) / 2);\n const halfHeight = Math.floor(Math.floor((frameCounter * h) / 30) / 2);\n fightMessage.width = halfWidth * 2; // width\n fightMessage.height = halfHeight * 2; // height\n fightMessage.x = 100 - halfWidth; // x coord\n fightMessage.y = 70 - halfHeight; // y coord\n } else {\n const index = (frameCounter + 1) % 9;\n // code ...\n const halfWidth = Math.floor(Math.floor((sizeArray[index] * w) / 30) / 2);\n const halfHeight = Math.floor(\n Math.floor((sizeArray[index] * h) / 30) / 2\n );\n fightMessage.width = halfWidth * 2; // width\n fightMessage.height = halfHeight * 2; // height\n fightMessage.y = 70 - halfHeight; // y coord\n fightMessage.x = 100 - halfWidth; // x coord\n }\n }\n\n /**\n * Draw sachisoft message as frame goes\n * @param {number} frameCounter\n */\n drawSachisoft(frameCounter) {\n if (frameCounter === 0) {\n this.messages.sachisoft.visible = true;\n this.messages.sachisoft.alpha = 0;\n }\n this.messages.sachisoft.alpha = Math.min(\n 1,\n this.messages.sachisoft.alpha + 0.04\n );\n\n if (frameCounter > 70) {\n this.messages.sachisoft.alpha = 1;\n }\n }\n\n /**\n * referred to FUN_00405ca0\n * Draw sitting pikachu tiles as frame goes\n * @param {number} frameCounter\n */\n drawSittingPikachuTiles(frameCounter) {\n if (frameCounter === 0) {\n this.sittingPikachuTilesContainer.visible = true;\n this.sittingPikachuTilesContainer.alpha = 0;\n }\n\n // movement\n // @ts-ignore\n const h = this.sittingPikachuTilesContainer.getChildAt(0).texture.height;\n this.sittingPikachuTilesDisplacement =\n (this.sittingPikachuTilesDisplacement + 2) % h;\n this.sittingPikachuTilesContainer.x = -this.sittingPikachuTilesDisplacement;\n this.sittingPikachuTilesContainer.y = -this.sittingPikachuTilesDisplacement;\n\n if (frameCounter > 30) {\n // alpha\n this.sittingPikachuTilesContainer.alpha = Math.min(\n 1,\n this.sittingPikachuTilesContainer.alpha + 0.04\n );\n }\n\n if (frameCounter > 70) {\n this.sittingPikachuTilesContainer.alpha = 1;\n }\n }\n\n /**\n * referred to FUN_00405b70\n * Draw pikachu volleyball message as frame goes\n * @param {number} frameCounter\n */\n drawPikachuVolleyballMessage(frameCounter) {\n if (frameCounter === 0) {\n this.messages.pikachuVolleyball.visible = false;\n return;\n }\n\n if (frameCounter > 30) {\n this.messages.pikachuVolleyball.visible = true;\n }\n\n if (frameCounter > 30 && frameCounter <= 44) {\n const xDiff = 195 - 15 * (frameCounter - 30);\n this.messages.pikachuVolleyball.x = 140 + xDiff;\n } else if (frameCounter > 44 && frameCounter <= 55) {\n this.messages.pikachuVolleyball.x = 140;\n this.messages.pikachuVolleyball.width = 200 - 15 * (frameCounter - 44);\n } else if (frameCounter > 55 && frameCounter <= 71) {\n this.messages.pikachuVolleyball.x = 140;\n this.messages.pikachuVolleyball.width = 40 + 15 * (frameCounter - 55);\n } else if (frameCounter > 71) {\n this.messages.pikachuVolleyball.x = 140;\n this.messages.pikachuVolleyball.width =\n this.messages.pikachuVolleyball.texture.width;\n }\n }\n\n /**\n * referred to FUN_00405b70\n * Draw pokemon message as frame goes\n * @param {number} frameCounter\n */\n drawPokemonMessage(frameCounter) {\n if (frameCounter === 0) {\n this.messages.pokemon.visible = false;\n return;\n }\n\n if (frameCounter > 71) {\n this.messages.pokemon.visible = true;\n }\n }\n\n /**\n * referred to FUN_00405ec0\n * Draw with who messages (with computer or with friend) as frame goes\n * @param {number} frameCounter\n */\n drawWithWhoMessages(frameCounter) {\n const withWho = this.messages.withWho;\n const w = withWho[0].texture.width;\n const h = withWho[0].texture.height;\n\n if (frameCounter === 0) {\n for (let i = 0; i < 2; i++) {\n withWho[i].visible = false;\n }\n return;\n }\n\n if (frameCounter > 70) {\n if (this.selectedWithWhoMessageSizeIncrement < 10) {\n this.selectedWithWhoMessageSizeIncrement += 1;\n }\n for (let i = 0; i < 2; i++) {\n const selected = Number(this.selectedWithWho === i); // 1 if selected, 0 otherwise\n const halfWidthIncrement =\n selected * (this.selectedWithWhoMessageSizeIncrement + 2);\n const halfHeightIncrement =\n selected * this.selectedWithWhoMessageSizeIncrement;\n\n withWho[i].visible = true;\n withWho[i].x = 216 - w / 2 - halfWidthIncrement;\n withWho[i].y = 184 + 30 * i - halfHeightIncrement;\n withWho[i].width = w + 2 * halfWidthIncrement;\n withWho[i].height = h + 2 * halfHeightIncrement;\n }\n }\n }\n\n /**\n * Select with who for the effect that selected option gets bigger\n * @param {number} i 0: with computer, 1: with friend\n */\n selectWithWho(i) {\n this.selectedWithWho = i;\n this.selectedWithWhoMessageSizeIncrement = 2;\n }\n}\n\n/**\n * Class represent a game view where pikachus, ball, clouds, waves, and backgrounds are\n */\nexport class GameView {\n /**\n * Create a GameView object\n * @param {Object.} resources\n */\n constructor(resources) {\n const textures = resources[ASSETS_PATH.SPRITE_SHEET].textures;\n\n // Display objects below\n this.bgContainer = makeBGContainer(textures);\n const playerSprites = makePlayerAnimatedSprites(textures);\n this.player1 = playerSprites[0];\n this.player2 = playerSprites[1];\n this.ball = makeBallAnimatedSprites(textures);\n this.ballHyper = makeSpriteWithAnchorXY(\n textures,\n TEXTURES.BALL_HYPER,\n 0.5,\n 0.5\n );\n this.ballTrail = makeSpriteWithAnchorXY(\n textures,\n TEXTURES.BALL_TRAIL,\n 0.5,\n 0.5\n );\n this.punch = makeSpriteWithAnchorXY(\n textures,\n TEXTURES.BALL_PUNCH,\n 0.5,\n 0.5\n );\n\n // this.scoreBoards[0] for player1, this.scoreBoards[1] for player2\n this.scoreBoards = [\n makeScoreBoardSprite(textures),\n makeScoreBoardSprite(textures),\n ];\n\n this.shadows = {\n forPlayer1: makeSpriteWithAnchorXY(textures, TEXTURES.SHADOW, 0.5, 0.5),\n forPlayer2: makeSpriteWithAnchorXY(textures, TEXTURES.SHADOW, 0.5, 0.5),\n forBall: makeSpriteWithAnchorXY(textures, TEXTURES.SHADOW, 0.5, 0.5),\n };\n\n this.messages = {\n gameStart: makeSpriteWithAnchorXY(textures, TEXTURES.GAME_START, 0, 0),\n ready: makeSpriteWithAnchorXY(textures, TEXTURES.READY, 0, 0),\n gameEnd: makeSpriteWithAnchorXY(textures, TEXTURES.GAME_END, 0, 0),\n };\n\n this.cloudContainer = makeCloudContainer(textures);\n this.waveContainer = makeWaveContainer(textures);\n\n // container which include whole display objects\n // Should be careful on addChild order\n // The later added, the more front(z-index) on screen\n this.container = new Container();\n this.container.addChild(this.bgContainer);\n this.container.addChild(this.cloudContainer);\n this.container.addChild(this.waveContainer);\n this.container.addChild(this.shadows.forPlayer1);\n this.container.addChild(this.shadows.forPlayer2);\n this.container.addChild(this.shadows.forBall);\n this.container.addChild(this.player1);\n this.container.addChild(this.player2);\n this.container.addChild(this.ballTrail);\n this.container.addChild(this.ballHyper);\n this.container.addChild(this.ball);\n this.container.addChild(this.punch);\n this.container.addChild(this.scoreBoards[0]);\n this.container.addChild(this.scoreBoards[1]);\n this.container.addChild(this.messages.gameStart);\n this.container.addChild(this.messages.ready);\n this.container.addChild(this.messages.gameEnd);\n\n // location and visibility setting\n this.bgContainer.x = 0;\n this.bgContainer.y = 0;\n this.cloudContainer.x = 0;\n this.cloudContainer.y = 0;\n this.waveContainer.x = 0;\n this.waveContainer.y = 0;\n\n this.messages.ready.x = 176;\n this.messages.ready.y = 38;\n this.scoreBoards[0].x = 14; // score board is 14 pixel distant from boundary\n this.scoreBoards[0].y = 10;\n this.scoreBoards[1].x = 432 - 32 - 32 - 14; // 32 pixel is for number (32x32px) width; one score board has tow numbers\n this.scoreBoards[1].y = 10;\n\n this.shadows.forPlayer1.y = 273;\n this.shadows.forPlayer2.y = 273;\n this.shadows.forBall.y = 273;\n\n this.initializeVisibles();\n\n // clouds and wave model.\n // This model is included in this view object, not on controller object\n // since it is not dependent on user input, and only used for rendering.\n this.cloudArray = [];\n for (let i = 0; i < NUM_OF_CLOUDS; i++) {\n this.cloudArray.push(new Cloud());\n }\n this.wave = new Wave();\n }\n\n /** @return {boolean} Is visible? */\n get visible() {\n return this.container.visible;\n }\n\n /** @param {boolean} bool Is visible? */\n set visible(bool) {\n this.container.visible = bool;\n\n // when turn off view\n if (bool === false) {\n this.initializeVisibles();\n }\n }\n\n initializeVisibles() {\n for (const prop in this.messages) {\n this.messages[prop].visible = false;\n }\n }\n\n /** @typedef {import(\"./physics\").PikaPhysics} PikaPhysics */\n /**\n * Draw players and ball in the given physics object\n * @param {PikaPhysics} physics PikaPhysics object to draw\n */\n drawPlayersAndBall(physics) {\n const player1 = physics.player1;\n const player2 = physics.player2;\n const ball = physics.ball;\n\n this.player1.x = player1.x;\n this.player1.y = player1.y;\n if (player1.state === 3 || player1.state === 4) {\n this.player1.scale.x = player1.divingDirection === -1 ? -1 : 1;\n } else {\n this.player1.scale.x = 1;\n }\n this.shadows.forPlayer1.x = player1.x;\n\n this.player2.x = player2.x;\n this.player2.y = player2.y;\n if (player2.state === 3 || player2.state === 4) {\n this.player2.scale.x = player2.divingDirection === 1 ? 1 : -1;\n } else {\n this.player2.scale.x = -1;\n }\n this.shadows.forPlayer2.x = player2.x;\n\n const frameNumber1 = getFrameNumberForPlayerAnimatedSprite(\n player1.state,\n player1.frameNumber\n );\n const frameNumber2 = getFrameNumberForPlayerAnimatedSprite(\n player2.state,\n player2.frameNumber\n );\n this.player1.gotoAndStop(frameNumber1);\n this.player2.gotoAndStop(frameNumber2);\n\n this.ball.x = ball.x;\n this.ball.y = ball.y;\n this.shadows.forBall.x = ball.x;\n this.ball.gotoAndStop(ball.rotation);\n\n // For punch effect, refer FUN_00402ee0\n if (ball.punchEffectRadius > 0) {\n ball.punchEffectRadius -= 2;\n this.punch.width = 2 * ball.punchEffectRadius;\n this.punch.height = 2 * ball.punchEffectRadius;\n this.punch.x = ball.punchEffectX;\n this.punch.y = ball.punchEffectY;\n this.punch.visible = true;\n } else {\n this.punch.visible = false;\n }\n\n if (ball.isPowerHit === true) {\n this.ballHyper.x = ball.previousX;\n this.ballHyper.y = ball.previousY;\n this.ballTrail.x = ball.previousPreviousX;\n this.ballTrail.y = ball.previousPreviousY;\n\n this.ballHyper.visible = true;\n this.ballTrail.visible = true;\n } else {\n this.ballHyper.visible = false;\n this.ballTrail.visible = false;\n }\n }\n\n /**\n * Draw scores to each score board\n * @param {number[]} scores [0] for player1 score, [1] for player2 score\n */\n drawScoresToScoreBoards(scores) {\n for (let i = 0; i < 2; i++) {\n const scoreBoard = this.scoreBoards[i];\n const score = scores[i];\n const unitsAnimatedSprite = scoreBoard.getChildAt(0);\n const tensAnimatedSprite = scoreBoard.getChildAt(1);\n // @ts-ignore\n unitsAnimatedSprite.gotoAndStop(score % 10);\n // @ts-ignore\n tensAnimatedSprite.gotoAndStop(Math.floor(score / 10) % 10);\n if (score >= 10) {\n tensAnimatedSprite.visible = true;\n } else {\n tensAnimatedSprite.visible = false;\n }\n }\n }\n\n /**\n * Draw clouds and wave\n */\n drawCloudsAndWave() {\n const cloudArray = this.cloudArray;\n const wave = this.wave;\n\n cloudAndWaveEngine(cloudArray, wave);\n\n for (let i = 0; i < NUM_OF_CLOUDS; i++) {\n const cloud = cloudArray[i];\n const cloudSprite = this.cloudContainer.getChildAt(i);\n cloudSprite.x = cloud.spriteTopLeftPointX;\n cloudSprite.y = cloud.spriteTopLeftPointY;\n // @ts-ignore\n cloudSprite.width = cloud.spriteWidth;\n // @ts-ignore\n cloudSprite.height = cloud.spriteHeight;\n }\n\n for (let i = 0; i < 432 / 16; i++) {\n const waveSprite = this.waveContainer.getChildAt(i);\n waveSprite.y = wave.yCoords[i];\n }\n }\n\n /**\n * refered FUN_00403f20\n * Draw game start message as frame goes\n * @param {number} frameCounter current frame number\n * @param {number} frameTotal total frame number for game start message\n */\n drawGameStartMessage(frameCounter, frameTotal) {\n if (frameCounter === 0) {\n this.messages.gameStart.visible = true;\n } else if (frameCounter >= frameTotal - 1) {\n this.messages.gameStart.visible = false;\n return;\n }\n\n const gameStartMessage = this.messages.gameStart;\n // game start message rendering\n const w = gameStartMessage.texture.width; // game start message texture width\n const h = gameStartMessage.texture.height; // game start message texture height\n const halfWidth = Math.floor((w * frameCounter) / 50);\n const halfHeight = Math.floor((h * frameCounter) / 50);\n gameStartMessage.x = 216 - halfWidth;\n gameStartMessage.y = 50 + 2 * halfHeight;\n gameStartMessage.width = 2 * halfWidth;\n gameStartMessage.height = 2 * halfHeight;\n }\n\n /**\n * Draw ready message\n * @param {boolean} bool turn on?\n */\n drawReadyMessage(bool) {\n this.messages.ready.visible = bool;\n }\n\n /**\n * Togle ready message.\n * Turn off if it's on, turn on if it's off.\n */\n toggleReadyMessage() {\n this.messages.ready.visible = !this.messages.ready.visible;\n }\n\n /**\n * refered FUN_00404070\n * Draw game end message as frame goes\n * @param {number} frameCounter\n */\n drawGameEndMessage(frameCounter) {\n const gameEndMessage = this.messages.gameEnd;\n const w = gameEndMessage.texture.width; // game end message texture width;\n const h = gameEndMessage.texture.height; // game end message texture height;\n\n if (frameCounter === 0) {\n gameEndMessage.visible = true;\n }\n if (frameCounter < 50) {\n const halfWidthIncrement = 2 * Math.floor(((50 - frameCounter) * w) / 50);\n const halfHeightIncrement =\n 2 * Math.floor(((50 - frameCounter) * h) / 50);\n\n gameEndMessage.x = 216 - w / 2 - halfWidthIncrement;\n gameEndMessage.y = 50 - halfHeightIncrement;\n gameEndMessage.width = w + 2 * halfWidthIncrement;\n gameEndMessage.height = h + 2 * halfHeightIncrement;\n } else {\n gameEndMessage.x = 216 - w / 2;\n gameEndMessage.y = 50;\n gameEndMessage.width = w;\n gameEndMessage.height = h;\n }\n }\n}\n\n/**\n * Class representing fade in out effect\n */\nexport class FadeInOut {\n constructor(resources) {\n const textures = resources[ASSETS_PATH.SPRITE_SHEET].textures;\n this.black = makeSpriteWithAnchorXY(textures, TEXTURES.BLACK, 0, 0);\n this.black.width = 432;\n this.black.height = 304;\n this.black.x = 0;\n this.black.y = 0;\n this.black.alpha = 1;\n }\n\n /** @return {boolean} Is visible? */\n get visible() {\n return this.black.visible;\n }\n\n /** @param {boolean} bool Is visible? */\n set visible(bool) {\n this.black.visible = bool;\n }\n\n /**\n * Set black alpha for fade in out\n * @param {number} alpha number in [0, 1]\n */\n setBlackAlphaTo(alpha) {\n this.black.alpha = alpha;\n if (this.black.alpha === 0) {\n this.black.visible = false;\n } else {\n this.black.visible = true;\n }\n }\n\n /**\n * Increase black alpha for fade in out\n * @param {number} alphaIncrement if alphaIncrement > 0: fade out, else fade in\n */\n changeBlackAlphaBy(alphaIncrement) {\n if (alphaIncrement >= 0) {\n this.black.alpha = Math.min(1, this.black.alpha + alphaIncrement);\n } else {\n this.black.alpha = Math.max(0, this.black.alpha + alphaIncrement);\n }\n if (this.black.alpha === 0) {\n this.black.visible = false;\n } else {\n this.black.visible = true;\n }\n }\n}\n\n/**\n * Make sitting pikachu tiles\n * @param {Object.} textures\n * @return {Container}\n */\nfunction makeSittingPikachuTilesContainer(textures) {\n const container = new Container();\n const texture = textures[TEXTURES.SITTING_PIKACHU];\n const w = texture.width;\n const h = texture.height;\n\n let tile;\n for (let j = 0; j < Math.floor(304 / h) + 2; j++) {\n for (let i = 0; i < Math.floor(432 / w) + 2; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(container, tile, w * i, h * j);\n }\n }\n\n return container;\n}\n\n/**\n * Make background\n * @param {Object.} textures\n * @return {Container}\n */\nfunction makeBGContainer(textures) {\n const bgContainer = new Container();\n\n // sky\n let tile;\n let texture = textures[TEXTURES.SKY_BLUE];\n for (let j = 0; j < 12; j++) {\n for (let i = 0; i < 432 / 16; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 16 * i, 16 * j);\n }\n }\n\n // mountain\n texture = textures[TEXTURES.MOUNTAIN];\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 0, 188);\n\n // ground_red\n texture = textures[TEXTURES.GROUND_RED];\n for (let i = 0; i < 432 / 16; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 16 * i, 248);\n }\n\n // ground_line\n texture = textures[TEXTURES.GROUND_LINE];\n for (let i = 1; i < 432 / 16 - 1; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 16 * i, 264);\n }\n texture = textures[TEXTURES.GROUND_LINE_LEFT_MOST];\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 0, 264);\n texture = textures[TEXTURES.GROUND_LINE_RIGHT_MOST];\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 432 - 16, 264);\n\n // ground_yellow\n texture = textures[TEXTURES.GROUND_YELLOW];\n for (let j = 0; j < 2; j++) {\n for (let i = 0; i < 432 / 16; i++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(\n bgContainer,\n tile,\n 16 * i,\n 280 + 16 * j\n );\n }\n }\n\n // net pillar\n texture = textures[TEXTURES.NET_PILLAR_TOP];\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 213, 176);\n texture = textures[TEXTURES.NET_PILLAR];\n for (let j = 0; j < 12; j++) {\n tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(bgContainer, tile, 213, 184 + 8 * j);\n }\n\n return bgContainer;\n}\n\n/**\n * Make animated sprites for both players\n * @param {Object.} textures\n * @return {AnimatedSprite[]} [0] for player 1, [1] for player2\n */\nfunction makePlayerAnimatedSprites(textures) {\n const getPlayerTexture = (i, j) => textures[TEXTURES.PIKACHU(i, j)];\n const playerTextureArray = [];\n for (let i = 0; i < 7; i++) {\n if (i === 3) {\n playerTextureArray.push(getPlayerTexture(i, 0));\n playerTextureArray.push(getPlayerTexture(i, 1));\n } else if (i === 4) {\n playerTextureArray.push(getPlayerTexture(i, 0));\n } else {\n for (let j = 0; j < 5; j++) {\n playerTextureArray.push(getPlayerTexture(i, j));\n }\n }\n }\n const player1AnimatedSprite = new AnimatedSprite(playerTextureArray, false);\n const player2AnimatedSprite = new AnimatedSprite(playerTextureArray, false);\n\n player1AnimatedSprite.anchor.x = 0.5;\n player1AnimatedSprite.anchor.y = 0.5;\n player2AnimatedSprite.anchor.x = 0.5;\n player2AnimatedSprite.anchor.y = 0.5;\n\n return [player1AnimatedSprite, player2AnimatedSprite];\n}\n\n/**\n * Make animated sprite of ball\n * @param {Object.} textures\n * @return {AnimatedSprite}\n */\nfunction makeBallAnimatedSprites(textures) {\n const getBallTexture = (s) => textures[TEXTURES.BALL(s)];\n const ballTextureArray = [\n getBallTexture(0),\n getBallTexture(1),\n getBallTexture(2),\n getBallTexture(3),\n getBallTexture(4),\n getBallTexture('hyper'),\n ];\n const ballAnimatedSprite = new AnimatedSprite(ballTextureArray, false);\n\n ballAnimatedSprite.anchor.x = 0.5;\n ballAnimatedSprite.anchor.y = 0.5;\n\n return ballAnimatedSprite;\n}\n\n/**\n * Make sprite with the texture on the path and with the given anchor x, y\n * @param {Object.} textures\n * @param {string} path\n * @param {number} anchorX anchor.x, number in [0, 1]\n * @param {number} anchorY anchor.y, number in [0, 1]\n * @return {Sprite}\n */\nfunction makeSpriteWithAnchorXY(textures, path, anchorX, anchorY) {\n const sprite = new Sprite(textures[path]);\n sprite.anchor.x = anchorX;\n sprite.anchor.y = anchorY;\n return sprite;\n}\n\n/**\n * Make score boards\n * @param {Object.} textures\n * @return {Container} child with index 0 for player 1 score board, child with index 1 for player2 score board\n */\nfunction makeScoreBoardSprite(textures) {\n const getNumberTexture = (n) => textures[TEXTURES.NUMBER(n)];\n const numberTextureArray = [];\n for (let i = 0; i < 10; i++) {\n numberTextureArray.push(getNumberTexture(i));\n }\n const numberAnimatedSprites = [null, null];\n numberAnimatedSprites[0] = new AnimatedSprite(numberTextureArray, false);\n numberAnimatedSprites[1] = new AnimatedSprite(numberTextureArray, false);\n\n const scoreBoard = new Container();\n addChildToParentAndSetLocalPosition(\n scoreBoard,\n numberAnimatedSprites[0],\n 32,\n 0\n ); // for units\n addChildToParentAndSetLocalPosition(\n scoreBoard,\n numberAnimatedSprites[1],\n 0,\n 0\n ); // for tens\n\n scoreBoard.setChildIndex(numberAnimatedSprites[0], 0); // for units\n scoreBoard.setChildIndex(numberAnimatedSprites[1], 1); // for tens\n\n return scoreBoard;\n}\n\n/**\n * Make a container with cloud sprites\n * @param {Object.} textures\n * @return {Container}\n */\nfunction makeCloudContainer(textures) {\n const cloudContainer = new Container();\n const texture = textures[TEXTURES.CLOUD];\n for (let i = 0; i < NUM_OF_CLOUDS; i++) {\n const cloud = new Sprite(texture);\n cloud.anchor.x = 0;\n cloud.anchor.y = 0;\n cloudContainer.addChild(cloud);\n }\n\n return cloudContainer;\n}\n\n/**\n * Make a container with wave sprites\n * @param {Object.} textures\n * @return {Container}\n */\nfunction makeWaveContainer(textures) {\n const waveContainer = new Container();\n const texture = textures[TEXTURES.WAVE];\n for (let i = 0; i < 432 / 16; i++) {\n const tile = new Sprite(texture);\n addChildToParentAndSetLocalPosition(waveContainer, tile, 16 * i, 0);\n }\n\n return waveContainer;\n}\n\n/**\n * Add child to parent and set local position\n * @param {Container} parent\n * @param {Sprite} child\n * @param {number} x local x\n * @param {number} y local y\n */\nfunction addChildToParentAndSetLocalPosition(parent, child, x, y) {\n parent.addChild(child);\n child.anchor.x = 0;\n child.anchor.y = 0;\n child.x = x;\n child.y = y;\n}\n\n/**\n * Get frame number for player animated sprite corresponds to the player state\n *\n * number of frames for state 0, state 1 and state 2 is 5 for each.\n * number of frames for state 3 is 2.\n * number of frames for state 4 is 1.\n * number of frames for state 5, state 6 is 5 for each.\n * @param {number} state player state\n * @param {number} frameNumber\n */\nfunction getFrameNumberForPlayerAnimatedSprite(state, frameNumber) {\n if (state < 4) {\n return 5 * state + frameNumber;\n } else if (state === 4) {\n return 17 + frameNumber;\n } else if (state > 4) {\n return 18 + 5 * (state - 5) + frameNumber;\n }\n}\n","/**\n * This module takes charge of the user input via keyboard\n */\n'use strict';\nimport { PikaUserInput } from './physics.js';\n\n/**\n * Class representing a keyboard used to control a player\n */\nexport class PikaKeyboard extends PikaUserInput {\n /**\n * Create a keyboard used for game controller\n * left, right, up, down, powerHit: KeyboardEvent.code value for each\n * Refer {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values}\n * @param {string} left KeyboardEvent.code value of the key to use for left\n * @param {string} right KeyboardEvent.code value of the key to use for right\n * @param {string} up KeyboardEvent.code value of the key to use for up\n * @param {string} down KeyboardEvent.code value of the key to use for down\n * @param {string} powerHit KeyboardEvent.code value of the key to use for power hit or selection\n * @param {string} downRight KeyboardEvent.code value of the key to use for having the same effect\n * when pressing down key and right key at the same time (Only player 1\n * has this key)\n */\n constructor(left, right, up, down, powerHit, downRight = null) {\n super();\n\n /** @type {boolean} */\n this.powerHitKeyIsDownPrevious = false;\n\n /** @type {Key} */\n this.leftKey = new Key(left);\n /** @type {Key} */\n this.rightKey = new Key(right);\n /** @type {Key} */\n this.upKey = new Key(up);\n /** @type {Key} */\n this.downKey = new Key(down);\n /** @type {Key} */\n this.powerHitKey = new Key(powerHit);\n /** @type {Key} */\n this.downRightKey = new Key(downRight);\n }\n\n /**\n * Get xDirection, yDirection, powerHit input from the keyboard.\n * This method is for freezing the keyboard input during the process of one game frame.\n */\n getInput() {\n if (this.leftKey.isDown) {\n this.xDirection = -1;\n } else if (\n this.rightKey.isDown ||\n (this.downRightKey && this.downRightKey.isDown)\n ) {\n this.xDirection = 1;\n } else {\n this.xDirection = 0;\n }\n\n if (this.upKey.isDown) {\n this.yDirection = -1;\n } else if (\n this.downKey.isDown ||\n (this.downRightKey && this.downRightKey.isDown)\n ) {\n this.yDirection = 1;\n } else {\n this.yDirection = 0;\n }\n\n const isDown = this.powerHitKey.isDown;\n if (!this.powerHitKeyIsDownPrevious && isDown) {\n this.powerHit = 1;\n } else {\n this.powerHit = 0;\n }\n this.powerHitKeyIsDownPrevious = isDown;\n }\n\n /**\n * Subscribe keydown, keyup event listeners for the keys of this keyboard\n */\n subscribe() {\n this.leftKey.subscribe();\n this.rightKey.subscribe();\n this.upKey.subscribe();\n this.downKey.subscribe();\n this.powerHitKey.subscribe();\n this.downRightKey.subscribe();\n }\n\n /**\n * Unsubscribe keydown, keyup event listeners for the keys of this keyboard\n */\n unsubscribe() {\n this.leftKey.unsubscribe();\n this.rightKey.unsubscribe();\n this.upKey.unsubscribe();\n this.downKey.unsubscribe();\n this.powerHitKey.unsubscribe();\n this.downRightKey.unsubscribe();\n }\n}\n\n/**\n * Class representing a key on a keyboard\n * referred to: https://github.com/kittykatattack/learningPixi\n */\nclass Key {\n /**\n * Create a key\n * Refer {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values}\n * @param {string} value KeyboardEvent.code value of this key\n */\n constructor(value) {\n this.value = value;\n this.isDown = false;\n this.isUp = true;\n\n this.downListener = this.downHandler.bind(this);\n this.upListener = this.upHandler.bind(this);\n this.subscribe();\n }\n\n /**\n * When key downed\n * @param {KeyboardEvent} event\n */\n downHandler(event) {\n if (event.code === this.value) {\n this.isDown = true;\n this.isUp = false;\n event.preventDefault();\n }\n }\n\n /**\n * When key upped\n * @param {KeyboardEvent} event\n */\n upHandler(event) {\n if (event.code === this.value) {\n this.isDown = false;\n this.isUp = true;\n event.preventDefault();\n }\n }\n\n /**\n * Subscribe event listeners\n */\n subscribe() {\n // I think an event listener for keyup should be attached\n // before the one for keydown to prevent a buggy behavior.\n // If keydown event listener were attached first and\n // a key was downed and upped before keyup event listener were attached,\n // I think the value of this.isDown would be true (and the value of this.isUp would be false)\n // for a while before the user press this key again.\n window.addEventListener('keyup', this.upListener);\n window.addEventListener('keydown', this.downListener);\n }\n\n /**\n * Unsubscribe event listeners\n */\n unsubscribe() {\n window.removeEventListener('keydown', this.downListener);\n window.removeEventListener('keyup', this.upListener);\n this.isDown = false;\n this.isUp = true;\n }\n}\n","/**\n * This module takes charge of the game audio (or sounds)\n */\n'use strict';\nimport { sound, Sound, filters } from '@pixi/sound';\nimport { ASSETS_PATH } from './assets_path.js';\n\nconst SOUNDS = ASSETS_PATH.SOUNDS;\n\n/** @typedef {import('@pixi/loaders').LoaderResource} LoaderResource */\n\n/**\n * Class representing audio\n */\nexport class PikaAudio {\n /**\n * Create a PikaAudio object\n * @param {Object.} resources loader.resources\n */\n constructor(resources) {\n /** @type {Object.} sounds pack */\n this.sounds = {\n bgm: new PikaStereoSound(resources[SOUNDS.BGM].sound),\n pipikachu: new PikaStereoSound(resources[SOUNDS.PIPIKACHU].sound),\n pika: new PikaStereoSound(resources[SOUNDS.PIKA].sound),\n chu: new PikaStereoSound(resources[SOUNDS.CHU].sound),\n pi: new PikaStereoSound(resources[SOUNDS.PI].sound),\n pikachu: new PikaStereoSound(resources[SOUNDS.PIKACHU].sound),\n powerHit: new PikaStereoSound(resources[SOUNDS.POWERHIT].sound),\n ballTouchesGround: new PikaStereoSound(\n resources[SOUNDS.BALLTOUCHESGROUND].sound\n ),\n };\n\n this.sounds.bgm.loop = true;\n /** @constant @type {number} proper bgm volume */\n this.properBGMVolume = 0.2;\n /** @constant @type {number} proper sfx volume */\n this.properSFXVolume = 0.35;\n this.adjustVolume();\n }\n\n /**\n * Adjust audio volume\n */\n adjustVolume() {\n for (const prop in this.sounds) {\n if (prop === 'bgm') {\n this.sounds[prop].volume = this.properBGMVolume;\n } else {\n this.sounds[prop].volume = this.properSFXVolume;\n }\n }\n }\n\n /**\n * turn BGM volume\n * @param {boolean} turnOn turnOn? turnOff\n */\n turnBGMVolume(turnOn) {\n let volume;\n if (turnOn) {\n volume = this.properBGMVolume;\n } else {\n volume = 0;\n }\n this.sounds.bgm.volume = volume;\n }\n\n /**\n * turn SFX volume\n * @param {boolean} turnOn turnOn? turnOff\n */\n turnSFXVolume(turnOn) {\n let volume;\n if (turnOn) {\n volume = this.properSFXVolume;\n } else {\n volume = 0;\n }\n for (const prop in this.sounds) {\n if (prop !== 'bgm') {\n this.sounds[prop].volume = volume;\n }\n }\n }\n\n muteAll() {\n sound.muteAll();\n }\n\n unmuteAll() {\n sound.unmuteAll();\n }\n}\n\n/**\n * Class representing a stereo sound\n */\nclass PikaStereoSound {\n /**\n * create a PikaStereoSound object\n * @param {Sound} sound\n */\n constructor(sound) {\n this.center = sound;\n this.left = Sound.from(sound.url);\n this.right = Sound.from(sound.url);\n\n const centerPanning = new filters.StereoFilter(0);\n const leftPanning = new filters.StereoFilter(-0.75);\n const rightPanning = new filters.StereoFilter(0.75);\n this.center.filters = [centerPanning];\n this.left.filters = [leftPanning];\n this.right.filters = [rightPanning];\n }\n\n /**\n * @param {number} v volume: number in [0, 1]\n */\n set volume(v) {\n this.center.volume = v;\n this.left.volume = v;\n this.right.volume = v;\n }\n\n /**\n * @param {boolean} bool\n */\n set loop(bool) {\n this.center.loop = bool;\n this.left.loop = bool;\n this.right.loop = bool;\n }\n\n /**\n * play this stereo sound\n * @param {number} leftOrCenterOrRight -1: left, 0: center, 1: right\n */\n play(leftOrCenterOrRight = 0) {\n if (leftOrCenterOrRight === 0) {\n this.center.play();\n } else if (leftOrCenterOrRight === -1) {\n this.left.play();\n } else if (leftOrCenterOrRight === 1) {\n this.right.play();\n }\n }\n\n /**\n * stop this stereo sound\n */\n stop() {\n this.center.stop();\n this.left.stop();\n this.right.stop();\n }\n}\n","/**\n * The Controller part in MVC pattern\n */\n'use strict';\nimport { GROUND_HALF_WIDTH, PikaPhysics } from './physics.js';\nimport { MenuView, GameView, FadeInOut, IntroView } from './view.js';\nimport { PikaKeyboard } from './keyboard.js';\nimport { PikaAudio } from './audio.js';\n\n/** @typedef {import('@pixi/display').Container} Container */\n/** @typedef {import('@pixi/loaders').LoaderResource} LoaderResource */\n\n/** @typedef GameState @type {function():void} */\n\n/**\n * Class representing Pikachu Volleyball game\n */\nexport class PikachuVolleyball {\n /**\n * Create a Pikachu Volleyball game which includes physics, view, audio\n * @param {Container} stage container which is rendered by PIXI.Renderer or PIXI.CanvasRenderer\n * @param {Object.} resources resources property of the PIXI.Loader object which is used for loading the game resources\n */\n constructor(stage, resources) {\n this.view = {\n intro: new IntroView(resources),\n menu: new MenuView(resources),\n game: new GameView(resources),\n fadeInOut: new FadeInOut(resources),\n };\n stage.addChild(this.view.intro.container);\n stage.addChild(this.view.menu.container);\n stage.addChild(this.view.game.container);\n stage.addChild(this.view.fadeInOut.black);\n this.view.intro.visible = false;\n this.view.menu.visible = false;\n this.view.game.visible = false;\n this.view.fadeInOut.visible = false;\n\n this.audio = new PikaAudio(resources);\n this.physics = new PikaPhysics(true, true);\n this.keyboardArray = [\n new PikaKeyboard('KeyD', 'KeyG', 'KeyR', 'KeyV', 'KeyZ', 'KeyF'), // for player1\n new PikaKeyboard( // for player2\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Enter'\n ),\n ];\n\n /** @type {number} game fps */\n this.normalFPS = 25;\n /** @type {number} fps for slow motion */\n this.slowMotionFPS = 5;\n\n /** @constant @type {number} number of frames for slow motion */\n this.SLOW_MOTION_FRAMES_NUM = 6;\n /** @type {number} number of frames left for slow motion */\n this.slowMotionFramesLeft = 0;\n /** @type {number} number of elapsed normal fps frames for rendering slow motion */\n this.slowMotionNumOfSkippedFrames = 0;\n\n /** @type {number} 0: with computer, 1: with friend */\n this.selectedWithWho = 0;\n\n /** @type {number[]} [0] for player 1 score, [1] for player 2 score */\n this.scores = [0, 0];\n /** @type {number} winning score: if either one of the players reaches this score, game ends */\n this.winningScore = 15;\n\n /** @type {boolean} Is the game ended? */\n this.gameEnded = false;\n /** @type {boolean} Is the round ended? */\n this.roundEnded = false;\n /** @type {boolean} Will player 2 serve? */\n this.isPlayer2Serve = false;\n\n /** @type {number} frame counter */\n this.frameCounter = 0;\n /** @type {Object.} total number of frames for each game state */\n this.frameTotal = {\n intro: 165,\n afterMenuSelection: 15,\n beforeStartOfNewGame: 15,\n startOfNewGame: 71,\n afterEndOfRound: 5,\n beforeStartOfNextRound: 30,\n gameEnd: 211,\n };\n\n /** @type {number} counter for frames while there is no input from keyboard */\n this.noInputFrameCounter = 0;\n /** @type {Object.} total number of frames to be rendered while there is no input */\n this.noInputFrameTotal = {\n menu: 225,\n };\n\n /** @type {boolean} true: paused, false: not paused */\n this.paused = false;\n\n /** @type {boolean} true: stereo, false: mono */\n this.isStereoSound = true;\n\n /** @type {boolean} true: practice mode on, false: practice mode off */\n this._isPracticeMode = false;\n\n /**\n * The game state which is being rendered now\n * @type {GameState}\n */\n this.state = this.intro;\n }\n\n /**\n * Game loop\n * This function should be called at regular intervals ( interval = (1 / FPS) second )\n */\n gameLoop() {\n if (this.paused === true) {\n return;\n }\n if (this.slowMotionFramesLeft > 0) {\n this.slowMotionNumOfSkippedFrames++;\n if (\n this.slowMotionNumOfSkippedFrames %\n Math.round(this.normalFPS / this.slowMotionFPS) !==\n 0\n ) {\n return;\n }\n this.slowMotionFramesLeft--;\n this.slowMotionNumOfSkippedFrames = 0;\n }\n // catch keyboard input and freeze it\n this.keyboardArray[0].getInput();\n this.keyboardArray[1].getInput();\n this.state();\n }\n\n /**\n * Intro: a man with a brief case\n * @type {GameState}\n */\n intro() {\n if (this.frameCounter === 0) {\n this.view.intro.visible = true;\n this.view.fadeInOut.setBlackAlphaTo(0);\n this.audio.sounds.bgm.stop();\n }\n this.view.intro.drawMark(this.frameCounter);\n this.frameCounter++;\n\n if (\n this.keyboardArray[0].powerHit === 1 ||\n this.keyboardArray[1].powerHit === 1\n ) {\n this.frameCounter = 0;\n this.view.intro.visible = false;\n this.state = this.menu;\n }\n\n if (this.frameCounter >= this.frameTotal.intro) {\n this.frameCounter = 0;\n this.view.intro.visible = false;\n this.state = this.menu;\n }\n }\n\n /**\n * Menu: select who do you want to play. With computer? With friend?\n * @type {GameState}\n */\n menu() {\n if (this.frameCounter === 0) {\n this.view.menu.visible = true;\n this.view.fadeInOut.setBlackAlphaTo(0);\n this.selectedWithWho = 0;\n this.view.menu.selectWithWho(this.selectedWithWho);\n }\n this.view.menu.drawFightMessage(this.frameCounter);\n this.view.menu.drawSachisoft(this.frameCounter);\n this.view.menu.drawSittingPikachuTiles(this.frameCounter);\n this.view.menu.drawPikachuVolleyballMessage(this.frameCounter);\n this.view.menu.drawPokemonMessage(this.frameCounter);\n this.view.menu.drawWithWhoMessages(this.frameCounter);\n this.frameCounter++;\n\n if (\n this.frameCounter < 71 &&\n (this.keyboardArray[0].powerHit === 1 ||\n this.keyboardArray[1].powerHit === 1)\n ) {\n this.frameCounter = 71;\n return;\n }\n\n if (this.frameCounter <= 71) {\n return;\n }\n\n if (\n (this.keyboardArray[0].yDirection === -1 ||\n this.keyboardArray[1].yDirection === -1) &&\n this.selectedWithWho === 1\n ) {\n this.noInputFrameCounter = 0;\n this.selectedWithWho = 0;\n this.view.menu.selectWithWho(this.selectedWithWho);\n this.audio.sounds.pi.play();\n } else if (\n (this.keyboardArray[0].yDirection === 1 ||\n this.keyboardArray[1].yDirection === 1) &&\n this.selectedWithWho === 0\n ) {\n this.noInputFrameCounter = 0;\n this.selectedWithWho = 1;\n this.view.menu.selectWithWho(this.selectedWithWho);\n this.audio.sounds.pi.play();\n } else {\n this.noInputFrameCounter++;\n }\n\n if (\n this.keyboardArray[0].powerHit === 1 ||\n this.keyboardArray[1].powerHit === 1\n ) {\n if (this.selectedWithWho === 1) {\n this.physics.player1.isComputer = false;\n this.physics.player2.isComputer = false;\n } else {\n if (this.keyboardArray[0].powerHit === 1) {\n this.physics.player1.isComputer = false;\n this.physics.player2.isComputer = true;\n } else if (this.keyboardArray[1].powerHit === 1) {\n this.physics.player1.isComputer = true;\n this.physics.player2.isComputer = false;\n }\n }\n this.audio.sounds.pikachu.play();\n this.frameCounter = 0;\n this.noInputFrameCounter = 0;\n this.state = this.afterMenuSelection;\n return;\n }\n\n if (this.noInputFrameCounter >= this.noInputFrameTotal.menu) {\n this.physics.player1.isComputer = true;\n this.physics.player2.isComputer = true;\n this.frameCounter = 0;\n this.noInputFrameCounter = 0;\n this.state = this.afterMenuSelection;\n }\n }\n\n /**\n * Fade out after menu selection\n * @type {GameState}\n */\n afterMenuSelection() {\n this.view.fadeInOut.changeBlackAlphaBy(1 / 16);\n this.frameCounter++;\n if (this.frameCounter >= this.frameTotal.afterMenuSelection) {\n this.frameCounter = 0;\n this.state = this.beforeStartOfNewGame;\n }\n }\n\n /**\n * Delay before start of new game (This is for the delay that exist in the original game)\n * @type {GameState}\n */\n beforeStartOfNewGame() {\n this.frameCounter++;\n if (this.frameCounter >= this.frameTotal.beforeStartOfNewGame) {\n this.frameCounter = 0;\n this.view.menu.visible = false;\n this.state = this.startOfNewGame;\n }\n }\n\n /**\n * Start of new game: Initialize ball and players and print game start message\n * @type {GameState}\n */\n startOfNewGame() {\n if (this.frameCounter === 0) {\n this.view.game.visible = true;\n this.gameEnded = false;\n this.roundEnded = false;\n this.isPlayer2Serve = false;\n this.physics.player1.gameEnded = false;\n this.physics.player1.isWinner = false;\n this.physics.player2.gameEnded = false;\n this.physics.player2.isWinner = false;\n\n this.scores[0] = 0;\n this.scores[1] = 0;\n this.view.game.drawScoresToScoreBoards(this.scores);\n\n this.physics.player1.initializeForNewRound();\n this.physics.player2.initializeForNewRound();\n this.physics.ball.initializeForNewRound(this.isPlayer2Serve);\n this.view.game.drawPlayersAndBall(this.physics);\n\n this.view.fadeInOut.setBlackAlphaTo(1); // set black screen\n this.audio.sounds.bgm.play();\n }\n\n this.view.game.drawGameStartMessage(\n this.frameCounter,\n this.frameTotal.startOfNewGame\n );\n this.view.game.drawCloudsAndWave();\n this.view.fadeInOut.changeBlackAlphaBy(-(1 / 17)); // fade in\n this.frameCounter++;\n\n if (this.frameCounter >= this.frameTotal.startOfNewGame) {\n this.frameCounter = 0;\n this.view.fadeInOut.setBlackAlphaTo(0);\n this.state = this.round;\n }\n }\n\n /**\n * Round: the players play volleyball in this game state\n * @type {GameState}\n */\n round() {\n const pressedPowerHit =\n this.keyboardArray[0].powerHit === 1 ||\n this.keyboardArray[1].powerHit === 1;\n\n if (\n this.physics.player1.isComputer === true &&\n this.physics.player2.isComputer === true &&\n pressedPowerHit\n ) {\n this.frameCounter = 0;\n this.view.game.visible = false;\n this.state = this.intro;\n return;\n }\n\n const isBallTouchingGround = this.physics.runEngineForNextFrame(\n this.keyboardArray\n );\n\n this.playSoundEffect();\n this.view.game.drawPlayersAndBall(this.physics);\n this.view.game.drawCloudsAndWave();\n\n if (this.gameEnded === true) {\n this.view.game.drawGameEndMessage(this.frameCounter);\n this.frameCounter++;\n if (\n this.frameCounter >= this.frameTotal.gameEnd ||\n (this.frameCounter >= 70 && pressedPowerHit)\n ) {\n this.frameCounter = 0;\n this.view.game.visible = false;\n this.state = this.intro;\n }\n return;\n }\n\n if (\n isBallTouchingGround &&\n this._isPracticeMode === false &&\n this.roundEnded === false &&\n this.gameEnded === false\n ) {\n if (this.physics.ball.punchEffectX < GROUND_HALF_WIDTH) {\n this.isPlayer2Serve = true;\n this.scores[1] += 1;\n if (this.scores[1] >= this.winningScore) {\n this.gameEnded = true;\n this.physics.player1.isWinner = false;\n this.physics.player2.isWinner = true;\n this.physics.player1.gameEnded = true;\n this.physics.player2.gameEnded = true;\n }\n } else {\n this.isPlayer2Serve = false;\n this.scores[0] += 1;\n if (this.scores[0] >= this.winningScore) {\n this.gameEnded = true;\n this.physics.player1.isWinner = true;\n this.physics.player2.isWinner = false;\n this.physics.player1.gameEnded = true;\n this.physics.player2.gameEnded = true;\n }\n }\n this.view.game.drawScoresToScoreBoards(this.scores);\n if (this.roundEnded === false && this.gameEnded === false) {\n this.slowMotionFramesLeft = this.SLOW_MOTION_FRAMES_NUM;\n }\n this.roundEnded = true;\n }\n\n if (this.roundEnded === true && this.gameEnded === false) {\n // if this is the last frame of this round, begin fade out\n if (this.slowMotionFramesLeft === 0) {\n this.view.fadeInOut.changeBlackAlphaBy(1 / 16); // fade out\n this.state = this.afterEndOfRound;\n }\n }\n }\n\n /**\n * Fade out after end of round\n * @type {GameState}\n */\n afterEndOfRound() {\n this.view.fadeInOut.changeBlackAlphaBy(1 / 16);\n this.frameCounter++;\n if (this.frameCounter >= this.frameTotal.afterEndOfRound) {\n this.frameCounter = 0;\n this.state = this.beforeStartOfNextRound;\n }\n }\n\n /**\n * Before start of next round, initialize ball and players, and print ready message\n * @type {GameState}\n */\n beforeStartOfNextRound() {\n if (this.frameCounter === 0) {\n this.view.fadeInOut.setBlackAlphaTo(1);\n this.view.game.drawReadyMessage(false);\n\n this.physics.player1.initializeForNewRound();\n this.physics.player2.initializeForNewRound();\n this.physics.ball.initializeForNewRound(this.isPlayer2Serve);\n this.view.game.drawPlayersAndBall(this.physics);\n }\n\n this.view.game.drawCloudsAndWave();\n this.view.fadeInOut.changeBlackAlphaBy(-(1 / 16));\n\n this.frameCounter++;\n if (this.frameCounter % 5 === 0) {\n this.view.game.toggleReadyMessage();\n }\n\n if (this.frameCounter >= this.frameTotal.beforeStartOfNextRound) {\n this.frameCounter = 0;\n this.view.game.drawReadyMessage(false);\n this.view.fadeInOut.setBlackAlphaTo(0);\n this.roundEnded = false;\n this.state = this.round;\n }\n }\n\n /**\n * Play sound effect on {@link round}\n */\n playSoundEffect() {\n const audio = this.audio;\n for (let i = 0; i < 2; i++) {\n const player = this.physics[`player${i + 1}`];\n const sound = player.sound;\n let leftOrCenterOrRight = 0;\n if (this.isStereoSound) {\n leftOrCenterOrRight = i === 0 ? -1 : 1;\n }\n if (sound.pipikachu === true) {\n audio.sounds.pipikachu.play(leftOrCenterOrRight);\n sound.pipikachu = false;\n }\n if (sound.pika === true) {\n audio.sounds.pika.play(leftOrCenterOrRight);\n sound.pika = false;\n }\n if (sound.chu === true) {\n audio.sounds.chu.play(leftOrCenterOrRight);\n sound.chu = false;\n }\n }\n const ball = this.physics.ball;\n const sound = ball.sound;\n let leftOrCenterOrRight = 0;\n if (this.isStereoSound) {\n if (ball.punchEffectX < GROUND_HALF_WIDTH) {\n leftOrCenterOrRight = -1;\n } else if (ball.punchEffectX > GROUND_HALF_WIDTH) {\n leftOrCenterOrRight = 1;\n }\n }\n if (sound.powerHit === true) {\n audio.sounds.powerHit.play(leftOrCenterOrRight);\n sound.powerHit = false;\n }\n if (sound.ballTouchesGround === true) {\n audio.sounds.ballTouchesGround.play(leftOrCenterOrRight);\n sound.ballTouchesGround = false;\n }\n }\n\n /**\n * Called if restart button clicked\n */\n restart() {\n this.frameCounter = 0;\n this.noInputFrameCounter = 0;\n this.slowMotionFramesLeft = 0;\n this.slowMotionNumOfSkippedFrames = 0;\n this.view.menu.visible = false;\n this.view.game.visible = false;\n this.state = this.intro;\n }\n\n /** @return {boolean} */\n get isPracticeMode() {\n return this._isPracticeMode;\n }\n\n /**\n * @param {boolean} bool true: turn on practice mode, false: turn off practice mode\n */\n set isPracticeMode(bool) {\n this._isPracticeMode = bool;\n this.view.game.scoreBoards[0].visible = !bool;\n this.view.game.scoreBoards[1].visible = !bool;\n }\n}\n","/**\n * Manages event listeners relevant to the UI (menu bar, buttons, etc.) of the web page\n */\n'use strict';\n\nimport { localStorageWrapper } from './utils/local_storage_wrapper.js';\n\n/** @typedef {import('./pikavolley.js').PikachuVolleyball} PikachuVolleyball */\n/** @typedef {import('@pixi/ticker').Ticker} Ticker */\n/** @typedef {{graphic?: string, bgm?: string, sfx?: string, speed?: string, winningScore?: string}} Options */\n\n/**\n * Enum for \"game paused by what?\".\n * The greater the number, the higher the precedence.\n *\n * @readonly\n * @enum {number}\n */\nconst PauseResumePrecedence = {\n pauseBtn: 3,\n messageBox: 2,\n dropdown: 1,\n notPaused: 0,\n};\n\n/**\n * Manages pausing and resuming of the game\n */\nconst pauseResumeManager = {\n /** @type {number} PauseResumePrecedence enum */\n _precedence: PauseResumePrecedence.notPaused,\n /**\n * Pause game\n * @param {PikachuVolleyball} pikaVolley\n * @param {number} precedence PauseResumePrecedence enum\n */\n pause: function (pikaVolley, precedence) {\n // @ts-ignore\n if (precedence > this._precedence) {\n pikaVolley.paused = true;\n this._precedence = precedence;\n }\n },\n /**\n * Resume game\n * @param {PikachuVolleyball} pikaVolley\n * @param {number} precedence PauseResumePrecedence enum\n */\n resume: function (pikaVolley, precedence) {\n if (precedence === this._precedence) {\n pikaVolley.paused = false;\n this._precedence = PauseResumePrecedence.notPaused;\n }\n },\n};\n\n/**\n * Set up the user interface: menu bar, buttons, dropdowns, submenus, etc.\n * @param {PikachuVolleyball} pikaVolley\n * @param {Ticker} ticker\n */\nexport function setUpUI(pikaVolley, ticker) {\n /**\n * Apply options\n * @param {Options} options\n */\n const applyOptions = (options) => {\n setSelectedOptionsBtn(options);\n switch (options.graphic) {\n case 'sharp':\n document.getElementById('game-canvas').classList.remove('graphic-soft');\n break;\n case 'soft':\n document.getElementById('game-canvas').classList.add('graphic-soft');\n break;\n }\n switch (options.bgm) {\n case 'on':\n pikaVolley.audio.turnBGMVolume(true);\n break;\n case 'off':\n pikaVolley.audio.turnBGMVolume(false);\n break;\n }\n switch (options.sfx) {\n case 'stereo':\n pikaVolley.audio.turnSFXVolume(true);\n pikaVolley.isStereoSound = true;\n break;\n case 'mono':\n pikaVolley.audio.turnSFXVolume(true);\n pikaVolley.isStereoSound = false;\n break;\n case 'off':\n pikaVolley.audio.turnSFXVolume(false);\n break;\n }\n switch (options.speed) {\n case 'slow':\n pikaVolley.normalFPS = 20;\n ticker.maxFPS = pikaVolley.normalFPS;\n break;\n case 'medium':\n pikaVolley.normalFPS = 25;\n ticker.maxFPS = pikaVolley.normalFPS;\n break;\n case 'fast':\n pikaVolley.normalFPS = 30;\n ticker.maxFPS = pikaVolley.normalFPS;\n break;\n }\n switch (options.winningScore) {\n case '5':\n pikaVolley.winningScore = 5;\n break;\n case '10':\n pikaVolley.winningScore = 10;\n break;\n case '15':\n pikaVolley.winningScore = 15;\n break;\n }\n };\n\n /**\n * Save options\n * @param {Options} options\n */\n const saveOptions = (options) => {\n setSelectedOptionsBtn(options);\n if (options.graphic) {\n localStorageWrapper.set('pv-offline-graphic', options.graphic);\n }\n if (options.bgm) {\n localStorageWrapper.set('pv-offline-bgm', options.bgm);\n }\n if (options.sfx) {\n localStorageWrapper.set('pv-offline-sfx', options.sfx);\n }\n if (options.speed) {\n localStorageWrapper.set('pv-offline-speed', options.speed);\n }\n if (options.winningScore) {\n localStorageWrapper.set('pv-offline-winningScore', options.winningScore);\n }\n };\n\n /**\n * Load options\n * @returns {Options}\n */\n const loadOptions = () => ({\n graphic: localStorageWrapper.get('pv-offline-graphic'),\n bgm: localStorageWrapper.get('pv-offline-bgm'),\n sfx: localStorageWrapper.get('pv-offline-sfx'),\n speed: localStorageWrapper.get('pv-offline-speed'),\n winningScore: localStorageWrapper.get('pv-offline-winningScore'),\n });\n\n /**\n * Apply and save options\n * @param {Options} options\n */\n const applyAndSaveOptions = (options) => {\n applyOptions(options);\n saveOptions(options);\n };\n\n // Load and apply saved options\n applyOptions(loadOptions());\n\n setUpBtns(pikaVolley, applyAndSaveOptions);\n setUpToShowDropdownsAndSubmenus(pikaVolley);\n\n // hide or show menubar if the user presses the \"esc\" key\n window.addEventListener('keydown', (event) => {\n if (event.code === 'Escape') {\n const menuBar = document.getElementById('menu-bar');\n if (menuBar.classList.contains('hidden')) {\n menuBar.classList.remove('hidden');\n } else {\n menuBar.classList.add('hidden');\n }\n event.preventDefault();\n } else if (event.code === 'Space') {\n const aboutBox = document.getElementById('about-box');\n if (aboutBox.classList.contains('hidden')) {\n event.preventDefault();\n }\n }\n });\n\n document.addEventListener('visibilitychange', function () {\n if (document.visibilityState === 'visible') {\n pikaVolley.audio.unmuteAll();\n } else {\n pikaVolley.audio.muteAll();\n }\n });\n}\n\n/**\n * Attach event listeners to the buttons\n * @param {PikachuVolleyball} pikaVolley\n * @param {(options: Options) => void} applyAndSaveOptions\n */\nfunction setUpBtns(pikaVolley, applyAndSaveOptions) {\n const gameDropdownBtn = document.getElementById('game-dropdown-btn');\n const optionsDropdownBtn = document.getElementById('options-dropdown-btn');\n const aboutBtn = document.getElementById('about-btn');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n // @ts-ignore\n aboutBtn.disabled = false;\n\n const pauseBtn = document.getElementById('pause-btn');\n pauseBtn.addEventListener('click', () => {\n if (pauseBtn.classList.contains('selected')) {\n pauseBtn.classList.remove('selected');\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.pauseBtn);\n } else {\n pauseBtn.classList.add('selected');\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.pauseBtn);\n }\n });\n\n const restartBtn = document.getElementById('restart-btn');\n restartBtn.addEventListener('click', () => {\n if (pauseBtn.classList.contains('selected')) {\n pauseBtn.classList.remove('selected');\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.pauseBtn);\n }\n pikaVolley.restart();\n });\n\n const graphicSharpBtn = document.getElementById('graphic-sharp-btn');\n const graphicSoftBtn = document.getElementById('graphic-soft-btn');\n graphicSharpBtn.addEventListener('click', () => {\n applyAndSaveOptions({ graphic: 'sharp' });\n });\n graphicSoftBtn.addEventListener('click', () => {\n applyAndSaveOptions({ graphic: 'soft' });\n });\n\n const bgmOnBtn = document.getElementById('bgm-on-btn');\n const bgmOffBtn = document.getElementById('bgm-off-btn');\n bgmOnBtn.addEventListener('click', () => {\n applyAndSaveOptions({ bgm: 'on' });\n });\n bgmOffBtn.addEventListener('click', () => {\n applyAndSaveOptions({ bgm: 'off' });\n });\n\n const stereoBtn = document.getElementById('stereo-btn');\n const monoBtn = document.getElementById('mono-btn');\n const sfxOffBtn = document.getElementById('sfx-off-btn');\n stereoBtn.addEventListener('click', () => {\n applyAndSaveOptions({ sfx: 'stereo' });\n });\n monoBtn.addEventListener('click', () => {\n applyAndSaveOptions({ sfx: 'mono' });\n });\n sfxOffBtn.addEventListener('click', () => {\n applyAndSaveOptions({ sfx: 'off' });\n });\n\n // Game speed:\n // slow: 1 frame per 50ms = 20 FPS\n // medium: 1 frame per 40ms = 25 FPS\n // fast: 1 frame per 33ms = 30.303030... FPS\n const slowSpeedBtn = document.getElementById('slow-speed-btn');\n const mediumSpeedBtn = document.getElementById('medium-speed-btn');\n const fastSpeedBtn = document.getElementById('fast-speed-btn');\n slowSpeedBtn.addEventListener('click', () => {\n applyAndSaveOptions({ speed: 'slow' });\n });\n mediumSpeedBtn.addEventListener('click', () => {\n applyAndSaveOptions({ speed: 'medium' });\n });\n fastSpeedBtn.addEventListener('click', () => {\n applyAndSaveOptions({ speed: 'fast' });\n });\n\n const winningScore5Btn = document.getElementById('winning-score-5-btn');\n const winningScore10Btn = document.getElementById('winning-score-10-btn');\n const winningScore15Btn = document.getElementById('winning-score-15-btn');\n const noticeBox1 = document.getElementById('notice-box-1');\n const noticeOKBtn1 = document.getElementById('notice-ok-btn-1');\n const winningScoreInNoticeBox1 = document.getElementById(\n 'winning-score-in-notice-box-1'\n );\n function isWinningScoreAlreadyReached(winningScore) {\n const isGamePlaying =\n pikaVolley.state === pikaVolley.round ||\n pikaVolley.state === pikaVolley.afterEndOfRound ||\n pikaVolley.state === pikaVolley.beforeStartOfNextRound;\n if (\n isGamePlaying &&\n (pikaVolley.scores[0] >= winningScore ||\n pikaVolley.scores[1] >= winningScore)\n ) {\n return true;\n }\n return false;\n }\n const noticeBox2 = document.getElementById('notice-box-2');\n const noticeOKBtn2 = document.getElementById('notice-ok-btn-2');\n winningScore5Btn.addEventListener('click', () => {\n if (winningScore5Btn.classList.contains('selected')) {\n return;\n }\n if (pikaVolley.isPracticeMode === true) {\n noticeBox2.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n if (isWinningScoreAlreadyReached(5)) {\n winningScoreInNoticeBox1.textContent = '5';\n noticeBox1.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n applyAndSaveOptions({ winningScore: '5' });\n });\n winningScore10Btn.addEventListener('click', () => {\n if (winningScore10Btn.classList.contains('selected')) {\n return;\n }\n if (pikaVolley.isPracticeMode === true) {\n noticeBox2.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n if (isWinningScoreAlreadyReached(10)) {\n winningScoreInNoticeBox1.textContent = '10';\n noticeBox1.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n applyAndSaveOptions({ winningScore: '10' });\n });\n winningScore15Btn.addEventListener('click', () => {\n if (winningScore15Btn.classList.contains('selected')) {\n return;\n }\n if (pikaVolley.isPracticeMode === true) {\n noticeBox2.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n if (isWinningScoreAlreadyReached(15)) {\n winningScoreInNoticeBox1.textContent = '15';\n noticeBox1.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n // @ts-ignore\n aboutBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n return;\n }\n applyAndSaveOptions({ winningScore: '15' });\n });\n noticeOKBtn1.addEventListener('click', () => {\n if (!noticeBox1.classList.contains('hidden')) {\n noticeBox1.classList.add('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n // @ts-ignore\n aboutBtn.disabled = false;\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.messageBox);\n }\n });\n noticeOKBtn2.addEventListener('click', () => {\n if (!noticeBox2.classList.contains('hidden')) {\n noticeBox2.classList.add('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n // @ts-ignore\n aboutBtn.disabled = false;\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.messageBox);\n }\n });\n\n const practiceModeOnBtn = document.getElementById('practice-mode-on-btn');\n const practiceModeOffBtn = document.getElementById('practice-mode-off-btn');\n practiceModeOnBtn.addEventListener('click', () => {\n practiceModeOffBtn.classList.remove('selected');\n practiceModeOnBtn.classList.add('selected');\n pikaVolley.isPracticeMode = true;\n });\n practiceModeOffBtn.addEventListener('click', () => {\n practiceModeOnBtn.classList.remove('selected');\n practiceModeOffBtn.classList.add('selected');\n pikaVolley.isPracticeMode = false;\n });\n\n const aboutBox = document.getElementById('about-box');\n const closeAboutBtn = document.getElementById('close-about-btn');\n aboutBtn.addEventListener('click', () => {\n if (aboutBox.classList.contains('hidden')) {\n aboutBox.classList.remove('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.messageBox);\n } else {\n aboutBox.classList.add('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.messageBox);\n }\n });\n closeAboutBtn.addEventListener('click', () => {\n if (!aboutBox.classList.contains('hidden')) {\n aboutBox.classList.add('hidden');\n // @ts-ignore\n gameDropdownBtn.disabled = false;\n // @ts-ignore\n optionsDropdownBtn.disabled = false;\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.messageBox);\n }\n });\n\n const resetToDefaultBtn = document.getElementById('reset-to-default-btn');\n resetToDefaultBtn.addEventListener('click', () => {\n // turn off practice mode\n practiceModeOffBtn.click();\n\n // and restore the reset options to default\n const defaultOptions = {\n graphic: 'sharp',\n bgm: 'on',\n sfx: 'stereo',\n speed: 'medium',\n winningScore: '15',\n };\n applyAndSaveOptions(defaultOptions);\n });\n}\n\n/**\n * Set selected (checked) options btn fit to options\n * @param {Options} options\n */\nfunction setSelectedOptionsBtn(options) {\n if (options.graphic) {\n const graphicSharpBtn = document.getElementById('graphic-sharp-btn');\n const graphicSoftBtn = document.getElementById('graphic-soft-btn');\n switch (options.graphic) {\n case 'sharp':\n graphicSoftBtn.classList.remove('selected');\n graphicSharpBtn.classList.add('selected');\n break;\n case 'soft':\n graphicSharpBtn.classList.remove('selected');\n graphicSoftBtn.classList.add('selected');\n break;\n }\n }\n if (options.bgm) {\n const bgmOnBtn = document.getElementById('bgm-on-btn');\n const bgmOffBtn = document.getElementById('bgm-off-btn');\n switch (options.bgm) {\n case 'on':\n bgmOffBtn.classList.remove('selected');\n bgmOnBtn.classList.add('selected');\n break;\n case 'off':\n bgmOnBtn.classList.remove('selected');\n bgmOffBtn.classList.add('selected');\n break;\n }\n }\n if (options.sfx) {\n const stereoBtn = document.getElementById('stereo-btn');\n const monoBtn = document.getElementById('mono-btn');\n const sfxOffBtn = document.getElementById('sfx-off-btn');\n switch (options.sfx) {\n case 'stereo':\n monoBtn.classList.remove('selected');\n sfxOffBtn.classList.remove('selected');\n stereoBtn.classList.add('selected');\n break;\n case 'mono':\n sfxOffBtn.classList.remove('selected');\n stereoBtn.classList.remove('selected');\n monoBtn.classList.add('selected');\n break;\n case 'off':\n stereoBtn.classList.remove('selected');\n monoBtn.classList.remove('selected');\n sfxOffBtn.classList.add('selected');\n break;\n }\n }\n if (options.speed) {\n const slowSpeedBtn = document.getElementById('slow-speed-btn');\n const mediumSpeedBtn = document.getElementById('medium-speed-btn');\n const fastSpeedBtn = document.getElementById('fast-speed-btn');\n switch (options.speed) {\n case 'slow':\n mediumSpeedBtn.classList.remove('selected');\n fastSpeedBtn.classList.remove('selected');\n slowSpeedBtn.classList.add('selected');\n break;\n case 'medium':\n fastSpeedBtn.classList.remove('selected');\n slowSpeedBtn.classList.remove('selected');\n mediumSpeedBtn.classList.add('selected');\n break;\n case 'fast':\n slowSpeedBtn.classList.remove('selected');\n mediumSpeedBtn.classList.remove('selected');\n fastSpeedBtn.classList.add('selected');\n break;\n }\n }\n if (options.winningScore) {\n const winningScore5Btn = document.getElementById('winning-score-5-btn');\n const winningScore10Btn = document.getElementById('winning-score-10-btn');\n const winningScore15Btn = document.getElementById('winning-score-15-btn');\n switch (options.winningScore) {\n case '5':\n winningScore10Btn.classList.remove('selected');\n winningScore15Btn.classList.remove('selected');\n winningScore5Btn.classList.add('selected');\n break;\n case '10':\n winningScore15Btn.classList.remove('selected');\n winningScore5Btn.classList.remove('selected');\n winningScore10Btn.classList.add('selected');\n break;\n case '15':\n winningScore5Btn.classList.remove('selected');\n winningScore10Btn.classList.remove('selected');\n winningScore15Btn.classList.add('selected');\n break;\n }\n }\n}\n\n/**\n * Attach event listeners to show dropdowns and submenus properly\n * @param {PikachuVolleyball} pikaVolley\n */\nfunction setUpToShowDropdownsAndSubmenus(pikaVolley) {\n // hide dropdowns and submenus if the user clicks outside of these\n window.addEventListener('click', (event) => {\n // @ts-ignore\n if (!event.target.matches('.dropdown-btn, .submenu-btn')) {\n hideSubmenus();\n hideDropdownsExcept('');\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.dropdown);\n }\n });\n\n // set up to show dropdowns\n document.getElementById('game-dropdown-btn').addEventListener('click', () => {\n toggleDropdown('game-dropdown', pikaVolley);\n });\n document\n .getElementById('options-dropdown-btn')\n .addEventListener('click', () => {\n toggleDropdown('options-dropdown', pikaVolley);\n });\n\n // set up to show submenus on mouseover event\n document\n .getElementById('graphic-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('graphic-submenu-btn', 'graphic-submenu');\n });\n document\n .getElementById('bgm-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('bgm-submenu-btn', 'bgm-submenu');\n });\n document\n .getElementById('sfx-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('sfx-submenu-btn', 'sfx-submenu');\n });\n document\n .getElementById('speed-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('speed-submenu-btn', 'speed-submenu');\n });\n document\n .getElementById('winning-score-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('winning-score-submenu-btn', 'winning-score-submenu');\n });\n document\n .getElementById('practice-mode-submenu-btn')\n .addEventListener('mouseover', () => {\n showSubmenu('practice-mode-submenu-btn', 'practice-mode-submenu');\n });\n document\n .getElementById('reset-to-default-btn')\n .addEventListener('mouseover', () => {\n hideSubmenus();\n });\n\n // set up to show submenus on click event\n // (it is for touch device equipped with physical keyboard)\n document.getElementById('bgm-submenu-btn').addEventListener('click', () => {\n showSubmenu('bgm-submenu-btn', 'bgm-submenu');\n });\n document.getElementById('sfx-submenu-btn').addEventListener('click', () => {\n showSubmenu('sfx-submenu-btn', 'sfx-submenu');\n });\n document.getElementById('speed-submenu-btn').addEventListener('click', () => {\n showSubmenu('speed-submenu-btn', 'speed-submenu');\n });\n document\n .getElementById('winning-score-submenu-btn')\n .addEventListener('click', () => {\n showSubmenu('winning-score-submenu-btn', 'winning-score-submenu');\n });\n document\n .getElementById('practice-mode-submenu-btn')\n .addEventListener('click', () => {\n showSubmenu('practice-mode-submenu-btn', 'practice-mode-submenu');\n });\n document\n .getElementById('reset-to-default-btn')\n .addEventListener('click', () => {\n hideSubmenus();\n });\n}\n\n/**\n * Toggle (show or hide) the dropdown menu\n * @param {string} dropdownID html element id of the dropdown to toggle\n * @param {PikachuVolleyball} pikaVolley\n */\nfunction toggleDropdown(dropdownID, pikaVolley) {\n hideSubmenus();\n hideDropdownsExcept(dropdownID);\n const willShow = document.getElementById(dropdownID).classList.toggle('show');\n if (willShow) {\n pauseResumeManager.pause(pikaVolley, PauseResumePrecedence.dropdown);\n } else {\n pauseResumeManager.resume(pikaVolley, PauseResumePrecedence.dropdown);\n }\n}\n\n/**\n * Show the submenu\n * @param {string} submenuBtnID html element id of the submenu button whose submenu to show\n * @param {string} subMenuID html element id of the submenu to show\n */\nfunction showSubmenu(submenuBtnID, subMenuID) {\n hideSubmenus();\n document.getElementById(submenuBtnID).classList.add('open');\n document.getElementById(subMenuID).classList.add('show');\n}\n\n/**\n * Hide all other dropdowns except the dropdown\n * @param {string} dropdownID html element id of the dropdown\n */\nfunction hideDropdownsExcept(dropdownID) {\n const dropdowns = document.getElementsByClassName('dropdown');\n for (let i = 0; i < dropdowns.length; i++) {\n if (dropdowns[i].id !== dropdownID) {\n dropdowns[i].classList.remove('show');\n }\n }\n}\n\n/**\n * Hide all submenus\n */\nfunction hideSubmenus() {\n const submenus = document.getElementsByClassName('submenu');\n for (let i = 0; i < submenus.length; i++) {\n submenus[i].classList.remove('show');\n }\n const submenuBtns = document.getElementsByClassName('submenu-btn');\n for (let i = 0; i < submenuBtns.length; i++) {\n submenuBtns[i].classList.remove('open');\n }\n}\n","/**\n * This is the main script which executes the game.\n * General explanations for the all source code files of the game are following.\n *\n ********************************************************************************************************************\n * This web version of the Pikachu Volleyball is made by\n * reverse engineering the core part of the original Pikachu Volleyball game\n * which is developed by \"1997 (C) SACHI SOFT / SAWAYAKAN Programmers\" & \"1997 (C) Satoshi Takenouchi\".\n *\n * \"physics.js\", \"cloud_and_wave.js\", and some codes in \"view.js\" are the results of this reverse engineering.\n * Refer to the comments in each file for the machine code addresses of the original functions.\n ********************************************************************************************************************\n *\n * This web version game is mainly composed of three parts which follows MVC pattern.\n * 1) \"physics.js\" (Model): The physics engine which takes charge of the dynamics of the ball and the players (Pikachus).\n * It is gained by reverse engineering the machine code of the original game.\n * 2) \"view.js\" (View): The rendering part of the game which depends on pixi.js (https://www.pixijs.com/, https://github.com/pixijs/pixi.js) library.\n * Some codes in this part is gained by reverse engineering the original machine code.\n * 3) \"pikavolley.js\" (Controller): Make the game work by controlling the Model and the View according to the user input.\n *\n * And explanations for other source files are below.\n * - \"cloud_and_wave.js\": This is also a Model part which takes charge of the clouds and wave motion in the game. Of course, it is also rendered by \"view.js\".\n * It is also gained by reverse engineering the original machine code.\n * - \"keyboard.js\": Support the Controller(\"pikavolley.js\") to get a user input via keyboard.\n * - \"audio.js\": The game audio or sounds. It depends on pixi-sound (https://github.com/pixijs/pixi-sound) library.\n * - \"rand.js\": For the random function used in the Models (\"physics.js\", \"cloud_and_wave.js\").\n * - \"assets_path.js\": For the assets (image files, sound files) locations.\n * - \"ui.js\": For the user interface (menu bar, buttons etc.) of the html page.\n */\n'use strict';\nimport { settings } from '@pixi/settings';\nimport { SCALE_MODES } from '@pixi/constants';\nimport { Renderer, BatchRenderer, autoDetectRenderer } from '@pixi/core';\nimport { Prepare } from '@pixi/prepare';\nimport { Container } from '@pixi/display';\nimport { Loader } from '@pixi/loaders';\nimport { SpritesheetLoader } from '@pixi/spritesheet';\nimport { Ticker } from '@pixi/ticker';\nimport { CanvasRenderer } from '@pixi/canvas-renderer';\nimport { CanvasSpriteRenderer } from '@pixi/canvas-sprite';\nimport { CanvasPrepare } from '@pixi/canvas-prepare';\nimport '@pixi/canvas-display';\nimport { PikachuVolleyball } from './pikavolley.js';\nimport { ASSETS_PATH } from './assets_path.js';\nimport { setUpUI } from './ui.js';\n\n// Reference for how to use Renderer.registerPlugin:\n// https://github.com/pixijs/pixijs/blob/af3c0c6bb15aeb1049178c972e4a14bb4cabfce4/bundles/pixi.js/src/index.ts#L27-L34\nRenderer.registerPlugin('prepare', Prepare);\nRenderer.registerPlugin('batch', BatchRenderer);\n// Reference for how to use CanvasRenderer.registerPlugin:\n// https://github.com/pixijs/pixijs/blob/af3c0c6bb15aeb1049178c972e4a14bb4cabfce4/bundles/pixi.js-legacy/src/index.ts#L13-L19\nCanvasRenderer.registerPlugin('prepare', CanvasPrepare);\nCanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer);\nLoader.registerPlugin(SpritesheetLoader);\n\n// Set settings.RESOLUTION to 2 instead of 1 to make the game screen do not look\n// much blurry in case of the image rendering mode of 'image-rendering: auto',\n// which is like bilinear interpolation, which is used in \"soft\" game graphic option.\nsettings.RESOLUTION = 2;\nsettings.SCALE_MODE = SCALE_MODES.NEAREST;\nsettings.ROUND_PIXELS = true;\n\nconst renderer = autoDetectRenderer({\n width: 432,\n height: 304,\n antialias: false,\n backgroundColor: 0x000000,\n backgroundAlpha: 1,\n // Decided to use only Canvas for compatibility reason. One player had reported that\n // on their browser, where pixi chooses to use WebGL renderer, the graphics are not fine.\n // And the issue had been fixed by using Canvas renderer. And also for the sake of testing,\n // it is more comfortable just to stick with Canvas renderer so that it is unnecessary to switch\n // between WebGL renderer and Canvas renderer.\n forceCanvas: true,\n});\n\nconst stage = new Container();\nconst ticker = new Ticker();\nconst loader = new Loader();\n\nrenderer.view.setAttribute('id', 'game-canvas');\ndocument.getElementById('game-canvas-container').appendChild(renderer.view);\nrenderer.render(stage); // To make the initial canvas painting stable in the Firefox browser.\n\nloader.add(ASSETS_PATH.SPRITE_SHEET);\nfor (const prop in ASSETS_PATH.SOUNDS) {\n loader.add(ASSETS_PATH.SOUNDS[prop]);\n}\n\nsetUpInitialUI();\n\n/**\n * Set up the initial UI.\n */\nfunction setUpInitialUI() {\n const loadingBox = document.getElementById('loading-box');\n const progressBar = document.getElementById('progress-bar');\n loader.onProgress.add(() => {\n progressBar.style.width = `${loader.progress}%`;\n });\n loader.onComplete.add(() => {\n loadingBox.classList.add('hidden');\n });\n\n const aboutBox = document.getElementById('about-box');\n const aboutBtn = document.getElementById('about-btn');\n const closeAboutBtn = document.getElementById('close-about-btn');\n const gameDropdownBtn = document.getElementById('game-dropdown-btn');\n const optionsDropdownBtn = document.getElementById('options-dropdown-btn');\n // @ts-ignore\n gameDropdownBtn.disabled = true;\n // @ts-ignore\n optionsDropdownBtn.disabled = true;\n const closeAboutBox = () => {\n if (!aboutBox.classList.contains('hidden')) {\n aboutBox.classList.add('hidden');\n // @ts-ignore\n aboutBtn.disabled = true;\n }\n aboutBtn.getElementsByClassName('text-play')[0].classList.add('hidden');\n aboutBtn.getElementsByClassName('text-about')[0].classList.remove('hidden');\n aboutBtn.classList.remove('glow');\n closeAboutBtn\n .getElementsByClassName('text-play')[0]\n .classList.add('hidden');\n closeAboutBtn\n .getElementsByClassName('text-close')[0]\n .classList.remove('hidden');\n closeAboutBtn.classList.remove('glow');\n\n loader.load(setup); // setup is called after loader finishes loading\n loadingBox.classList.remove('hidden');\n aboutBtn.removeEventListener('click', closeAboutBox);\n closeAboutBtn.removeEventListener('click', closeAboutBox);\n };\n aboutBtn.addEventListener('click', closeAboutBox);\n closeAboutBtn.addEventListener('click', closeAboutBox);\n}\n\n/**\n * Set up the game and the full UI, and start the game.\n */\nfunction setup() {\n const pikaVolley = new PikachuVolleyball(stage, loader.resources);\n setUpUI(pikaVolley, ticker);\n start(pikaVolley);\n}\n\n/**\n * Start the game.\n * @param {PikachuVolleyball} pikaVolley\n */\nfunction start(pikaVolley) {\n ticker.maxFPS = pikaVolley.normalFPS;\n ticker.add(() => {\n pikaVolley.gameLoop();\n renderer.render(stage);\n });\n ticker.start();\n}\n","export const localStorageWrapper = {\n /**\n * Get value corresponding to the key from localStorage\n * @param {string} key\n * @returns {string|null}\n */\n get: (key) => {\n let value = null;\n try {\n value = localStorage.getItem(key);\n } catch (err) {\n console.error(err);\n }\n return value;\n },\n\n /*\n * Set key-value pair to the localStorage\n * @param {string} key\n * @param {string} value\n */\n set: (key, value) => {\n try {\n localStorage.setItem(key, value);\n } catch (err) {\n console.error(err);\n }\n },\n};\n"],"names":["ASSETS_PATH","SPRITE_SHEET","TEXTURES","SOUNDS","PIKACHU","i","j","BALL","s","NUMBER","n","SKY_BLUE","MOUNTAIN","GROUND_RED","GROUND_LINE","GROUND_LINE_LEFT_MOST","GROUND_LINE_RIGHT_MOST","GROUND_YELLOW","NET_PILLAR_TOP","NET_PILLAR","SHADOW","BALL_HYPER","BALL_TRAIL","BALL_PUNCH","CLOUD","WAVE","BLACK","SACHISOFT","READY","GAME_END","MARK","POKEMON","PIKACHU_VOLLEYBALL","FIGHT","WITH_COMPUTER","WITH_FRIEND","GAME_START","SITTING_PIKACHU","BGM","PIPIKACHU","PIKA","CHU","PI","POWERHIT","BALLTOUCHESGROUND","rand","Math","floor","random","GROUND_WIDTH","GROUND_HALF_WIDTH","PLAYER_TOUCHING_GROUND_Y_COORD","BALL_TOUCHING_GROUND_Y_COORD","PikaPhysics","constructor","isPlayer1Computer","isPlayer2Computer","this","player1","Player","player2","ball","Ball","runEngineForNextFrame","userInputArray","isBallTouchingGround","previousPreviousX","previousX","previousPreviousY","previousY","x","y","futureFineRotation","fineRotation","xVelocity","rotation","futureBallX","futureBallY","yVelocity","abs","sound","ballTouchesGround","punchEffectX","punchEffectRadius","punchEffectY","processCollisionBetweenBallAndWorldAndSetBallPosition","player","theOtherPlayer","calculateExpectedLandingPointXFor","processPlayerMovementAndSetPlayerPosition","isCollisionBetweenBallAndPlayerHappened","isCollisionWithBallHappened","processCollisionBetweenBallAndPlayer","state","physicsEngine","isPlayer2","isComputer","initializeForNewRound","divingDirection","lyingDownDurationLeft","isWinner","gameEnded","computerWhereToStandBy","pipikachu","pika","chu","frameNumber","normalStatusArmSwingDirection","delayBeforeNextFrame","computerBoldness","isPlayer2Serve","expectedLandingPointX","powerHit","isPowerHit","playerX","playerY","diff","userInput","xDirection","yDirection","virtualExpectedLandingPointX","leftBoundary","Number","rightBoundary","willInputPowerHit","expectedLandingPointXWhenPowerHit","decideWhetherInputPowerHit","letComputerDecideUserInput","playerVelocityX","futurePlayerX","futurePlayerY","futureFrameNumber","processGameEndFrameFor","playerState","ballAbsYVelocity","copyBall","loopCounter","futureCopyBallX","userInputXDirection","userInputYDirection","Cloud","topLeftPointX","topLeftPointY","topLeftPointXVelocity","sizeDiffTurnNumber","sizeDiff","spriteTopLeftPointX","spriteTopLeftPointY","spriteWidth","spriteHeight","Wave","verticalCoord","verticalCoordVelocity","yCoords","push","IntroView","resources","textures","mark","makeSpriteWithAnchorXY","container","addChild","visible","bool","drawMark","frameCounter","alpha","min","max","MenuView","messages","pokemon","pikachuVolleyball","withWho","sachisoft","fight","sittingPikachuTilesContainer","texture","w","width","h","height","tile","addChildToParentAndSetLocalPosition","makeSittingPikachuTilesContainer","initializeVisibles","sittingPikachuTilesDisplacement","selectedWithWho","selectedWithWhoMessageSizeIncrement","prop","drawFightMessage","sizeArray","fightMessage","halfWidth","halfHeight","index","drawSachisoft","drawSittingPikachuTiles","getChildAt","drawPikachuVolleyballMessage","xDiff","drawPokemonMessage","drawWithWhoMessages","selected","halfWidthIncrement","halfHeightIncrement","selectWithWho","GameView","bgContainer","makeBGContainer","playerSprites","getPlayerTexture","playerTextureArray","player1AnimatedSprite","player2AnimatedSprite","anchor","makePlayerAnimatedSprites","getBallTexture","ballTextureArray","ballAnimatedSprite","makeBallAnimatedSprites","ballHyper","ballTrail","punch","scoreBoards","makeScoreBoardSprite","shadows","forPlayer1","forPlayer2","forBall","gameStart","ready","gameEnd","cloudContainer","cloud","makeCloudContainer","waveContainer","makeWaveContainer","cloudArray","wave","drawPlayersAndBall","physics","scale","frameNumber1","getFrameNumberForPlayerAnimatedSprite","frameNumber2","gotoAndStop","drawScoresToScoreBoards","scores","scoreBoard","score","unitsAnimatedSprite","tensAnimatedSprite","drawCloudsAndWave","cloudAndWaveEngine","cloudSprite","drawGameStartMessage","frameTotal","gameStartMessage","drawReadyMessage","toggleReadyMessage","drawGameEndMessage","gameEndMessage","FadeInOut","black","setBlackAlphaTo","changeBlackAlphaBy","alphaIncrement","path","anchorX","anchorY","sprite","numberTextureArray","numberAnimatedSprites","setChildIndex","parent","child","PikaKeyboard","left","right","up","down","downRight","super","powerHitKeyIsDownPrevious","leftKey","Key","rightKey","upKey","downKey","powerHitKey","downRightKey","getInput","isDown","subscribe","unsubscribe","value","isUp","downListener","downHandler","bind","upListener","upHandler","event","code","preventDefault","window","addEventListener","removeEventListener","PikaAudio","sounds","bgm","PikaStereoSound","pi","pikachu","loop","properBGMVolume","properSFXVolume","adjustVolume","volume","turnBGMVolume","turnOn","turnSFXVolume","muteAll","unmuteAll","center","url","centerPanning","leftPanning","rightPanning","filters","v","play","leftOrCenterOrRight","stop","PikachuVolleyball","stage","view","intro","menu","game","fadeInOut","audio","keyboardArray","normalFPS","slowMotionFPS","SLOW_MOTION_FRAMES_NUM","slowMotionFramesLeft","slowMotionNumOfSkippedFrames","winningScore","roundEnded","afterMenuSelection","beforeStartOfNewGame","startOfNewGame","afterEndOfRound","beforeStartOfNextRound","noInputFrameCounter","noInputFrameTotal","paused","isStereoSound","_isPracticeMode","gameLoop","round","pressedPowerHit","playSoundEffect","restart","isPracticeMode","pauseResumeManager","_precedence","pause","pikaVolley","precedence","resume","setSelectedOptionsBtn","options","graphic","graphicSharpBtn","document","getElementById","graphicSoftBtn","classList","remove","add","bgmOnBtn","bgmOffBtn","sfx","stereoBtn","monoBtn","sfxOffBtn","speed","slowSpeedBtn","mediumSpeedBtn","fastSpeedBtn","winningScore5Btn","winningScore10Btn","winningScore15Btn","toggleDropdown","dropdownID","hideSubmenus","hideDropdownsExcept","toggle","showSubmenu","submenuBtnID","subMenuID","dropdowns","getElementsByClassName","length","id","submenus","submenuBtns","settings","renderer","antialias","backgroundColor","backgroundAlpha","forceCanvas","loader","setAttribute","appendChild","render","setup","ticker","applyOptions","maxFPS","applyAndSaveOptions","gameDropdownBtn","optionsDropdownBtn","aboutBtn","disabled","pauseBtn","contains","noticeBox1","noticeOKBtn1","winningScoreInNoticeBox1","isWinningScoreAlreadyReached","noticeBox2","noticeOKBtn2","textContent","practiceModeOnBtn","practiceModeOffBtn","aboutBox","closeAboutBtn","click","setUpBtns","saveOptions","target","matches","setUpToShowDropdownsAndSubmenus","menuBar","visibilityState","setUpUI","start","loadingBox","progressBar","onProgress","style","progress","onComplete","closeAboutBox","load","setUpInitialUI","localStorageWrapper","get","key","localStorage","getItem","err","console","error","set","setItem"],"sourceRoot":""} \ No newline at end of file diff --git a/sw.js b/sw.js index 328fa4b..55826ec 100644 --- a/sw.js +++ b/sw.js @@ -1,2 +1,2 @@ -if(!self.define){let e,s={};const r=(r,i)=>(r=new URL(r+".js",i).href,s[r]||new Promise((s=>{if("document"in self){const e=document.createElement("script");e.src=r,e.onload=s,document.head.appendChild(e)}else e=r,importScripts(r),s()})).then((()=>{let e=s[r];if(!e)throw new Error(`Module ${r} didn’t register its module`);return e})));self.define=(i,d)=>{const a=e||("document"in self?document.currentScript.src:"")||location.href;if(s[a])return;let c={};const o=e=>r(e,a),n={module:{uri:a},exports:c,require:o};s[a]=Promise.all(i.map((e=>n[e]||o(e)))).then((e=>(d(...e),c)))}}define(["./workbox-d5348a15"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.precacheAndRoute([{url:"407.bundle.js",revision:"1bee7c3e4f681d79778458d562f32fdb"},{url:"407.bundle.js.LICENSE.txt",revision:"5c018e230a018b5417ea6d77f6db7997"},{url:"dark_color_scheme.bundle.js",revision:"15fd2ff5720636254dd3bff5cd6ab7c4"},{url:"en/index.html",revision:"73d53cf8902a7dc8bb18379429f15e54"},{url:"en/manifest.json",revision:"9c2fba642fff247e04697110fcc58ff9"},{url:"en/update-history/index.html",revision:"bea1c2c31f98ef4eb330652620bcaaef"},{url:"index.html",revision:"97623352ef3b2b2572bfa2108aeabdfe"},{url:"is_embedded_in_other_website.bundle.js",revision:"ed9756eafdc0b1ae07d5457b20c2c84e"},{url:"ko.bundle.js",revision:"85b7983e86676f7e9e59a1ad52034a2b"},{url:"ko/index.html",revision:"1e8f3facc13c49fd930b02739e75cee4"},{url:"ko/manifest.json",revision:"20e0d1683d218b21f80574bc139aeb81"},{url:"ko/update-history/index.html",revision:"c6e62362ae9c9cda053d3dde3e38e983"},{url:"main.bundle.js",revision:"d85a3ed5d26b9c0c12b8ccee94ac61e2"},{url:"resources/assets/images/IDI_PIKAICON-0.png",revision:"818a5aabfd92f99c7d1f98b8361d3c7f"},{url:"resources/assets/images/IDI_PIKAICON-1_gap_filled.png",revision:"f3f21ca643c4ff5e692b8de485ae8004"},{url:"resources/assets/images/IDI_PIKAICON-1_gap_filled_192.png",revision:"dac21c95f585cb036ad61246d3d722b2"},{url:"resources/assets/images/IDI_PIKAICON-1_gap_filled_512.png",revision:"6cbcbdfef391a347ba1643574bd7ed1b"},{url:"resources/assets/images/controls.png",revision:"5275b91d01abe46c45f43fe59c95d170"},{url:"resources/assets/images/controls_ko.png",revision:"c5c52fd2313b63d024ad06060609c84f"},{url:"resources/assets/images/screenshot.png",revision:"3867bffd4bef3786694f9ebeb77d4d1d"},{url:"resources/assets/images/sprite_sheet.json",revision:"5b62092ca5b40d420e906629b647c919"},{url:"resources/assets/images/sprite_sheet.png",revision:"4fc3712243966195534ee80e1ca81364"},{url:"resources/assets/sounds/WAVE140_1.wav",revision:"a31e486f9bf2dfa2548a4208d78edc1f"},{url:"resources/assets/sounds/WAVE141_1.wav",revision:"e6b661515829712630bbead41d86ee8d"},{url:"resources/assets/sounds/WAVE142_1.wav",revision:"918c03522e79304ad8bb8891c35f58a3"},{url:"resources/assets/sounds/WAVE143_1.wav",revision:"eb2ac1cb1900cd970cdd86be87ebea11"},{url:"resources/assets/sounds/WAVE144_1.wav",revision:"6b16d233bc68aea2a7d071eee85da431"},{url:"resources/assets/sounds/WAVE145_1.wav",revision:"85da47de3575fbedaef71188fe4fc05f"},{url:"resources/assets/sounds/WAVE146_1.wav",revision:"9976daa90c7fd3f7008cf30e7cda8825"},{url:"resources/assets/sounds/bgm.mp3",revision:"029ae684624b50612c09a255264b2d93"},{url:"resources/style.css",revision:"9243735970a4dd56f1b6ea2297612c68"},{url:"runtime.bundle.js",revision:"5515a84be76013d8df230538de8a73bc"},{url:"zh/index.html",revision:"cca881dee46987e0fca1320f69cebc65"},{url:"zh/manifest.json",revision:"bd6076c6691c90bfda46149789420061"},{url:"zh/update-history/index.html",revision:"72f77973d4c583f26c63a6678fa4c4bf"}],{}),e.cleanupOutdatedCaches()})); +if(!self.define){let e,s={};const r=(r,i)=>(r=new URL(r+".js",i).href,s[r]||new Promise((s=>{if("document"in self){const e=document.createElement("script");e.src=r,e.onload=s,document.head.appendChild(e)}else e=r,importScripts(r),s()})).then((()=>{let e=s[r];if(!e)throw new Error(`Module ${r} didn’t register its module`);return e})));self.define=(i,d)=>{const a=e||("document"in self?document.currentScript.src:"")||location.href;if(s[a])return;let c={};const o=e=>r(e,a),n={module:{uri:a},exports:c,require:o};s[a]=Promise.all(i.map((e=>n[e]||o(e)))).then((e=>(d(...e),c)))}}define(["./workbox-d5348a15"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.precacheAndRoute([{url:"407.bundle.js",revision:"1bee7c3e4f681d79778458d562f32fdb"},{url:"407.bundle.js.LICENSE.txt",revision:"5c018e230a018b5417ea6d77f6db7997"},{url:"dark_color_scheme.bundle.js",revision:"15fd2ff5720636254dd3bff5cd6ab7c4"},{url:"en/index.html",revision:"73d53cf8902a7dc8bb18379429f15e54"},{url:"en/manifest.json",revision:"9c2fba642fff247e04697110fcc58ff9"},{url:"en/update-history/index.html",revision:"bea1c2c31f98ef4eb330652620bcaaef"},{url:"index.html",revision:"97623352ef3b2b2572bfa2108aeabdfe"},{url:"is_embedded_in_other_website.bundle.js",revision:"ed9756eafdc0b1ae07d5457b20c2c84e"},{url:"ko.bundle.js",revision:"85b7983e86676f7e9e59a1ad52034a2b"},{url:"ko/index.html",revision:"1e8f3facc13c49fd930b02739e75cee4"},{url:"ko/manifest.json",revision:"20e0d1683d218b21f80574bc139aeb81"},{url:"ko/update-history/index.html",revision:"c6e62362ae9c9cda053d3dde3e38e983"},{url:"main.bundle.js",revision:"69b2ba9b0cb43b71dcc726e3b1c26afb"},{url:"resources/assets/images/IDI_PIKAICON-0.png",revision:"818a5aabfd92f99c7d1f98b8361d3c7f"},{url:"resources/assets/images/IDI_PIKAICON-1_gap_filled.png",revision:"f3f21ca643c4ff5e692b8de485ae8004"},{url:"resources/assets/images/IDI_PIKAICON-1_gap_filled_192.png",revision:"dac21c95f585cb036ad61246d3d722b2"},{url:"resources/assets/images/IDI_PIKAICON-1_gap_filled_512.png",revision:"6cbcbdfef391a347ba1643574bd7ed1b"},{url:"resources/assets/images/controls.png",revision:"5275b91d01abe46c45f43fe59c95d170"},{url:"resources/assets/images/controls_ko.png",revision:"c5c52fd2313b63d024ad06060609c84f"},{url:"resources/assets/images/screenshot.png",revision:"3867bffd4bef3786694f9ebeb77d4d1d"},{url:"resources/assets/images/sprite_sheet.json",revision:"5b62092ca5b40d420e906629b647c919"},{url:"resources/assets/images/sprite_sheet.png",revision:"4fc3712243966195534ee80e1ca81364"},{url:"resources/assets/sounds/WAVE140_1.wav",revision:"a31e486f9bf2dfa2548a4208d78edc1f"},{url:"resources/assets/sounds/WAVE141_1.wav",revision:"e6b661515829712630bbead41d86ee8d"},{url:"resources/assets/sounds/WAVE142_1.wav",revision:"918c03522e79304ad8bb8891c35f58a3"},{url:"resources/assets/sounds/WAVE143_1.wav",revision:"eb2ac1cb1900cd970cdd86be87ebea11"},{url:"resources/assets/sounds/WAVE144_1.wav",revision:"6b16d233bc68aea2a7d071eee85da431"},{url:"resources/assets/sounds/WAVE145_1.wav",revision:"85da47de3575fbedaef71188fe4fc05f"},{url:"resources/assets/sounds/WAVE146_1.wav",revision:"9976daa90c7fd3f7008cf30e7cda8825"},{url:"resources/assets/sounds/bgm.mp3",revision:"029ae684624b50612c09a255264b2d93"},{url:"resources/style.css",revision:"9243735970a4dd56f1b6ea2297612c68"},{url:"runtime.bundle.js",revision:"5515a84be76013d8df230538de8a73bc"},{url:"zh/index.html",revision:"cca881dee46987e0fca1320f69cebc65"},{url:"zh/manifest.json",revision:"bd6076c6691c90bfda46149789420061"},{url:"zh/update-history/index.html",revision:"72f77973d4c583f26c63a6678fa4c4bf"}],{}),e.cleanupOutdatedCaches()})); //# sourceMappingURL=sw.js.map diff --git a/sw.js.map b/sw.js.map index 249413a..799f3cf 100644 --- a/sw.js.map +++ b/sw.js.map @@ -1 +1 @@ -{"version":3,"file":"sw.js","sources":["../../../../../private/var/folders/cg/kth39qgn39sd9nwkpkpx3kz40000gn/T/13712ca651b2bcee40362e78cef502e7/sw.js"],"sourcesContent":["import {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/Users/kyutae/develop/Pikachu_Volleyball/pikachu-volleyball/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/Users/kyutae/develop/Pikachu_Volleyball/pikachu-volleyball/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.addEventListener('message', (event) => {\n if (event.data && event.data.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\n\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"407.bundle.js\",\n \"revision\": \"1bee7c3e4f681d79778458d562f32fdb\"\n },\n {\n \"url\": \"407.bundle.js.LICENSE.txt\",\n \"revision\": \"5c018e230a018b5417ea6d77f6db7997\"\n },\n {\n \"url\": \"dark_color_scheme.bundle.js\",\n \"revision\": \"15fd2ff5720636254dd3bff5cd6ab7c4\"\n },\n {\n \"url\": \"en/index.html\",\n \"revision\": \"73d53cf8902a7dc8bb18379429f15e54\"\n },\n {\n \"url\": \"en/manifest.json\",\n \"revision\": \"9c2fba642fff247e04697110fcc58ff9\"\n },\n {\n \"url\": \"en/update-history/index.html\",\n \"revision\": \"bea1c2c31f98ef4eb330652620bcaaef\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"97623352ef3b2b2572bfa2108aeabdfe\"\n },\n {\n \"url\": \"is_embedded_in_other_website.bundle.js\",\n \"revision\": \"ed9756eafdc0b1ae07d5457b20c2c84e\"\n },\n {\n \"url\": \"ko.bundle.js\",\n \"revision\": \"85b7983e86676f7e9e59a1ad52034a2b\"\n },\n {\n \"url\": \"ko/index.html\",\n \"revision\": \"1e8f3facc13c49fd930b02739e75cee4\"\n },\n {\n \"url\": \"ko/manifest.json\",\n \"revision\": \"20e0d1683d218b21f80574bc139aeb81\"\n },\n {\n \"url\": \"ko/update-history/index.html\",\n \"revision\": \"c6e62362ae9c9cda053d3dde3e38e983\"\n },\n {\n \"url\": \"main.bundle.js\",\n \"revision\": \"d85a3ed5d26b9c0c12b8ccee94ac61e2\"\n },\n {\n \"url\": \"resources/assets/images/IDI_PIKAICON-0.png\",\n \"revision\": \"818a5aabfd92f99c7d1f98b8361d3c7f\"\n },\n {\n \"url\": \"resources/assets/images/IDI_PIKAICON-1_gap_filled.png\",\n \"revision\": \"f3f21ca643c4ff5e692b8de485ae8004\"\n },\n {\n \"url\": \"resources/assets/images/IDI_PIKAICON-1_gap_filled_192.png\",\n \"revision\": \"dac21c95f585cb036ad61246d3d722b2\"\n },\n {\n \"url\": \"resources/assets/images/IDI_PIKAICON-1_gap_filled_512.png\",\n \"revision\": \"6cbcbdfef391a347ba1643574bd7ed1b\"\n },\n {\n \"url\": \"resources/assets/images/controls.png\",\n \"revision\": \"5275b91d01abe46c45f43fe59c95d170\"\n },\n {\n \"url\": \"resources/assets/images/controls_ko.png\",\n \"revision\": \"c5c52fd2313b63d024ad06060609c84f\"\n },\n {\n \"url\": \"resources/assets/images/screenshot.png\",\n \"revision\": \"3867bffd4bef3786694f9ebeb77d4d1d\"\n },\n {\n \"url\": \"resources/assets/images/sprite_sheet.json\",\n \"revision\": \"5b62092ca5b40d420e906629b647c919\"\n },\n {\n \"url\": \"resources/assets/images/sprite_sheet.png\",\n \"revision\": \"4fc3712243966195534ee80e1ca81364\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE140_1.wav\",\n \"revision\": \"a31e486f9bf2dfa2548a4208d78edc1f\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE141_1.wav\",\n \"revision\": \"e6b661515829712630bbead41d86ee8d\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE142_1.wav\",\n \"revision\": \"918c03522e79304ad8bb8891c35f58a3\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE143_1.wav\",\n \"revision\": \"eb2ac1cb1900cd970cdd86be87ebea11\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE144_1.wav\",\n \"revision\": \"6b16d233bc68aea2a7d071eee85da431\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE145_1.wav\",\n \"revision\": \"85da47de3575fbedaef71188fe4fc05f\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE146_1.wav\",\n \"revision\": \"9976daa90c7fd3f7008cf30e7cda8825\"\n },\n {\n \"url\": \"resources/assets/sounds/bgm.mp3\",\n \"revision\": \"029ae684624b50612c09a255264b2d93\"\n },\n {\n \"url\": \"resources/style.css\",\n \"revision\": \"9243735970a4dd56f1b6ea2297612c68\"\n },\n {\n \"url\": \"runtime.bundle.js\",\n \"revision\": \"5515a84be76013d8df230538de8a73bc\"\n },\n {\n \"url\": \"zh/index.html\",\n \"revision\": \"cca881dee46987e0fca1320f69cebc65\"\n },\n {\n \"url\": \"zh/manifest.json\",\n \"revision\": \"bd6076c6691c90bfda46149789420061\"\n },\n {\n \"url\": \"zh/update-history/index.html\",\n \"revision\": \"72f77973d4c583f26c63a6678fa4c4bf\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();\n\n\n\n\n\n\n\n"],"names":["self","addEventListener","event","data","type","skipWaiting","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches"],"mappings":"0nBAoBAA,KAAKC,iBAAiB,WAAYC,IAC5BA,EAAMC,MAA4B,iBAApBD,EAAMC,KAAKC,MAC3BJ,KAAKK,aACN,IAWHC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,wDACPC,SAAY,oCAEd,CACED,IAAO,4DACPC,SAAY,oCAEd,CACED,IAAO,4DACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,oBACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,qCAEb,CA7IgC,GA8InCC,EAAAA"} \ No newline at end of file +{"version":3,"file":"sw.js","sources":["../../../../../private/var/folders/cg/kth39qgn39sd9nwkpkpx3kz40000gn/T/f264fa66d5f67bfce0c81a8011c331da/sw.js"],"sourcesContent":["import {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/Users/kyutae/develop/Pikachu_Volleyball/pikachu-volleyball/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/Users/kyutae/develop/Pikachu_Volleyball/pikachu-volleyball/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.addEventListener('message', (event) => {\n if (event.data && event.data.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\n\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"407.bundle.js\",\n \"revision\": \"1bee7c3e4f681d79778458d562f32fdb\"\n },\n {\n \"url\": \"407.bundle.js.LICENSE.txt\",\n \"revision\": \"5c018e230a018b5417ea6d77f6db7997\"\n },\n {\n \"url\": \"dark_color_scheme.bundle.js\",\n \"revision\": \"15fd2ff5720636254dd3bff5cd6ab7c4\"\n },\n {\n \"url\": \"en/index.html\",\n \"revision\": \"73d53cf8902a7dc8bb18379429f15e54\"\n },\n {\n \"url\": \"en/manifest.json\",\n \"revision\": \"9c2fba642fff247e04697110fcc58ff9\"\n },\n {\n \"url\": \"en/update-history/index.html\",\n \"revision\": \"bea1c2c31f98ef4eb330652620bcaaef\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"97623352ef3b2b2572bfa2108aeabdfe\"\n },\n {\n \"url\": \"is_embedded_in_other_website.bundle.js\",\n \"revision\": \"ed9756eafdc0b1ae07d5457b20c2c84e\"\n },\n {\n \"url\": \"ko.bundle.js\",\n \"revision\": \"85b7983e86676f7e9e59a1ad52034a2b\"\n },\n {\n \"url\": \"ko/index.html\",\n \"revision\": \"1e8f3facc13c49fd930b02739e75cee4\"\n },\n {\n \"url\": \"ko/manifest.json\",\n \"revision\": \"20e0d1683d218b21f80574bc139aeb81\"\n },\n {\n \"url\": \"ko/update-history/index.html\",\n \"revision\": \"c6e62362ae9c9cda053d3dde3e38e983\"\n },\n {\n \"url\": \"main.bundle.js\",\n \"revision\": \"69b2ba9b0cb43b71dcc726e3b1c26afb\"\n },\n {\n \"url\": \"resources/assets/images/IDI_PIKAICON-0.png\",\n \"revision\": \"818a5aabfd92f99c7d1f98b8361d3c7f\"\n },\n {\n \"url\": \"resources/assets/images/IDI_PIKAICON-1_gap_filled.png\",\n \"revision\": \"f3f21ca643c4ff5e692b8de485ae8004\"\n },\n {\n \"url\": \"resources/assets/images/IDI_PIKAICON-1_gap_filled_192.png\",\n \"revision\": \"dac21c95f585cb036ad61246d3d722b2\"\n },\n {\n \"url\": \"resources/assets/images/IDI_PIKAICON-1_gap_filled_512.png\",\n \"revision\": \"6cbcbdfef391a347ba1643574bd7ed1b\"\n },\n {\n \"url\": \"resources/assets/images/controls.png\",\n \"revision\": \"5275b91d01abe46c45f43fe59c95d170\"\n },\n {\n \"url\": \"resources/assets/images/controls_ko.png\",\n \"revision\": \"c5c52fd2313b63d024ad06060609c84f\"\n },\n {\n \"url\": \"resources/assets/images/screenshot.png\",\n \"revision\": \"3867bffd4bef3786694f9ebeb77d4d1d\"\n },\n {\n \"url\": \"resources/assets/images/sprite_sheet.json\",\n \"revision\": \"5b62092ca5b40d420e906629b647c919\"\n },\n {\n \"url\": \"resources/assets/images/sprite_sheet.png\",\n \"revision\": \"4fc3712243966195534ee80e1ca81364\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE140_1.wav\",\n \"revision\": \"a31e486f9bf2dfa2548a4208d78edc1f\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE141_1.wav\",\n \"revision\": \"e6b661515829712630bbead41d86ee8d\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE142_1.wav\",\n \"revision\": \"918c03522e79304ad8bb8891c35f58a3\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE143_1.wav\",\n \"revision\": \"eb2ac1cb1900cd970cdd86be87ebea11\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE144_1.wav\",\n \"revision\": \"6b16d233bc68aea2a7d071eee85da431\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE145_1.wav\",\n \"revision\": \"85da47de3575fbedaef71188fe4fc05f\"\n },\n {\n \"url\": \"resources/assets/sounds/WAVE146_1.wav\",\n \"revision\": \"9976daa90c7fd3f7008cf30e7cda8825\"\n },\n {\n \"url\": \"resources/assets/sounds/bgm.mp3\",\n \"revision\": \"029ae684624b50612c09a255264b2d93\"\n },\n {\n \"url\": \"resources/style.css\",\n \"revision\": \"9243735970a4dd56f1b6ea2297612c68\"\n },\n {\n \"url\": \"runtime.bundle.js\",\n \"revision\": \"5515a84be76013d8df230538de8a73bc\"\n },\n {\n \"url\": \"zh/index.html\",\n \"revision\": \"cca881dee46987e0fca1320f69cebc65\"\n },\n {\n \"url\": \"zh/manifest.json\",\n \"revision\": \"bd6076c6691c90bfda46149789420061\"\n },\n {\n \"url\": \"zh/update-history/index.html\",\n \"revision\": \"72f77973d4c583f26c63a6678fa4c4bf\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();\n\n\n\n\n\n\n\n"],"names":["self","addEventListener","event","data","type","skipWaiting","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches"],"mappings":"0nBAoBAA,KAAKC,iBAAiB,WAAYC,IAC5BA,EAAMC,MAA4B,iBAApBD,EAAMC,KAAKC,MAC3BJ,KAAKK,aACN,IAWHC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,4BACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,oCAEd,CACED,IAAO,wDACPC,SAAY,oCAEd,CACED,IAAO,4DACPC,SAAY,oCAEd,CACED,IAAO,4DACPC,SAAY,oCAEd,CACED,IAAO,uCACPC,SAAY,oCAEd,CACED,IAAO,0CACPC,SAAY,oCAEd,CACED,IAAO,yCACPC,SAAY,oCAEd,CACED,IAAO,4CACPC,SAAY,oCAEd,CACED,IAAO,2CACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,wCACPC,SAAY,oCAEd,CACED,IAAO,kCACPC,SAAY,oCAEd,CACED,IAAO,sBACPC,SAAY,oCAEd,CACED,IAAO,oBACPC,SAAY,oCAEd,CACED,IAAO,gBACPC,SAAY,oCAEd,CACED,IAAO,mBACPC,SAAY,oCAEd,CACED,IAAO,+BACPC,SAAY,qCAEb,CA7IgC,GA8InCC,EAAAA"} \ No newline at end of file