/g,_=/>/g,m=RegExp(`>|${d}(?:([^\\s"'>=/]+)(${d}*=${d}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),p=/'/g,g=/"/g,$=/^(?:script|style|textarea|title)$/i,y=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),x=y(1),T=Symbol.for("lit-noChange"),E=Symbol.for("lit-nothing"),A=new WeakMap,C=r$1.createTreeWalker(r$1,129);function P(t,i){if(!a(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==s$2?s$2.createHTML(i):i}const V=(t,i)=>{const s=t.length-1,o=[];let r,l=2===i?"":3===i?"":"",c=f$2;for(let i=0;i"===u[0]?(c=r??f$2,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?m:'"'===u[3]?g:p):c===g||c===p?c=m:c===v||c===_?c=f$2:(c=m,r=void 0);const x=c===m&&t[i+1].startsWith("/>")?" ":"";l+=c===f$2?s+n$1:d>=0?(o.push(a),s.slice(0,d)+e$1+s.slice(d)+h$1+x):s+h$1+(-2===d?i:x)}return[P(t,l+(t[s]||"")+(2===i?"":3===i?"":"")),o]};class N{constructor({strings:t,_$litType$:s},n){let r;this.parts=[];let c=0,a=0;const u=t.length-1,d=this.parts,[f,v]=V(t,s);if(this.el=N.createElement(f,n),C.currentNode=this.el.content,2===s||3===s){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(r=C.nextNode())&&d.length0){r.textContent=i$2?i$2.emptyScript:"";for(let i=0;i2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=E}_$AI(t,i=this,s,e){const h=this.strings;let o=!1;if(void 0===h)t=S(this,t,i,0),o=!c$1(t)||t!==this._$AH&&t!==T,o&&(this._$AH=t);else{const e=t;let n,r;for(t=h[0],n=0;n{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new R(i.insertBefore(l(),t),t,void 0,s??{})}return h._$AI(t),h /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */};const s$1=globalThis;let i$1=class i extends y$1{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const r=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=B(r,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return T}};i$1._$litElement$=!0,i$1["finalized"]=!0,s$1.litElementHydrateSupport?.({LitElement:i$1});const o$1=s$1.litElementPolyfillSupport;o$1?.({LitElement:i$1});(s$1.litElementVersions??=[]).push("4.2.0"); // Copyright 2023 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. const HIDDEN_CLASS="hidden"; // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. const IS_IOS=/CriOS/.test(window.navigator.userAgent);const IS_HIDPI=window.devicePixelRatio>1;const IS_MOBILE=/Android/.test(window.navigator.userAgent)||IS_IOS;const IS_RTL=document.documentElement.dir==="rtl";const FPS=60; // Copyright 2025 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. function getRandomNum(min,max){return Math.floor(Math.random()*(max-min+1))+min}function getTimeStamp(){return IS_IOS?(new Date).getTime():performance.now()}function getRunnerImageSprite(){if("imageSprite"in Runner){return Runner.imageSprite}return null}function getRunnerAltGameImageSprite(){if("altGameImageSprite"in Runner){return Runner.altGameImageSprite}return null}function getRunnerAltCommonImageSprite(){if("altCommonImageSprite"in Runner){return Runner.altCommonImageSprite}return null}function getRunnerOrigImageSprite(){if("origImageSprite"in Runner){return Runner.origImageSprite}return null}function getRunnerSlowdown(){if("slowDown"in Runner&&typeof Runner.slowDown==="boolean"){return Runner.slowDown}return null}function getRunnerAudioCues(){if("audioCues"in Runner&&typeof Runner.audioCues==="boolean"){return Runner.audioCues}return null}function getRunnerSpriteDefinition(){if("spriteDefinition"in Runner){return Runner.spriteDefinition}return null}function getRunnerDefaultDimensions(){if("defaultDimensions"in Runner){return Runner.defaultDimensions}return null}function getRunnerConfigValue(key){if("config"in Runner&&Runner.config&&key in Runner.config){return Runner.config[key]}return null}function getRunnerGeneratedSoundFx(){if("generatedSoundFx"in Runner){return Runner.generatedSoundFx}return null} // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var Dimensions;(function(Dimensions){Dimensions[Dimensions["WIDTH"]=10]="WIDTH";Dimensions[Dimensions["HEIGHT"]=13]="HEIGHT";Dimensions[Dimensions["DEST_WIDTH"]=11]="DEST_WIDTH"})(Dimensions||(Dimensions={}));var Config$2;(function(Config){Config[Config["MAX_DISTANCE_UNITS"]=5]="MAX_DISTANCE_UNITS";Config[Config["ACHIEVEMENT_DISTANCE"]=100]="ACHIEVEMENT_DISTANCE";Config[Config["COEFFICIENT"]=.025]="COEFFICIENT";Config[Config["FLASH_DURATION"]=250]="FLASH_DURATION";Config[Config["FLASH_ITERATIONS"]=3]="FLASH_ITERATIONS";Config[Config["HIGH_SCORE_HIT_AREA_PADDING"]=4]="HIGH_SCORE_HIT_AREA_PADDING"})(Config$2||(Config$2={}));class DistanceMeter{achievement=false;canvas;canvasCtx;image;spritePos;x=0;y=5;maxScore=0;highScore="0";digits=[];defaultString="";flashTimer=0;flashIterations=0;flashingRafId=null;highScoreBounds=null;highScoreFlashing=false;maxScoreUnits=Config$2.MAX_DISTANCE_UNITS;canvasWidth;frameTimeStamp;constructor(canvas,spritePos,canvasWidth){this.canvas=canvas;const canvasContext=canvas.getContext("2d");assert(canvasContext);this.canvasCtx=canvasContext;const runnerImageSprite=getRunnerImageSprite();assert(runnerImageSprite);this.image=runnerImageSprite;this.spritePos=spritePos;this.canvasWidth=canvasWidth;this.init(canvasWidth)}init(width){let maxDistanceStr="";this.calcXpos(width);this.maxScore=this.maxScoreUnits;for(let i=0;ithis.maxScore&&this.maxScoreUnits===Config$2.MAX_DISTANCE_UNITS){this.maxScoreUnits++;this.maxScore=parseInt(this.maxScore+"9",10)}if(distance>0){if(distance%Config$2.ACHIEVEMENT_DISTANCE===0){this.achievement=true;this.flashTimer=0;playSound=true}const distanceStr=(this.defaultString+distance).substr(-this.maxScoreUnits);this.digits=distanceStr.split("")}else{this.digits=this.defaultString.split("")}}else{if(this.flashIterations<=Config$2.FLASH_ITERATIONS){this.flashTimer+=deltaTime;if(this.flashTimerConfig$2.FLASH_DURATION*2){this.flashTimer=0;this.flashIterations++}}else{this.achievement=false;this.flashIterations=0;this.flashTimer=0}}if(paint){for(let i=this.digits.length-1;i>=0;i--){this.draw(i,parseInt(this.digits[i],10))}}this.drawHighScore();return playSound}drawHighScore(){if(this.highScore.length>0){this.canvasCtx.save();this.canvasCtx.globalAlpha=.8;for(let i=this.highScore.length-1;i>=0;i--){const characterToDraw=this.highScore[i];let characterSpritePosition=parseInt(characterToDraw,10);if(isNaN(characterSpritePosition)){switch(characterToDraw){case"H":characterSpritePosition=10;break;case"I":characterSpritePosition=11;break;default:continue}}this.draw(i,characterSpritePosition,true)}this.canvasCtx.restore()}}setHighScore(distance){distance=this.getActualDistance(distance);const highScoreStr=(this.defaultString+distance).substr(-this.maxScoreUnits);this.highScore="HI "+highScoreStr}hasClickedOnHighScore(e){let x=0;let y=0;if(e instanceof TouchEvent){const canvasBounds=this.canvas.getBoundingClientRect();x=e.touches[0].clientX-canvasBounds.left;y=e.touches[0].clientY-canvasBounds.top}else{x=e.offsetX;y=e.offsetY}this.highScoreBounds=this.getHighScoreBounds();return x>=this.highScoreBounds.x&&x<=this.highScoreBounds.x+this.highScoreBounds.width&&y>=this.highScoreBounds.y&&y<=this.highScoreBounds.y+this.highScoreBounds.height}getHighScoreBounds(){return{x:this.x-this.maxScoreUnits*2*Dimensions.WIDTH-Config$2.HIGH_SCORE_HIT_AREA_PADDING,y:this.y,width:Dimensions.WIDTH*(this.highScore.length+1)+Config$2.HIGH_SCORE_HIT_AREA_PADDING,height:Dimensions.HEIGHT+Config$2.HIGH_SCORE_HIT_AREA_PADDING*2}}flashHighScore(){const now=getTimeStamp();const deltaTime=now-(this.frameTimeStamp||now);let paint=true;this.frameTimeStamp=now;if(this.flashIterations>Config$2.FLASH_ITERATIONS*2){this.cancelHighScoreFlashing();return}this.flashTimer+=deltaTime;if(this.flashTimerConfig$2.FLASH_DURATION*2){this.flashTimer=0;this.flashIterations++}if(paint){this.drawHighScore()}else{this.clearHighScoreBounds()}this.flashingRafId=requestAnimationFrame(this.flashHighScore.bind(this))}clearHighScoreBounds(){assert(this.highScoreBounds);this.canvasCtx.save();this.canvasCtx.fillStyle="#fff";this.canvasCtx.rect(this.highScoreBounds.x,this.highScoreBounds.y,this.highScoreBounds.width,this.highScoreBounds.height);this.canvasCtx.fill();this.canvasCtx.restore()}startHighScoreFlashing(){this.highScoreFlashing=true;this.flashHighScore()}isHighScoreFlashing(){return this.highScoreFlashing}cancelHighScoreFlashing(){if(this.flashingRafId){cancelAnimationFrame(this.flashingRafId)}this.flashIterations=0;this.flashTimer=0;this.highScoreFlashing=false;this.clearHighScoreBounds();this.drawHighScore()}resetHighScore(){this.setHighScore(0);this.cancelHighScoreFlashing()}reset(){this.update(0,0);this.achievement=false}} // Copyright 2021 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. const GAME_TYPE=[];class CollisionBox{x;y;width;height;constructor(x,y,width,height){this.x=x;this.y=y;this.width=width;this.height=height}}const spriteDefinitionByType={original:{ldpi:{backgroundEl:{x:86,y:2},cactusLarge:{x:332,y:2},cactusSmall:{x:228,y:2},obstacle2:{x:332,y:2},obstacle:{x:228,y:2},cloud:{x:86,y:2},horizon:{x:2,y:54},moon:{x:484,y:2},pterodactyl:{x:134,y:2},restart:{x:2,y:68},textSprite:{x:655,y:2},tRex:{x:848,y:2},star:{x:645,y:2},collectable:{x:0,y:0},altGameEnd:{x:32,y:0}},hdpi:{backgroundEl:{x:166,y:2},cactusLarge:{x:652,y:2},cactusSmall:{x:446,y:2},obstacle2:{x:652,y:2},obstacle:{x:446,y:2},cloud:{x:166,y:2},horizon:{x:2,y:104},moon:{x:954,y:2},pterodactyl:{x:260,y:2},restart:{x:2,y:130},textSprite:{x:1294,y:2},tRex:{x:1678,y:2},star:{x:1276,y:2},collectable:{x:0,y:0},altGameEnd:{x:64,y:0}},maxGapCoefficient:1.5,maxObstacleLength:3,hasClouds:true,bottomPad:10,obstacles:[{type:"cactusSmall",width:17,height:35,yPos:105,multipleSpeed:4,minGap:120,minSpeed:0,collisionBoxes:[{x:0,y:7,width:5,height:27},{x:4,y:0,width:6,height:34},{x:10,y:4,width:7,height:14}]},{type:"cactusLarge",width:25,height:50,yPos:90,multipleSpeed:7,minGap:120,minSpeed:0,collisionBoxes:[{x:0,y:12,width:7,height:38},{x:8,y:0,width:7,height:49},{x:13,y:10,width:10,height:38}]},{type:"pterodactyl",width:46,height:40,yPos:[100,75,50],yPosMobile:[100,50],multipleSpeed:999,minSpeed:8.5,minGap:150,collisionBoxes:[{x:15,y:15,width:16,height:5},{x:18,y:21,width:24,height:6},{x:2,y:14,width:4,height:3},{x:6,y:10,width:4,height:7},{x:10,y:8,width:6,height:9}],numFrames:2,frameRate:1e3/6,speedOffset:.8},{type:"collectable",width:31,height:24,yPos:104,multipleSpeed:1e3,minGap:9999,minSpeed:0,collisionBoxes:[{x:0,y:0,width:32,height:25}]}],backgroundEl:{CLOUD:{height:14,offset:4,width:46,xPos:1,fixed:false}},backgroundElConfig:{maxBgEls:1,maxGap:400,minGap:100,pos:0,speed:.5,yPos:125},lines:[{sourceX:2,sourceY:52,width:600,height:12,yPos:127}],altGameOverTextConfig:{textX:32,textY:0,textWidth:246,textHeight:17,flashDuration:1500,flashing:false}}}; // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. const RESTART_ANIM_DURATION=875;const LOGO_PAUSE_DURATION=875;const FLASH_ITERATIONS=5;const animConfig={frames:[0,36,72,108,144,180,216,252],msPerFrame:RESTART_ANIM_DURATION/8};const defaultPanelDimensions={textX:0,textY:13,textWidth:191,textHeight:11,restartWidth:36,restartHeight:32};class GameOverPanel{canvasCtx;canvasDimensions;textImgPos;restartImgPos;altGameEndImgPos;altGameModeActive;frameTimeStamp=0;animTimer=0;currentFrame=0;gameOverRafId=null;flashTimer=0;flashCounter=0;originalText=true;constructor(canvas,textImgPos,restartImgPos,dimensions,altGameEndImgPos,altGameActive){const canvasContext=canvas.getContext("2d");assert(canvasContext);this.canvasCtx=canvasContext;this.canvasDimensions=dimensions;this.textImgPos=textImgPos;this.restartImgPos=restartImgPos;this.altGameEndImgPos=altGameEndImgPos??null;this.altGameModeActive=altGameActive??false}updateDimensions(width,height){this.canvasDimensions.width=width;if(height){this.canvasDimensions.height=height}this.currentFrame=animConfig.frames.length-1}drawGameOverText(dimensions,useAltText){const centerX=this.canvasDimensions.width/2;let textSourceX=dimensions.textX;let textSourceY=dimensions.textY;let textSourceWidth=dimensions.textWidth;let textSourceHeight=dimensions.textHeight;const textTargetX=Math.round(centerX-dimensions.textWidth/2);const textTargetY=Math.round((this.canvasDimensions.height-25)/3);const textTargetWidth=dimensions.textWidth;const textTargetHeight=dimensions.textHeight;if(IS_HIDPI){textSourceY*=2;textSourceX*=2;textSourceWidth*=2;textSourceHeight*=2}if(!useAltText){textSourceX+=this.textImgPos.x;textSourceY+=this.textImgPos.y}const spriteSource=useAltText?getRunnerAltCommonImageSprite():getRunnerOrigImageSprite();assert(spriteSource);this.canvasCtx.save();if(IS_RTL){this.canvasCtx.translate(this.canvasDimensions.width,0);this.canvasCtx.scale(-1,1)}this.canvasCtx.drawImage(spriteSource,textSourceX,textSourceY,textSourceWidth,textSourceHeight,textTargetX,textTargetY,textTargetWidth,textTargetHeight);this.canvasCtx.restore()}drawAltGameElements(tRex){const spriteDefinition=getRunnerSpriteDefinition();assert(spriteDefinition);if(this.altGameModeActive&&spriteDefinition){assert(this.altGameEndImgPos);const altGameEndConfig=spriteDefinition.altGameEndConfig;assert(altGameEndConfig);let altGameEndSourceWidth=altGameEndConfig.width;let altGameEndSourceHeight=altGameEndConfig.height;const altGameEndTargetX=tRex.xPos+altGameEndConfig.xOffset;const altGameEndTargetY=tRex.yPos+altGameEndConfig.yOffset;if(IS_HIDPI){altGameEndSourceWidth*=2;altGameEndSourceHeight*=2}const altCommonImageSprite=getRunnerAltCommonImageSprite();assert(altCommonImageSprite);this.canvasCtx.drawImage(altCommonImageSprite,this.altGameEndImgPos.x,this.altGameEndImgPos.y,altGameEndSourceWidth,altGameEndSourceHeight,altGameEndTargetX,altGameEndTargetY,altGameEndConfig.width,altGameEndConfig.height)}}drawRestartButton(){const dimensions=defaultPanelDimensions;let framePosX=animConfig.frames[this.currentFrame];let restartSourceWidth=dimensions.restartWidth;let restartSourceHeight=dimensions.restartHeight;const restartTargetX=this.canvasDimensions.width/2-dimensions.restartHeight/2;const restartTargetY=this.canvasDimensions.height/2;if(IS_HIDPI){restartSourceWidth*=2;restartSourceHeight*=2;framePosX*=2}this.canvasCtx.save();if(IS_RTL){this.canvasCtx.translate(this.canvasDimensions.width,0);this.canvasCtx.scale(-1,1)}const origImageSprite=getRunnerOrigImageSprite();assert(origImageSprite);this.canvasCtx.drawImage(origImageSprite,this.restartImgPos.x+framePosX,this.restartImgPos.y,restartSourceWidth,restartSourceHeight,restartTargetX,restartTargetY,dimensions.restartWidth,dimensions.restartHeight);this.canvasCtx.restore()}draw(altGameModeActive,tRex){if(altGameModeActive){this.altGameModeActive=altGameModeActive}this.drawGameOverText(defaultPanelDimensions,false);this.drawRestartButton();if(tRex){this.drawAltGameElements(tRex)}this.update()}update(){const now=getTimeStamp();const deltaTime=now-(this.frameTimeStamp||now);this.frameTimeStamp=now;this.animTimer+=deltaTime;this.flashTimer+=deltaTime;if(this.currentFrame===0&&this.animTimer>LOGO_PAUSE_DURATION){this.animTimer=0;this.currentFrame++;this.drawRestartButton()}else if(this.currentFrame>0&&this.currentFrame=animConfig.msPerFrame){this.currentFrame++;this.drawRestartButton()}}else if(!this.altGameModeActive&&this.currentFrame===animConfig.frames.length){this.reset();return}if(this.altGameModeActive&&spriteDefinitionByType.original.altGameOverTextConfig){const altTextConfig=spriteDefinitionByType.original.altGameOverTextConfig;if(altTextConfig.flashing){if(this.flashCounteraltTextConfig.flashDuration){this.flashTimer=0;this.originalText=!this.originalText;this.clearGameOverTextBounds();if(this.originalText){this.drawGameOverText(defaultPanelDimensions,false);this.flashCounter++}else{this.drawGameOverText(altTextConfig,true)}}else if(this.flashCounter>=FLASH_ITERATIONS){this.reset();return}}else{this.clearGameOverTextBounds(altTextConfig);this.drawGameOverText(altTextConfig,true)}}this.gameOverRafId=requestAnimationFrame(this.update.bind(this))}clearGameOverTextBounds(dimensions=defaultPanelDimensions){this.canvasCtx.save();this.canvasCtx.clearRect(Math.round(this.canvasDimensions.width/2-dimensions.textWidth/2),Math.round((this.canvasDimensions.height-25)/3),dimensions.textWidth,dimensions.textHeight+4);this.canvasCtx.restore()}reset(){if(this.gameOverRafId){cancelAnimationFrame(this.gameOverRafId);this.gameOverRafId=null}this.animTimer=0;this.frameTimeStamp=0;this.currentFrame=0;this.flashTimer=0;this.flashCounter=0;this.originalText=true}} // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. class GeneratedSoundFx{constructor(){this.context=new AudioContext;if(IS_IOS){this.context.onstatechange=()=>{if(this.context.state!=="running"){this.context.resume()}};this.context.resume()}this.panner=this.context.createStereoPanner?this.context.createStereoPanner():null}context;panner=null;bgSoundIntervalId=null;stopAll(){this.cancelFootSteps()}playNote(frequency,startTime,duration,vol=.01,pan=0){const osc1=this.context.createOscillator();const osc2=this.context.createOscillator();const volume=this.context.createGain();osc1.type="triangle";osc2.type="triangle";volume.gain.value=.1;if(this.panner){this.panner.pan.value=pan;osc1.connect(volume).connect(this.panner);osc2.connect(volume).connect(this.panner);this.panner.connect(this.context.destination)}else{osc1.connect(volume);osc2.connect(volume);volume.connect(this.context.destination)}osc1.frequency.value=frequency+1;osc2.frequency.value=frequency-2;volume.gain.setValueAtTime(vol,startTime+duration-.05);volume.gain.linearRampToValueAtTime(1e-5,startTime+duration);osc1.start(startTime);osc2.start(startTime);osc1.stop(startTime+duration);osc2.stop(startTime+duration)}background(){const now=this.context.currentTime;this.playNote(493.883,now,.116);this.playNote(659.255,now+.116,.232);this.loopFootSteps()}loopFootSteps(){if(!this.bgSoundIntervalId){this.bgSoundIntervalId=setInterval((()=>{this.playNote(73.42,this.context.currentTime,.05,.16);this.playNote(69.3,this.context.currentTime+.116,.116,.16)}),280)}}cancelFootSteps(){if(this.bgSoundIntervalId){clearInterval(this.bgSoundIntervalId);this.bgSoundIntervalId=null;this.playNote(103.83,this.context.currentTime,.232,.02);this.playNote(116.54,this.context.currentTime+.116,.232,.02)}}collect(){this.cancelFootSteps();const now=this.context.currentTime;this.playNote(830.61,now,.116);this.playNote(1318.51,now+.116,.232)}jump(){const now=this.context.currentTime;this.playNote(659.25,now,.116,.3,-.6);this.playNote(880,now+.116,.232,.3,-.6)}} // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. function getSpriteConfigForType(type){if("spriteDefinition"in Runner){const spriteDefinition=Runner.spriteDefinition;if(spriteDefinition){if(spriteDefinition.backgroundEl[type]){return spriteDefinition.backgroundEl[type]}}}return null}let globalConfig={maxBgEls:0,maxGap:0,minGap:0,msPerFrame:0,pos:0,speed:0,yPos:0};function getGlobalConfig(){return globalConfig}function setGlobalConfig(config){globalConfig=config}class BackgroundEl{gap;xPos;canvas;canvasCtx;spritePos;yPos=0;remove=false;type;animTimer=0;spriteConfig;switchFrames=false;constructor(canvas,spritePos,containerWidth,type){this.canvas=canvas;const canvasContext=this.canvas.getContext("2d");assert(canvasContext);this.canvasCtx=canvasContext;this.spritePos=spritePos;this.xPos=containerWidth;this.type=type;this.gap=getRandomNum(getGlobalConfig().minGap,getGlobalConfig().maxGap);const spriteConfig=getSpriteConfigForType(this.type);assert(spriteConfig);this.spriteConfig=spriteConfig;this.init()}init(){if(this.spriteConfig.fixed){assert(this.spriteConfig.fixedXPos);this.xPos=this.spriteConfig.fixedXPos}this.yPos=getGlobalConfig().yPos-this.spriteConfig.height+this.spriteConfig.offset;this.draw()}draw(){this.canvasCtx.save();let sourceWidth=this.spriteConfig.width;let sourceHeight=this.spriteConfig.height;let sourceX=this.spriteConfig.xPos;const outputWidth=sourceWidth;const outputHeight=sourceHeight;const imageSprite=getRunnerImageSprite();assert(imageSprite);if(IS_HIDPI){sourceWidth*=2;sourceHeight*=2;sourceX*=2}this.canvasCtx.drawImage(imageSprite,sourceX,this.spritePos.y,sourceWidth,sourceHeight,this.xPos,this.yPos,outputWidth,outputHeight);this.canvasCtx.restore()}update(speed){if(!this.remove){if(this.spriteConfig.fixed){const globalConfig=getGlobalConfig();assert(globalConfig.msPerFrame);this.animTimer+=speed;if(this.animTimer>globalConfig.msPerFrame){this.animTimer=0;this.switchFrames=!this.switchFrames}if(this.spriteConfig.fixedYPos1&&this.spriteConfig.fixedYPos2){this.yPos=this.switchFrames?this.spriteConfig.fixedYPos1:this.spriteConfig.fixedYPos2}}else{this.xPos-=getGlobalConfig().speed}this.draw();if(!this.isVisible()){this.remove=true}}}isVisible(){return this.xPos+this.spriteConfig.width>0}} // Copyright 2025 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. class Cloud{xPos;yPos=0;canvasCtx;remove=false;spritePos;constructor(canvas,spritePos,containerWidth){const canvasContext=canvas.getContext("2d");assert(canvasContext);this.canvasCtx=canvasContext;this.xPos=containerWidth;this.spritePos=spritePos;this.init()}init(){this.yPos=getRandomNum(Config$1.MAX_SKY_LEVEL,Config$1.MIN_SKY_LEVEL);this.draw()}draw(){const runnerImageSprite=getRunnerImageSprite();assert(runnerImageSprite);this.canvasCtx.save();let sourceWidth=Config$1.WIDTH;let sourceHeight=Config$1.HEIGHT;const outputWidth=sourceWidth;const outputHeight=sourceHeight;if(IS_HIDPI){sourceWidth=sourceWidth*2;sourceHeight=sourceHeight*2}this.canvasCtx.drawImage(runnerImageSprite,this.spritePos.x,this.spritePos.y,sourceWidth,sourceHeight,this.xPos,this.yPos,outputWidth,outputHeight);this.canvasCtx.restore()}update(speed){if(!this.remove){this.xPos-=Math.ceil(speed);this.draw();if(!this.isVisible()){this.remove=true}}}isVisible(){return this.xPos+Config$1.WIDTH>0}}var Config$1;(function(Config){Config[Config["HEIGHT"]=14]="HEIGHT";Config[Config["MAX_CLOUD_GAP"]=400]="MAX_CLOUD_GAP";Config[Config["MAX_SKY_LEVEL"]=30]="MAX_SKY_LEVEL";Config[Config["MIN_CLOUD_GAP"]=100]="MIN_CLOUD_GAP";Config[Config["MIN_SKY_LEVEL"]=71]="MIN_SKY_LEVEL";Config[Config["WIDTH"]=46]="WIDTH"})(Config$1||(Config$1={})); // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. class HorizonLine{canvasCtx;xPos;yPos=0;bumpThreshold=.5;sourceXPos;spritePos;sourceDimensions;dimensions;constructor(canvas,lineConfig){let sourceX=lineConfig.sourceX;let sourceY=lineConfig.sourceY;if(IS_HIDPI){sourceX*=2;sourceY*=2}this.spritePos={x:sourceX,y:sourceY};const canvasContext=canvas.getContext("2d");assert(canvasContext);this.canvasCtx=canvasContext;this.dimensions={width:lineConfig.width,height:lineConfig.height};this.sourceXPos=[this.spritePos.x,this.spritePos.x+this.dimensions.width];this.xPos=[0,this.dimensions.width];this.yPos=lineConfig.yPos;this.sourceDimensions={height:lineConfig.height,width:lineConfig.width};if(IS_HIDPI){this.sourceDimensions.width=lineConfig.width*2;this.sourceDimensions.height=lineConfig.height*2}this.draw()}getRandomType(){return Math.random()>this.bumpThreshold?this.dimensions.width:0}draw(){const runnerImageSprite=getRunnerImageSprite();assert(runnerImageSprite);this.canvasCtx.drawImage(runnerImageSprite,this.sourceXPos[0],this.spritePos.y,this.sourceDimensions.width,this.sourceDimensions.height,this.xPos[0],this.yPos,this.dimensions.width,this.dimensions.height);this.canvasCtx.drawImage(runnerImageSprite,this.sourceXPos[1],this.spritePos.y,this.sourceDimensions.width,this.sourceDimensions.height,this.xPos[1],this.yPos,this.dimensions.width,this.dimensions.height)}updatexPos(pos,increment){const line1=pos;const line2=pos===0?1:0;this.xPos[line1]-=increment;this.xPos[line2]=this.xPos[line1]+this.dimensions.width;if(this.xPos[line1]<=-this.dimensions.width){this.xPos[line1]+=this.dimensions.width*2;this.xPos[line2]=this.xPos[line1]-this.dimensions.width;this.sourceXPos[line1]=this.getRandomType()+this.spritePos.x}}update(deltaTime,speed){const increment=Math.floor(speed*(FPS/1e3)*deltaTime);this.updatexPos(this.xPos[0]<=0?0:1,increment);this.draw()}reset(){this.xPos[0]=0;this.xPos[1]=this.dimensions.width}} // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. const PHASES=[140,120,100,60,40,20,0];var Config;(function(Config){Config[Config["FADE_SPEED"]=.035]="FADE_SPEED";Config[Config["HEIGHT"]=40]="HEIGHT";Config[Config["MOON_SPEED"]=.25]="MOON_SPEED";Config[Config["NUM_STARS"]=2]="NUM_STARS";Config[Config["STAR_SIZE"]=9]="STAR_SIZE";Config[Config["STAR_SPEED"]=.3]="STAR_SPEED";Config[Config["STAR_MAX_Y"]=70]="STAR_MAX_Y";Config[Config["WIDTH"]=20]="WIDTH"})(Config||(Config={}));class NightMode{spritePos;canvasCtx;xPos=0;yPos=30;currentPhase=0;opacity=0;containerWidth;stars=new Array(Config.NUM_STARS);drawStars=false;constructor(canvas,spritePos,containerWidth){this.spritePos=spritePos;const canvasContext=canvas.getContext("2d");assert(canvasContext);this.canvasCtx=canvasContext;this.containerWidth=containerWidth;this.placeStars()}update(activated){if(activated&&this.opacity===0){this.currentPhase++;if(this.currentPhase>=PHASES.length){this.currentPhase=0}}if(activated&&(this.opacity<1||this.opacity===0)){this.opacity+=Config.FADE_SPEED}else if(this.opacity>0){this.opacity-=Config.FADE_SPEED}if(this.opacity>0){this.xPos=this.updateXpos(this.xPos,Config.MOON_SPEED);if(this.drawStars){for(let i=0;i1&&this.typeConfig.multipleSpeed>speed){this.size=1}this.width=this.typeConfig.width*this.size;if(Array.isArray(this.typeConfig.yPos)){assert(Array.isArray(this.typeConfig.yPosMobile));const yPosConfig=IS_MOBILE?this.typeConfig.yPosMobile:this.typeConfig.yPos;const randomYPos=yPosConfig[getRandomNum(0,yPosConfig.length-1)];assert(randomYPos);this.yPos=randomYPos}else{this.yPos=this.typeConfig.yPos}this.draw();if(this.size>1){assert(this.collisionBoxes.length>=3);this.collisionBoxes[1].width=this.width-this.collisionBoxes[0].width-this.collisionBoxes[2].width;this.collisionBoxes[2].x=this.width-this.collisionBoxes[2].width}if(this.typeConfig.speedOffset){this.speedOffset=Math.random()>.5?this.typeConfig.speedOffset:-this.typeConfig.speedOffset}this.gap=this.getGap(this.gapCoefficient,speed);if(getRunnerAudioCues()){this.gap*=2}}draw(){let sourceWidth=this.typeConfig.width;let sourceHeight=this.typeConfig.height;if(IS_HIDPI){sourceWidth=sourceWidth*2;sourceHeight=sourceHeight*2}let sourceX=sourceWidth*this.size*(.5*(this.size-1))+this.spritePos.x;if(this.currentFrame>0){sourceX+=sourceWidth*this.currentFrame}this.canvasCtx.drawImage(this.imageSprite,sourceX,this.spritePos.y,sourceWidth*this.size,sourceHeight,this.xPos,this.yPos,this.typeConfig.width*this.size,this.typeConfig.height)}update(deltaTime,speed){if(!this.remove){if(this.typeConfig.speedOffset){speed+=this.speedOffset}this.xPos-=Math.floor(speed*FPS/1e3*deltaTime);if(this.typeConfig.numFrames){assert(this.typeConfig.frameRate);this.timer+=deltaTime;if(this.timer>=this.typeConfig.frameRate){this.currentFrame=this.currentFrame===this.typeConfig.numFrames-1?0:this.currentFrame+1;this.timer=0}}this.draw();if(!this.isVisible()){this.remove=true}}}getGap(gapCoefficient,speed){const minGap=Math.round(this.width*speed+this.typeConfig.minGap*gapCoefficient);const maxGap=Math.round(minGap*maxGapCoefficient);return getRandomNum(minGap,maxGap)}isVisible(){return this.xPos+this.width>0}cloneCollisionBoxes(){const collisionBoxes=this.typeConfig.collisionBoxes;for(let i=collisionBoxes.length-1;i>=0;i--){this.collisionBoxes[i]=new CollisionBox(collisionBoxes[i].x,collisionBoxes[i].y,collisionBoxes[i].width,collisionBoxes[i].height)}}} // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. let obstacleTypes=[];class Horizon{constructor(canvas,spritePos,dimensions,gapCoefficient){this.canvas=canvas;this.canvasCtx=this.canvas.getContext("2d");this.config=Horizon.config;this.dimensions=dimensions;this.gapCoefficient=gapCoefficient;this.obstacles=[];this.obstacleHistory=[];this.horizonOffsets=[0,0];this.cloudFrequency=this.config.CLOUD_FREQUENCY;this.spritePos=spritePos;this.nightMode=null;this.altGameModeActive=false;this.clouds=[];this.cloudSpeed=this.config.BG_CLOUD_SPEED;this.backgroundEls=[];this.lastEl=null;this.backgroundSpeed=this.config.BG_CLOUD_SPEED;this.horizonLine=null;this.horizonLines=[];this.init()}init(){obstacleTypes=spriteDefinitionByType.original.obstacles;this.addCloud();for(let i=0;i=0;i--){bgElArray[i].update(elSpeed)}const lastEl=bgElArray[numElements-1];if(numElementslastEl.gap&&frequency>Math.random()){bgElAddFunction()}}else{bgElAddFunction()}}updateClouds(deltaTime,speed){const elSpeed=this.cloudSpeed/1e3*deltaTime*speed;this.updateBackgroundEl(elSpeed,this.clouds,this.config.MAX_CLOUDS,this.addCloud.bind(this),this.cloudFrequency);this.clouds=this.clouds.filter((obj=>!obj.remove))}updateBackgroundEls(deltaTime,speed){this.updateBackgroundEl(deltaTime,this.backgroundEls,getGlobalConfig().maxBgEls,this.addBackgroundEl.bind(this),this.cloudFrequency);this.backgroundEls=this.backgroundEls.filter((obj=>!obj.remove))}updateObstacles(deltaTime,currentSpeed){const updatedObstacles=this.obstacles.slice(0);for(let i=0;i0){const lastObstacle=this.obstacles[this.obstacles.length-1];if(lastObstacle&&!lastObstacle.followingObstacleCreated&&lastObstacle.isVisible()&&lastObstacle.xPos+lastObstacle.width+lastObstacle.gap0?getRandomNum(0,obstacleCount):0;const obstacleType=obstacleTypes[obstacleTypeIndex];if(obstacleCount>0&&this.duplicateObstacleCheck(obstacleType.type)||currentSpeed1){this.obstacleHistory.splice(Runner.config.MAX_OBSTACLE_DUPLICATION)}}}duplicateObstacleCheck(nextObstacleType){let duplicateCount=0;for(let i=0;i=Runner.config.MAX_OBSTACLE_DUPLICATION}reset(){this.obstacles=[];for(let l=0;l0){let index=getRandomNum(0,backgroundElTypes.length-1);let type=backgroundElTypes[index];while(type===this.lastEl&&backgroundElTypes.length>1){index=getRandomNum(0,backgroundElTypes.length-1);type=backgroundElTypes[index]}this.lastEl=type;this.backgroundEls.push(new BackgroundEl(this.canvas,this.spritePos.backgroundEl,this.dimensions.width,type))}}}Horizon.config={BG_CLOUD_SPEED:.2,BUMPY_THRESHOLD:.3,CLOUD_FREQUENCY:.5,HORIZON_HEIGHT:16,MAX_CLOUDS:6}; // Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. const defaultTrexConfig={dropVelocity:-5,flashOff:175,flashOn:100,height:47,heightDuck:25,introDuration:1500,speedDropCoefficient:3,spriteWidth:262,startXPos:50,width:44,widthDuck:59,invertJump:false};const slowJumpConfig={gravity:.25,maxJumpHeight:50,minJumpHeight:45,initialJumpVelocity:-20};const normalJumpConfig={gravity:.6,maxJumpHeight:30,minJumpHeight:30,initialJumpVelocity:-10};const collisionBoxes={ducking:[new CollisionBox(1,18,55,25)],running:[new CollisionBox(22,0,17,16),new CollisionBox(1,18,30,9),new CollisionBox(10,35,14,8),new CollisionBox(1,24,29,5),new CollisionBox(5,30,21,4),new CollisionBox(9,34,15,4)]};var Status;(function(Status){Status[Status["CRASHED"]=0]="CRASHED";Status[Status["DUCKING"]=1]="DUCKING";Status[Status["JUMPING"]=2]="JUMPING";Status[Status["RUNNING"]=3]="RUNNING";Status[Status["WAITING"]=4]="WAITING"})(Status||(Status={}));const BLINK_TIMING=7e3;const animFrames={[Status.WAITING]:{frames:[44,0],msPerFrame:1e3/3},[Status.RUNNING]:{frames:[88,132],msPerFrame:1e3/12},[Status.CRASHED]:{frames:[220],msPerFrame:1e3/60},[Status.JUMPING]:{frames:[0],msPerFrame:1e3/60},[Status.DUCKING]:{frames:[264,323],msPerFrame:1e3/8}};class Trex{config;playingIntro=false;xPos=0;yPos=0;jumpCount=0;ducking=false;blinkCount=0;jumping=false;speedDrop=false;canvasCtx;spritePos;xInitialPos=0;groundYPos=0;currentFrame=0;currentAnimFrames=[];blinkDelay=0;animStartTime=0;timer=0;msPerFrame=1e3/FPS;status=Status.WAITING;jumpVelocity=0;reachedMinHeight=false;altGameModeEnabled=false;flashing=false;minJumpHeight;constructor(canvas,spritePos){const canvasContext=canvas.getContext("2d");assert(canvasContext);this.canvasCtx=canvasContext;this.spritePos=spritePos;this.config=Object.assign(defaultTrexConfig,normalJumpConfig);const runnerDefaultDimensions=getRunnerDefaultDimensions();const runnerBottomPadding=getRunnerConfigValue("BOTTOM_PAD");assert(runnerDefaultDimensions);assert(runnerBottomPadding);this.groundYPos=runnerDefaultDimensions.height-this.config.height-runnerBottomPadding;this.yPos=this.groundYPos;this.minJumpHeight=this.groundYPos-this.config.minJumpHeight;this.draw(0,0);this.update(0,Status.WAITING)}enableSlowConfig(){const jumpConfig=getRunnerSlowdown()?slowJumpConfig:normalJumpConfig;this.config=Object.assign(defaultTrexConfig,jumpConfig);this.adjustAltGameConfigForSlowSpeed()}enableAltGameMode(spritePos){this.altGameModeEnabled=true;this.spritePos=spritePos;const spriteDefinition=getRunnerSpriteDefinition();assert(spriteDefinition);const tRexSpriteDefinition=spriteDefinition.tRex;assert(tRexSpriteDefinition.running1);const runnerDefaultDimensions=getRunnerDefaultDimensions();assert(runnerDefaultDimensions);animFrames[Status.RUNNING].frames=[tRexSpriteDefinition.running1.x,tRexSpriteDefinition.running2.x];animFrames[Status.CRASHED].frames=[tRexSpriteDefinition.crashed.x];if(typeof tRexSpriteDefinition.jumping.x==="object"){animFrames[Status.JUMPING].frames=tRexSpriteDefinition.jumping.x}else{animFrames[Status.JUMPING].frames=[tRexSpriteDefinition.jumping.x]}animFrames[Status.DUCKING].frames=[tRexSpriteDefinition.ducking1.x,tRexSpriteDefinition.ducking2.x];this.config.gravity=tRexSpriteDefinition.gravity||this.config.gravity;this.config.height=tRexSpriteDefinition.running1.h,this.config.initialJumpVelocity=tRexSpriteDefinition.initialJumpVelocity;this.config.maxJumpHeight=tRexSpriteDefinition.maxJumpHeight;this.config.minJumpHeight=tRexSpriteDefinition.minJumpHeight;this.config.width=tRexSpriteDefinition.running1.w;this.config.widthCrashed=tRexSpriteDefinition.crashed.w;this.config.widthJump=tRexSpriteDefinition.jumping.w;this.config.invertJump=tRexSpriteDefinition.invertJump;this.adjustAltGameConfigForSlowSpeed(tRexSpriteDefinition.gravity);this.groundYPos=runnerDefaultDimensions.height-this.config.height-spriteDefinition.bottomPad;this.yPos=this.groundYPos;this.reset()}adjustAltGameConfigForSlowSpeed(gravityValue){if(getRunnerSlowdown()){if(gravityValue){this.config.gravity=gravityValue/1.5}this.config.minJumpHeight*=1.5;this.config.maxJumpHeight*=1.5;this.config.initialJumpVelocity*=1.5}}setFlashing(status){this.flashing=status}setJumpVelocity(setting){this.config.initialJumpVelocity=-setting;this.config.dropVelocity=-setting/2}update(deltaTime,status){this.timer+=deltaTime;if(status){this.status=status;this.currentFrame=0;this.msPerFrame=animFrames[status].msPerFrame;this.currentAnimFrames=animFrames[status].frames;if(status===Status.WAITING){this.animStartTime=getTimeStamp();this.setBlinkDelay()}}if(this.playingIntro&&this.xPos=this.msPerFrame){this.currentFrame=this.currentFrame===this.currentAnimFrames.length-1?0:this.currentFrame+1;this.timer=0}if(this.speedDrop&&this.yPos===this.groundYPos){this.speedDrop=false;this.setDuck(true)}}draw(x,y){let sourceX=x;let sourceY=y;let sourceWidth=this.ducking&&this.status!==Status.CRASHED?this.config.widthDuck:this.config.width;let sourceHeight=this.config.height;const outputHeight=sourceHeight;if(this.altGameModeEnabled){assert(this.config.widthCrashed)}const outputWidth=this.altGameModeEnabled&&this.status===Status.CRASHED?this.config.widthCrashed:this.config.width;const runnerImageSprite=getRunnerImageSprite();assert(runnerImageSprite);if(this.altGameModeEnabled){if(this.jumping&&this.status!==Status.CRASHED){assert(this.config.widthJump);sourceWidth=this.config.widthJump}else if(this.status===Status.CRASHED){assert(this.config.widthCrashed);sourceWidth=this.config.widthCrashed}}if(IS_HIDPI){sourceX*=2;sourceY*=2;sourceWidth*=2;sourceHeight*=2}sourceX+=this.spritePos.x;sourceY+=this.spritePos.y;if(this.flashing){if(this.timerthis.config.flashOff){this.timer=0}}if(this.ducking&&this.status!==Status.CRASHED){this.canvasCtx.drawImage(runnerImageSprite,sourceX,sourceY,sourceWidth,sourceHeight,this.xPos,this.yPos,this.config.widthDuck,outputHeight)}else if(this.altGameModeEnabled&&this.jumping&&this.status!==Status.CRASHED){assert(this.config.widthJump);const spriteDefinition=getRunnerSpriteDefinition();assert(spriteDefinition);assert(spriteDefinition.tRex);const jumpOffset=spriteDefinition.tRex.jumping.xOffset*(IS_HIDPI?2:1);this.canvasCtx.drawImage(runnerImageSprite,sourceX,sourceY,sourceWidth,sourceHeight,this.xPos-jumpOffset,this.yPos,this.config.widthJump,outputHeight)}else{if(this.ducking&&this.status===Status.CRASHED){this.xPos++}this.canvasCtx.drawImage(runnerImageSprite,sourceX,sourceY,sourceWidth,sourceHeight,this.xPos,this.yPos,outputWidth,outputHeight)}this.canvasCtx.globalAlpha=1}setBlinkDelay(){this.blinkDelay=Math.ceil(Math.random()*BLINK_TIMING)}blink(time){const deltaTime=time-this.animStartTime;if(deltaTime>=this.blinkDelay){this.draw(this.currentAnimFrames[this.currentFrame],0);if(this.currentFrame===1){this.setBlinkDelay();this.animStartTime=time;this.blinkCount++}}}startJump(speed){if(!this.jumping){this.update(0,Status.JUMPING);this.jumpVelocity=this.config.initialJumpVelocity-speed/10;this.jumping=true;this.reachedMinHeight=false;this.speedDrop=false;if(this.config.invertJump){this.minJumpHeight=this.groundYPos+this.config.minJumpHeight}}}endJump(){if(this.reachedMinHeight&&this.jumpVelocitythis.minJumpHeight||!this.config.invertJump&&this.yPos-this.config.maxJumpHeight||!this.config.invertJump&&this.yPosthis.groundYPos){this.reset();this.jumpCount++;if(getRunnerAudioCues()){const generatedSoundFx=getRunnerGeneratedSoundFx();assert(generatedSoundFx);generatedSoundFx.loopFootSteps()}}}setSpeedDrop(){this.speedDrop=true;this.jumpVelocity=1}setDuck(isDucking){if(isDucking&&this.status!==Status.DUCKING){this.update(0,Status.DUCKING);this.ducking=true}else if(this.status===Status.DUCKING){this.update(0,Status.RUNNING);this.ducking=false}}reset(){this.xPos=this.xInitialPos;this.yPos=this.groundYPos;this.jumpVelocity=0;this.jumping=false;this.ducking=false;this.update(0,Status.RUNNING);this.speedDrop=false;this.jumpCount=0}getCollisionBoxes(){return this.ducking?collisionBoxes.ducking:collisionBoxes.running}} // Copyright 2014 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. function Runner(outerContainerId,opt_config){if(Runner.instance_){return Runner.instance_}Runner.instance_=this;this.outerContainerEl=document.querySelector(outerContainerId);this.containerEl=null;this.snackbarEl=null;this.touchController=null;this.config=opt_config||Object.assign(Runner.config,Runner.normalConfig);this.dimensions=Runner.defaultDimensions;this.gameType=null;Runner.spriteDefinition=spriteDefinitionByType["original"];this.altGameImageSprite=null;this.altGameModeActive=false;this.altGameModeFlashTimer=null;this.fadeInTimer=0;this.canvas=null;this.canvasCtx=null;this.tRex=null;this.distanceMeter=null;this.distanceRan=0;this.highestScore=0;this.syncHighestScore=false;this.time=0;this.runningTime=0;this.msPerFrame=1e3/FPS;this.currentSpeed=this.config.SPEED;Runner.slowDown=false;this.obstacles=[];this.activated=false;this.playing=false;this.crashed=false;this.paused=false;this.inverted=false;this.invertTimer=0;this.resizeTimerId_=null;this.playCount=0;this.audioBuffer=null;this.soundFx={};this.generatedSoundFx=null;this.audioContext=null;this.images={};this.imagesLoaded=0;this.pollingGamepads=false;this.gamepadIndex=undefined;this.previousGamepad=null;if(this.isDisabled()){this.setupDisabledRunner()}else{if(Runner.isAltGameModeEnabled()){this.initAltGameType();Runner.gameType=this.gameType}this.loadImages();window["initializeEasterEggHighScore"]=this.initializeHighScore.bind(this)}}const DEFAULT_WIDTH=600;const ARCADE_MODE_URL="chrome://dino/";const RESOURCE_POSTFIX="offline-resources-";const A11Y_STRINGS={ariaLabel:"dinoGameA11yAriaLabel",description:"dinoGameA11yDescription",gameOver:"dinoGameA11yGameOver",highScore:"dinoGameA11yHighScore",jump:"dinoGameA11yJump",started:"dinoGameA11yStartGame",speedLabel:"dinoGameA11ySpeedToggle"};Runner.config={AUDIOCUE_PROXIMITY_THRESHOLD:190,AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y:250,BG_CLOUD_SPEED:.2,BOTTOM_PAD:10,CANVAS_IN_VIEW_OFFSET:-10,CLEAR_TIME:3e3,CLOUD_FREQUENCY:.5,FADE_DURATION:1,FLASH_DURATION:1e3,GAMEOVER_CLEAR_TIME:1200,INITIAL_JUMP_VELOCITY:12,INVERT_FADE_DURATION:12e3,MAX_BLINK_COUNT:3,MAX_CLOUDS:6,MAX_OBSTACLE_LENGTH:3,MAX_OBSTACLE_DUPLICATION:2,RESOURCE_TEMPLATE_ID:"audio-resources",SPEED:6,SPEED_DROP_COEFFICIENT:3,ARCADE_MODE_INITIAL_TOP_POSITION:35,ARCADE_MODE_TOP_POSITION_PERCENT:.1};Runner.normalConfig={ACCELERATION:.001,AUDIOCUE_PROXIMITY_THRESHOLD:190,AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y:250,GAP_COEFFICIENT:.6,INVERT_DISTANCE:700,MAX_SPEED:13,MOBILE_SPEED_COEFFICIENT:1.2,SPEED:6};Runner.slowConfig={ACCELERATION:5e-4,AUDIOCUE_PROXIMITY_THRESHOLD:170,AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y:220,GAP_COEFFICIENT:.3,INVERT_DISTANCE:350,MAX_SPEED:9,MOBILE_SPEED_COEFFICIENT:1.5,SPEED:4.2};Runner.defaultDimensions={width:DEFAULT_WIDTH,height:150};Runner.classes={ARCADE_MODE:"arcade-mode",CANVAS:"runner-canvas",CONTAINER:"runner-container",CRASHED:"crashed",ICON:"icon-offline",INVERTED:"inverted",SNACKBAR:"snackbar",SNACKBAR_SHOW:"snackbar-show",TOUCH_CONTROLLER:"controller"};Runner.sounds={BUTTON_PRESS:"offline-sound-press",HIT:"offline-sound-hit",SCORE:"offline-sound-reached"};Runner.keycodes={JUMP:{38:1,32:1},DUCK:{40:1},RESTART:{13:1}};Runner.events={ANIM_END:"webkitAnimationEnd",CLICK:"click",KEYDOWN:"keydown",KEYUP:"keyup",POINTERDOWN:"pointerdown",POINTERUP:"pointerup",RESIZE:"resize",TOUCHEND:"touchend",TOUCHSTART:"touchstart",VISIBILITY:"visibilitychange",BLUR:"blur",FOCUS:"focus",LOAD:"load",GAMEPADCONNECTED:"gamepadconnected"};Runner.prototype={initAltGameType(){if(GAME_TYPE.length>0){this.gameType=loadTimeData&&loadTimeData.valueExists("altGameType")?GAME_TYPE[parseInt(loadTimeData.getValue("altGameType"),10)-1]:""}},isDisabled(){return loadTimeData&&loadTimeData.valueExists("disabledEasterEgg")},setupDisabledRunner(){this.containerEl=document.createElement("div");this.containerEl.className=Runner.classes.SNACKBAR;this.containerEl.textContent=loadTimeData.getValue("disabledEasterEgg");this.outerContainerEl.appendChild(this.containerEl);document.addEventListener(Runner.events.KEYDOWN,function(e){if(Runner.keycodes.JUMP[e.keyCode]){this.containerEl.classList.add(Runner.classes.SNACKBAR_SHOW);document.querySelector(".icon").classList.add("icon-disabled")}}.bind(this))},updateConfigSetting(setting,value){if(setting in this.config&&value!==undefined){this.config[setting]=value;switch(setting){case"gravity":case"minJumpHeight":case"speedDropCoefficient":this.tRex.config[setting]=value;break;case"initialJumpVelocity":this.tRex.setJumpVelocity(value);break;case"speed":this.setSpeed(value);break}}},createImageElement(resourceName){const imgSrc=loadTimeData&&loadTimeData.valueExists(resourceName)?loadTimeData.getString(resourceName):null;if(imgSrc){const el=document.createElement("img");el.id=resourceName;el.src=imgSrc;document.getElementById("offline-resources").appendChild(el);return el}return null},loadImages(){let scale="1x";this.spriteDef=Runner.spriteDefinition.ldpi;if(IS_HIDPI){scale="2x";this.spriteDef=Runner.spriteDefinition.hdpi}Runner.imageSprite=document.getElementById(RESOURCE_POSTFIX+scale);if(this.gameType){Runner.altGameImageSprite=this.createImageElement("altGameSpecificImage"+scale);Runner.altCommonImageSprite=this.createImageElement("altGameCommonImage"+scale)}Runner.origImageSprite=Runner.imageSprite;if(!Runner.altGameImageSprite||!Runner.altCommonImageSprite){Runner.isAltGameModeEnabled=()=>false;this.altGameModeActive=false}if(Runner.imageSprite.complete){this.init()}else{Runner.imageSprite.addEventListener(Runner.events.LOAD,this.init.bind(this))}},loadSounds(){if(!IS_IOS){this.audioContext=new AudioContext;const resourceTemplate=document.getElementById(this.config.RESOURCE_TEMPLATE_ID).content;for(const sound in Runner.sounds){let soundSrc=resourceTemplate.getElementById(Runner.sounds[sound]).src;soundSrc=soundSrc.substr(soundSrc.indexOf(",")+1);const buffer=decodeBase64ToArrayBuffer(soundSrc);this.audioContext.decodeAudioData(buffer,function(index,audioData){this.soundFx[index]=audioData}.bind(this,sound))}}},setSpeed(opt_speed){const speed=opt_speed||this.currentSpeed;if(this.dimensions.widthspeed?speed:mobileSpeed}else if(opt_speed){this.currentSpeed=opt_speed}},init(){document.querySelector("."+Runner.classes.ICON).style.visibility="hidden";if(this.isArcadeMode()){document.title=document.title+" - "+getA11yString(A11Y_STRINGS.ariaLabel)}this.adjustDimensions();this.setSpeed();const ariaLabel=getA11yString(A11Y_STRINGS.ariaLabel);this.containerEl=document.createElement("div");this.containerEl.setAttribute("role",IS_MOBILE?"button":"application");this.containerEl.setAttribute("tabindex","0");this.containerEl.setAttribute("title",getA11yString(A11Y_STRINGS.description));this.containerEl.setAttribute("aria-label",ariaLabel);this.containerEl.className=Runner.classes.CONTAINER;this.canvas=createCanvas(this.containerEl,this.dimensions.width,this.dimensions.height);this.a11yStatusEl=document.createElement("span");this.a11yStatusEl.className="offline-runner-live-region";this.a11yStatusEl.setAttribute("aria-live","assertive");this.a11yStatusEl.textContent="";Runner.a11yStatusEl=this.a11yStatusEl;this.slowSpeedCheckboxLabel=document.createElement("label");this.slowSpeedCheckboxLabel.className="slow-speed-option hidden";this.slowSpeedCheckboxLabel.textContent=getA11yString(A11Y_STRINGS.speedLabel);this.slowSpeedCheckbox=document.createElement("input");this.slowSpeedCheckbox.setAttribute("type","checkbox");this.slowSpeedCheckbox.setAttribute("title",getA11yString(A11Y_STRINGS.speedLabel));this.slowSpeedCheckbox.setAttribute("tabindex","0");this.slowSpeedCheckbox.setAttribute("checked","checked");this.slowSpeedToggleEl=document.createElement("span");this.slowSpeedToggleEl.className="slow-speed-toggle";this.slowSpeedCheckboxLabel.appendChild(this.slowSpeedCheckbox);this.slowSpeedCheckboxLabel.appendChild(this.slowSpeedToggleEl);if(IS_IOS){this.outerContainerEl.appendChild(this.a11yStatusEl)}else{this.containerEl.appendChild(this.a11yStatusEl)}this.canvasCtx=this.canvas.getContext("2d");this.canvasCtx.fillStyle="#f7f7f7";this.canvasCtx.fill();Runner.updateCanvasScaling(this.canvas);this.horizon=new Horizon(this.canvas,this.spriteDef,this.dimensions,this.config.GAP_COEFFICIENT);this.distanceMeter=new DistanceMeter(this.canvas,this.spriteDef.textSprite,this.dimensions.width);this.tRex=new Trex(this.canvas,this.spriteDef.tRex);this.outerContainerEl.appendChild(this.containerEl);this.outerContainerEl.appendChild(this.slowSpeedCheckboxLabel);this.startListening();this.update();window.addEventListener(Runner.events.RESIZE,this.debounceResize.bind(this));const darkModeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)");this.isDarkMode=darkModeMediaQuery&&darkModeMediaQuery.matches;darkModeMediaQuery.addListener((e=>{this.isDarkMode=e.matches}))},createTouchController(){this.touchController=document.createElement("div");this.touchController.className=Runner.classes.TOUCH_CONTROLLER;this.touchController.addEventListener(Runner.events.TOUCHSTART,this);this.touchController.addEventListener(Runner.events.TOUCHEND,this);this.outerContainerEl.appendChild(this.touchController)},debounceResize(){if(!this.resizeTimerId_){this.resizeTimerId_=setInterval(this.adjustDimensions.bind(this),250)}},adjustDimensions(){clearInterval(this.resizeTimerId_);this.resizeTimerId_=null;const boxStyles=window.getComputedStyle(this.outerContainerEl);const padding=Number(boxStyles.paddingLeft.substr(0,boxStyles.paddingLeft.length-2));this.dimensions.width=this.outerContainerEl.offsetWidth-padding*2;if(this.isArcadeMode()){this.dimensions.width=Math.min(DEFAULT_WIDTH,this.dimensions.width);if(this.activated){this.setArcadeModeContainerScale()}}if(this.canvas){this.canvas.width=this.dimensions.width;this.canvas.height=this.dimensions.height;Runner.updateCanvasScaling(this.canvas);this.distanceMeter.calcXPos(this.dimensions.width);this.clearCanvas();this.horizon.update(0,0,true);this.tRex.update(0);if(this.playing||this.crashed||this.paused){this.containerEl.style.width=this.dimensions.width+"px";this.containerEl.style.height=this.dimensions.height+"px";this.distanceMeter.update(0,Math.ceil(this.distanceRan));this.stop()}else{this.tRex.draw(0,0)}if(this.crashed&&this.gameOverPanel){this.gameOverPanel.updateDimensions(this.dimensions.width);this.gameOverPanel.draw(this.altGameModeActive,this.tRex)}}},playIntro(){if(!this.activated&&!this.crashed){this.playingIntro=true;this.tRex.playingIntro=true;const keyframes="@-webkit-keyframes intro { "+"from { width:"+this.tRex.config.width+"px }"+"to { width: "+this.dimensions.width+"px }"+"}";document.styleSheets[0].insertRule(keyframes,0);this.containerEl.addEventListener(Runner.events.ANIM_END,this.startGame.bind(this));this.containerEl.style.webkitAnimation="intro .4s ease-out 1 both";this.containerEl.style.width=this.dimensions.width+"px";this.setPlayStatus(true);this.activated=true}else if(this.crashed){this.restart()}},startGame(){if(this.isArcadeMode()){this.setArcadeMode()}this.toggleSpeed();this.runningTime=0;this.playingIntro=false;this.tRex.playingIntro=false;this.containerEl.style.webkitAnimation="";this.playCount++;if(Runner.audioCues){this.generatedSoundFx.background();this.containerEl.setAttribute("title",getA11yString(A11Y_STRINGS.jump))}document.addEventListener(Runner.events.VISIBILITY,this.onVisibilityChange.bind(this));window.addEventListener(Runner.events.BLUR,this.onVisibilityChange.bind(this));window.addEventListener(Runner.events.FOCUS,this.onVisibilityChange.bind(this))},clearCanvas(){this.canvasCtx.clearRect(0,0,this.dimensions.width,this.dimensions.height)},isCanvasInView(){return this.containerEl.getBoundingClientRect().top>Runner.config.CANVAS_IN_VIEW_OFFSET},enableAltGameMode(){Runner.imageSprite=Runner.altGameImageSprite;Runner.spriteDefinition=spriteDefinitionByType[Runner.gameType];if(IS_HIDPI){this.spriteDef=Runner.spriteDefinition.hdpi}else{this.spriteDef=Runner.spriteDefinition.ldpi}this.altGameModeActive=true;this.tRex.enableAltGameMode(this.spriteDef.tRex);this.horizon.enableAltGameMode(this.spriteDef);if(Runner.audioCues){this.generatedSoundFx.background()}},update(){this.updatePending=false;const now=getTimeStamp();let deltaTime=now-(this.time||now);if(this.altGameModeFlashTimer<0||this.altGameModeFlashTimer===0){this.altGameModeFlashTimer=null;this.tRex.setFlashing(false);this.enableAltGameMode()}else if(this.altGameModeFlashTimer>0){this.altGameModeFlashTimer-=deltaTime;this.tRex.update(deltaTime);deltaTime=0}this.time=now;if(this.playing){this.clearCanvas();if(this.altGameModeActive&&this.fadeInTimer<=this.config.FADE_DURATION){this.fadeInTimer+=deltaTime/1e3;this.canvasCtx.globalAlpha=this.fadeInTimer}else{this.canvasCtx.globalAlpha=1}if(this.tRex.jumping){this.tRex.updateJump(deltaTime)}this.runningTime+=deltaTime;const hasObstacles=this.runningTime>this.config.CLEAR_TIME;if(this.tRex.jumpCount===1&&!this.playingIntro){this.playIntro()}if(this.playingIntro){this.horizon.update(0,this.currentSpeed,hasObstacles)}else if(!this.crashed){const showNightMode=this.isDarkMode^this.inverted;deltaTime=!this.activated?0:deltaTime;this.horizon.update(deltaTime,this.currentSpeed,hasObstacles,showNightMode)}let collision=hasObstacles&&checkForCollision(this.horizon.obstacles[0],this.tRex);if(Runner.audioCues&&hasObstacles){const jumpObstacle=this.horizon.obstacles[0].typeConfig.type!=="collectable";if(!this.horizon.obstacles[0].jumpAlerted){const threshold=Runner.isMobileMouseInput?Runner.config.AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y:Runner.config.AUDIOCUE_PROXIMITY_THRESHOLD;const adjProximityThreshold=threshold+threshold*Math.log10(this.currentSpeed/Runner.config.SPEED);if(this.horizon.obstacles[0].xPosthis.config.INVERT_FADE_DURATION){this.invertTimer=0;this.invertTrigger=false;this.invert(false)}else if(this.invertTimer){this.invertTimer+=deltaTime}else{const actualDistance=this.distanceMeter.getActualDistance(Math.ceil(this.distanceRan));if(actualDistance>0){this.invertTrigger=!(actualDistance%this.config.INVERT_DISTANCE);if(this.invertTrigger&&this.invertTimer===0){this.invertTimer+=deltaTime;this.invert(false)}}}}}if(this.playing||!this.activated&&this.tRex.blinkCount=this.config.GAMEOVER_CLEAR_TIME&&Runner.keycodes.JUMP[keyCode])){this.handleGameOverClicks(e)}}else if(this.paused&&isjumpKey){this.tRex.reset();this.play()}},onGamepadConnected(e){if(!this.pollingGamepads){this.pollGamepadState()}},pollGamepadState(){const gamepads=navigator.getGamepads();this.pollActiveGamepad(gamepads);this.pollingGamepads=true;requestAnimationFrame(this.pollGamepadState.bind(this))},pollForActiveGamepad(gamepads){for(let i=0;i0&&gamepads[i].buttons[0].pressed){this.gamepadIndex=i;this.pollActiveGamepad(gamepads);return}}},pollActiveGamepad(gamepads){if(this.gamepadIndex===undefined){this.pollForActiveGamepad(gamepads);return}const gamepad=gamepads[this.gamepadIndex];if(!gamepad){this.gamepadIndex=undefined;this.pollForActiveGamepad(gamepads);return}this.pollGamepadButton(gamepad,0,38);if(gamepad.buttons.length>=2){this.pollGamepadButton(gamepad,1,40)}if(gamepad.buttons.length>=10){this.pollGamepadButton(gamepad,9,13)}this.previousGamepad=gamepad},pollGamepadButton(gamepad,buttonIndex,keyCode){const state=gamepad.buttons[buttonIndex].pressed;let previousState=false;if(this.previousGamepad){previousState=this.previousGamepad.buttons[buttonIndex].pressed}if(state!==previousState){const e=new KeyboardEvent(state?Runner.events.KEYDOWN:Runner.events.KEYUP,{keyCode:keyCode});document.dispatchEvent(e)}},handleGameOverClicks(e){if(e.target!==this.slowSpeedCheckbox){e.preventDefault();if(this.distanceMeter.hasClickedOnHighScore(e)&&this.highestScore){if(this.distanceMeter.isHighScoreFlashing()){this.saveHighScore(0,true);this.distanceMeter.resetHighScore()}else{this.distanceMeter.startHighScoreFlashing()}}else{this.distanceMeter.cancelHighScoreFlashing();this.restart()}}},isLeftClickOnCanvas(e){return e.button!=null&&e.button<2&&e.type===Runner.events.POINTERUP&&(e.target===this.canvas||IS_MOBILE&&Runner.audioCues&&e.target===this.containerEl)},scheduleNextUpdate(){if(!this.updatePending){this.updatePending=true;this.raqId=requestAnimationFrame(this.update.bind(this))}},isRunning(){return!!this.raqId},initializeHighScore(highScore){this.syncHighestScore=true;highScore=Math.ceil(highScore);if(highScorethis.highestScore){this.saveHighScore(this.distanceRan)}this.time=getTimeStamp();if(Runner.audioCues){this.generatedSoundFx.stopAll();announcePhrase(getA11yString(A11Y_STRINGS.gameOver).replace("$1",this.distanceMeter.getActualDistance(this.distanceRan).toString())+" "+getA11yString(A11Y_STRINGS.highScore).replace("$1",this.distanceMeter.getActualDistance(this.highestScore).toString()));this.containerEl.setAttribute("title",getA11yString(A11Y_STRINGS.ariaLabel))}this.showSpeedToggle();this.disableSpeedToggle(false)},stop(){this.setPlayStatus(false);this.paused=true;cancelAnimationFrame(this.raqId);this.raqId=0;if(Runner.audioCues){this.generatedSoundFx.stopAll()}},play(){if(!this.crashed){this.setPlayStatus(true);this.paused=false;this.tRex.update(0,Status.RUNNING);this.time=getTimeStamp();this.update();if(Runner.audioCues){this.generatedSoundFx.background()}}},restart(){if(!this.raqId){this.playCount++;this.runningTime=0;this.setPlayStatus(true);this.toggleSpeed();this.paused=false;this.crashed=false;this.distanceRan=0;this.setSpeed(this.config.SPEED);this.time=getTimeStamp();this.containerEl.classList.remove(Runner.classes.CRASHED);this.clearCanvas();this.distanceMeter.reset();this.horizon.reset();this.tRex.reset();this.playSound(this.soundFx.BUTTON_PRESS);this.invert(true);this.flashTimer=null;this.update();this.gameOverPanel.reset();if(Runner.audioCues){this.generatedSoundFx.background()}this.containerEl.setAttribute("title",getA11yString(A11Y_STRINGS.jump));announcePhrase(getA11yString(A11Y_STRINGS.started))}},setPlayStatus(isPlaying){if(this.touchController){this.touchController.classList.toggle(HIDDEN_CLASS,!isPlaying)}this.playing=isPlaying},isArcadeMode(){return IS_RTL?document.title.indexOf(ARCADE_MODE_URL)===1:document.title===ARCADE_MODE_URL},setArcadeMode(){document.body.classList.add(Runner.classes.ARCADE_MODE);this.setArcadeModeContainerScale()},setArcadeModeContainerScale(){const windowHeight=window.innerHeight;const scaleHeight=windowHeight/this.dimensions.height;const scaleWidth=window.innerWidth/this.dimensions.width;const scale=Math.max(1,Math.min(scaleHeight,scaleWidth));const scaledCanvasHeight=this.dimensions.height*scale;const translateY=Math.ceil(Math.max(0,(windowHeight-scaledCanvasHeight-Runner.config.ARCADE_MODE_INITIAL_TOP_POSITION)*Runner.config.ARCADE_MODE_TOP_POSITION_PERCENT))*window.devicePixelRatio;const cssScale=IS_RTL?-scale+","+scale:scale;this.containerEl.style.transform="scale("+cssScale+") translateY("+translateY+"px)"},onVisibilityChange(e){if(document.hidden||document.webkitHidden||e.type==="blur"||document.visibilityState!=="visible"){this.stop()}else if(!this.crashed){this.tRex.reset();this.play()}},playSound(soundBuffer){if(soundBuffer){const sourceNode=this.audioContext.createBufferSource();sourceNode.buffer=soundBuffer;sourceNode.connect(this.audioContext.destination);sourceNode.start(0)}},invert(reset){const htmlEl=document.firstElementChild;if(reset){htmlEl.classList.toggle(Runner.classes.INVERTED,false);this.invertTimer=0;this.inverted=false}else{this.inverted=htmlEl.classList.toggle(Runner.classes.INVERTED,this.invertTrigger)}}};Runner.updateCanvasScaling=function(canvas,opt_width,opt_height){const context=canvas.getContext("2d");const devicePixelRatio=Math.floor(window.devicePixelRatio)||1;const backingStoreRatio=Math.floor(context.webkitBackingStorePixelRatio)||1;const ratio=devicePixelRatio/backingStoreRatio;if(devicePixelRatio!==backingStoreRatio){const oldWidth=opt_width||canvas.width;const oldHeight=opt_height||canvas.height;canvas.width=oldWidth*ratio;canvas.height=oldHeight*ratio;canvas.style.width=oldWidth+"px";canvas.style.height=oldHeight+"px";context.scale(ratio,ratio);return true}else if(devicePixelRatio===1){canvas.style.width=canvas.width+"px";canvas.style.height=canvas.height+"px"}return false};Runner.isAltGameModeEnabled=function(){return loadTimeData&&loadTimeData.valueExists("enableAltGameMode")};function announcePhrase(phrase){if(Runner.a11yStatusEl){Runner.a11yStatusEl.textContent="";Runner.a11yStatusEl.textContent=phrase}}function getA11yString(stringName){return loadTimeData&&loadTimeData.valueExists(stringName)?loadTimeData.getString(stringName):""}function vibrate(duration){if(IS_MOBILE&&window.navigator.vibrate){window.navigator.vibrate(duration)}}function createCanvas(container,width,height,opt_classname){const canvas=document.createElement("canvas");canvas.className=Runner.classes.CANVAS;canvas.width=width;canvas.height=height;container.appendChild(canvas);return canvas}function decodeBase64ToArrayBuffer(base64String){const len=base64String.length/4*3;const str=atob(base64String);const arrayBuffer=new ArrayBuffer(len);const bytes=new Uint8Array(arrayBuffer);for(let i=0;iobstacleBoxX&&tRexBox.yobstacleBox.y){crashed=true}return crashed} // Copyright 2013 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. let showingDetails=false;let lastData=null;function toggleHelpBox(){showingDetails=!showingDetails;assert(lastData);B(getHtml(lastData,showingDetails),getRequiredElement("content"))}function diagnoseErrors(){if(window.errorPageController){window.errorPageController.diagnoseErrorsButtonClick()}}function portalSignin(){if(window.errorPageController){window.errorPageController.portalSigninButtonClick()}}let isSubFrame=false;if(window.top.location!==window.location){document.documentElement.setAttribute("subframe","");isSubFrame=true}function updateForDnsProbe(newData){onTemplateDataReceived(newData)}function getMainFrameErrorCssClass(showingDetails){return showingDetails?"showing-details":""}function getMainFrameErrorIconCssClass(data){return isSubFrame?"":data.iconClass}function getSubFrameErrorIconCssClass(data){return isSubFrame?data.iconClass:""}function shouldShowSuggestionsSummaryList(data){return!!data.suggestionsSummaryList&&data.suggestionsSummaryList.length>0}function getSuggestionsSummaryItemCssClass(data){assert(data.suggestionsSummaryList);return data.suggestionsSummaryList.length===1?"single-suggestion":""}function reloadButtonClick(e){const url=e.target.dataset["url"];if(window.errorPageController){window.errorPageController.reloadButtonClick()}else{assert(url);window.location.href=url}}function downloadButtonClick(){if(window.errorPageController){window.errorPageController.downloadButtonClick();const downloadButton=getRequiredElement("download-button");downloadButton.disabled=true;downloadButton.textContent=downloadButton.disabledText}}function detailsButtonClick(){if(window.errorPageController){window.errorPageController.detailsButtonClick()}toggleHelpBox()}function setAutoFetchState(scheduled,canSchedule){getRequiredElement("cancel-save-page-button").classList.toggle(HIDDEN_CLASS,!scheduled);getRequiredElement("save-page-for-later-button").classList.toggle(HIDDEN_CLASS,!canSchedule)}function savePageLaterClick(){assert(window.errorPageController);window.errorPageController.savePageForLater()}function cancelSavePageClick(){assert(window.errorPageController);window.errorPageController.cancelSavePage();setAutoFetchState(false,true)}function shouldShowControlButtons(data){const downloadButtonVisible=!!data.downloadButton&&!!data.downloadButton.msg;const reloadButtonVisible=!!data.reloadButton&&!!data.reloadButton.msg;return reloadButtonVisible||downloadButtonVisible}function shouldShowDetailsButton(data){return!!data.suggestionsDetails&&data.suggestionsDetails.length>0}function getDetailsButtonCssClass(data){return shouldShowControlButtons(data)?"":"singular"}function getDetailsButtonText(data,showingDetails){assert(data.details);assert(data.hideDetails);return showingDetails?data.hideDetails:data.details}function getButtonsCssClass(){let primaryControlOnLeft=true;primaryControlOnLeft=false;return primaryControlOnLeft?"suggested-left":"suggested-right"}function onDocumentLoad(){onTemplateDataReceived(window.loadTimeDataRaw)}function onTemplateDataReceived(newData){lastData=newData;B(getHtml(lastData,showingDetails),getRequiredElement("content"));if(!isSubFrame&&newData.iconClass==="icon-offline"){document.documentElement.classList.add("offline");loadTimeData.data=newData;new Runner(".interstitial-wrapper")}}function getHtml(data,showingDetails){return x`

${data.summary?x`

`:""} ${shouldShowSuggestionsSummaryList(data)?x`

${data.suggestionsSummaryListHeader}

    ${data.suggestionsSummaryList.map((item=>x`
  • `))}
`:""}
${data.errorCode}
${data.savePageLater?x` `:""}
${data.suggestionsDetails?x`
${data.suggestionsDetails.map((item=>x`
`))}
`:""}
${data.summary?x`
`:""} `}Object.assign(window,{diagnoseErrors:diagnoseErrors,portalSignin:portalSignin,toggleHelpBox:toggleHelpBox,updateForDnsProbe:updateForDnsProbe});document.addEventListener("DOMContentLoaded",onDocumentLoad);

This site can’t be reached

levi.skiperformance.com unexpectedly closed the connection.

Try:

ERR_CONNECTION_CLOSED
Check your Internet connection
Check any cables and reboot any routers, modems, or other network devices you may be using.
Allow Chrome to access the network in your firewall or antivirus settings.
If it is already listed as a program allowed to access the network, try removing it from the list and adding it again.
If you use a proxy server…
Go to the Chrome menu > Settings > Show advanced settings… > Change proxy settings… and make sure your configuration is set to "no proxy" or "direct."
levi.skiperformance.com unexpectedly closed the connection.