This repository was archived by the owner on Sep 7, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgame.js.map
1 lines (1 loc) · 165 KB
/
game.js.map
1
{"version":3,"sources":["../src/pubsub/pubsub.js","../src/pubsub/constants.js","../vendor/sfxr.js","../src/audio/ArcadeAudio.js","../src/audio/sounds.js","../src/audio/index.js","../src/config.js","../src/bomb/createBomb.js","../src/bomb/constants.js","../src/bomb/drawBomb.js","../src/utils/calculateCameraCoordinates.js","../src/directions/constants.js","../src/directions/directionIsAllowed.js","../src/directions/switchDirection.js","../src/directions/directionSwitchMap.js","../src/directions/isIntersection.js","../src/directions/getNextTile.js","../src/utils/degreesToRadians.js","../src/utils/getRandomInt.js","../src/utils/multiCollides.js","../src/utils/collides.js","../src/utils/isValidTile.js","../src/bomb/drawBombWithFuse.js","../src/messageBox/messageBox.js","../src/virus/Viruses.js","../src/virus/createVirus.js","../src/virus/Blips.js","../src/virus/updateVirus.js","../src/virus/utils/moveVirus.js","../src/virus/utils/isInTheMiddle.js","../src/virus/utils/getBestDirections.js","../src/directions/getOppositeDirection.js","../src/virus/drawVirus.js","../src/virus/createBlip.js","../src/virus/drawBlip.js","../src/server/Servers.js","../src/server/createServer.js","../src/map/tilesheet/utils/krakel.js","../src/server/drawServer.js","../src/bomb/updateBomb.js","../src/bomb/createShrapnel.js","../src/bomb/drawShrapnel.js","../src/bomb/Bombs.js","../src/loop/utils/moveCamera.js","../src/pathfinder/utils/extractShortest.js","../src/pathfinder/utils/findShortestPath.js","../src/pathfinder/utils/findPaths.js","../src/pathfinder/utils/convertMapToGraph.js","../src/pathfinder/utils/getNodeByCoords.js","../src/pathfinder/utils/initGraphAndAllowed.js","../src/pathfinder/pathfinder.js","../src/pathfinder/initPathfinder.js","../src/scoreBoard/scoreBoard.js","../src/user/Users.js","../src/user/createUser.js","../src/user/constants.js","../src/user/drawUser.js","../src/loop/createLoop.js","../src/map/tilesheet/drawCurve.js","../src/map/tilesheet/drawStraight.js","../src/map/tilesheet/drawTSection.js","../src/map/tilesheet/drawCrossing.js","../src/map/tilesheet/drawTerminus.js","../src/tileEngine/createTileEngine.js","../src/map/createMap.js","../src/map/utils/addPadding.js","../src/map/tilesheet/createTilesheet.js","../src/player/createPlayer.js","../src/player/drawPlayer.js","../src/utils/calculateRotation.js","../src/player/updatePlayer.js","../src/player/utils/getKey.js","../src/player/utils/isInTheMiddle.js","../src/canvas/createCanvas.js","../src/level/data.js","../src/level/mapHex2Arr.js","../src/level/getLevel.js","../src/gameManager/pressAnyKey.js","../src/gameManager/showStartScreen.js","../src/gameManager/gameManager.js","../src/index.js"],"names":["pubsub","[object Object]","this","subscribers","message","callback","permanent","push","filter","incomingMessage","payload","forEach","GAME_OVER","DROP_BOMB","DROP_SHIP","USERS_POSSIBLY_OFFLINE","BOMB_EXPLODES","INFECTED","LEVEL_COMPLETED","SERVER_INFECTED","SERVER_DESTROYED","SCORE","synth","_envelopeLength0","_envelopeLength1","_envelopeLength2","_period","_maxPeriod","_slide","_deltaSlide","_changeAmount","_changeTime","_changeLimit","_squareDuty","_dutySweep","_params","setSettings","values","i","String","fromCharCode","c","totalTime","e","multiplier","reset","p","f","g","h","a","n","o","l","m","totalReset","synthWave","buffer","length","_filters","s","v","_hpFilterCutoff","_lpFilterCutoff","_lpFilterOn","_masterVolume","x","_minFreqency","_phaser","q","r","_phaserDeltaOffset","_phaserOffset","_sustainPunch","d","_waveType","_envelopeLength","_envelopeOverLength0","_envelopeOverLength1","_envelopeOverLength2","_lpFilterDamping","_lpFilterOldPos","_periodTemp","_phaserInt","_pos","_finished","_envelopeStage","_envelopeTime","_envelopeVolume","_hpFilterPos","_lpFilterDeltaPos","_lpFilterPos","_phase","_phaserPos","_sample","_superSample","_phaserBuffer","Array","_noiseBuffer","Math","random","j","abs","jsfxr","settings","envelopeFullLength","data","Uint8Array","used","Uint16Array","dv","Uint32Array","output","slice","ArcadeAudio","aa","sounds","add","prototype","key","count","elem","index","tick","pool","audio","Audio","src","play","sound","soundData","floor","canvasWidth","canvasHeight","virusBlipInterval","createBomb","map","row","col","y","getXAndY","context","kontra","collisionRadius","fuseLength","status","FUSE_BURNING","shrapnel","explosionDuration","mapX","mapY","updateBomb","drawBomb","EXPLODED","sprite","drawBombWithFuse","render","calculateCameraCoordinates","sx","tileWidth","sy","tileHeight","N","E","S","W","directionIsAllowed","direction","tile","tileAtLayer","isValidTile","directionSwitchMap","allowed","includes","nextTile","getNextTile","switchDirection","curr","Error","nextDirection","change","otherDirections","dir","getRandomInt","1","2","3","4","5","6","9","10","11","12","13","7","8","15","16","intersectionTiles","Object","entries","Number","deg2rad","degrees","PI","ri","b","min","max","multiCollides","arr1","arr2","collisions","i1","sprite1","i2","sprite2","collides","dx","dy","sqrt","ctx","save","translate","rotate","lineWidth","strokeStyle","fillStyle","beginPath","moveTo","lineTo","arc","fill","stroke","fuseDeg","sparkCX","cos","sparkCY","sin","sparkX","sparkY","fillRect","restore","messageBox","timeoutHandler","div","document","createElement","setAttribute","getElementById","appendChild","clearTimeout","style","transition","innerHTML","opacity","setTimeout","viruses","gameInactive","cb","subscribe","virusConfig","virus","update","activeViruses","dropped","spawn","flash","server","servers","getRandom","speed","createVirus","getRowAndCol","interval","intervalId","setInterval","checkGameStatusWhenAllSpawned","clearInterval","publish","blips","createBlip","blip","ttl","visits","height","width","updateVirus","drawVirus","start","moveVirus","isInTheMiddle","isIntersection","bestDirections","viable","minVis","MAX_SAFE_INTEGER","vis","getBestDirection","getOppositeDirection","closePath","radius","drawBlip","serverCoordinates","nextServerPointer","createServer","find","broken","allViruses","getAll","availableServers","getAvailableServers","infected","error","getAvailableServersForDirection","isNextPointerInRange","drawServer","krakel","draw","createShrapnel","destroy","changeTile","rotation","rotationDir","drawShrapnel","Bombs","bombs","mapCoords","dropBomb","bomb","extractShortest","predecessors","end","nodes","u","undefined","get","reverse","findShortestPath","graph","shift","path","shortest","findPaths","concat","apply","costs","Map","open","addToOpen","cost","vertex","vertices","set","size","currentCost","from","keys","sort","bucket","node","adjacentNodes","delete","totalCost","vertexCost","convertMapToGraph","layers","layer","initGraphAndAllowed","adjacent","currAllowed","target","getNodeByCoords","layerData","pathfinder","coords","initPathfinder","changedMap","setDataFromMap","LSKEY","scoreBoard","score","highScore","localStorage","getItem","points","winPoints","setItem","online","offline","users","getStats","createUser","virusesWithRowAndCol","getAllWithRowAndCol","goneOffline","user","getOnlineUsers","isReachable","OFFLINE","endLevelOrGame","show","ONLINE","reduce","acc","userVirusCollisions","infect","someViruses","allOnlineUsers","drawUser","INFECTED_EVENT","spriteMapping","fg","bg","createLoop","player","shipMoving","gameLoop","getInfectedServers","teleport","moveCamera","calculatePointOnArc","deg","drawCurve","drawStraight","drawTSection","drawCrossing","drawTerminus","createTileEngine","properties","mapWidth","mapHeight","canvas","offscreenCanvas","offscreenContext","getContext","sxMax","syMax","_sx","_sy","layerOrder","tileEngine","tilesets","addTilesets","tileset","tilesetImage","image","firstGrid","lastTileset","tiles","Infinity","lastIndexOf","substr","assets","images","numTiles","lastGrid","addLayers","value","isArray","name","zIndex","prop","hasOwnProperty","JSON","parse","layerIndex","dataIndex","len","renderTile","preRenderImage","layerId","position","getIndex","drawImage","renderLayer","getRow","getCol","startX","startY","viewWidth","ceil","tileOffset","w","getTileset","currTile","clear","clearRect","createMap","async","mapPadding","paddedMap","arr","pad","retVal","idx","addPadding","Image","toDataURL","Promise","resolve","createTilesheet","createPlayer","scale","dropping","bombCoolingDown","teleportToServer","teleportCoolingDown","updatePlayer","drawPlayer","virusesOrServers","nextServer","getNext","playerWithRowAndCol","playerCannotReachTheseVirusesByPath","playerCanReachTheseVirusesFromServers","playerCannotReachTheseVirusesAtAll","virusByPath","virusServer","infectAllReachable","canReachVirus","degreesToRadians","calculateRotation","pressed","getKey","createCanvas","cssText","getLevel","levelIndex","level","hex","split","cc","charCodeAt","conv","mapHex2Arr","pressAnyKey","addEventListener","once","showStartScreen","init","break","nextLevelIndex","loop","stop","levelData","initLevel","startGame","startLevel","finishGame","updateOnlineStatus","startSpawning","enableControls"],"mappings":"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","sourcesContent":["// exported for testing\nexport class Pubsub {\n constructor() {\n this.subscribers = [];\n }\n subscribe(message, callback, permanent = false) {\n this.subscribers.push({ message, callback, permanent });\n }\n reset() {\n this.subscribers = this.subscribers.filter(({ permanent }) => permanent);\n }\n publish(incomingMessage, payload) {\n this.subscribers.forEach(({ message, callback }) => message === incomingMessage && callback(payload));\n }\n}\n\nexport default new Pubsub();\n","export const GAME_OVER = 0;\nexport const DROP_BOMB = 1;\nexport const DROP_SHIP = 2;\nexport const MAP_CHANGED = 3;\nexport const USERS_POSSIBLY_OFFLINE = 4;\nexport const BOMB_EXPLODES = 5;\nexport const INFECTED = 6;\nexport const LEVEL_COMPLETED = 7;\nexport const SERVER_INFECTED = 8;\nexport const SERVER_DESTROYED = 9;\nexport const PLAYER_TELEPORTED = 10;\nexport const SCORE = 11;\n","/**\n * SfxrParams\n *\n * Copyright 2010 Thomas Vian\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * @author Thomas Vian\n */\nfunction SfxrParams() {\n //--------------------------------------------------------------------------\n //\n // Settings String Methods\n //\n //--------------------------------------------------------------------------\n\n /**\n * Parses a settings array into the parameters\n * @param array Array of the settings values, where elements 0 - 23 are\n * a: waveType\n * b: attackTime\n * c: sustainTime\n * d: sustainPunch\n * e: decayTime\n * f: startFrequency\n * g: minFrequency\n * h: slide\n * i: deltaSlide\n * j: vibratoDepth\n * k: vibratoSpeed\n * l: changeAmount\n * m: changeSpeed\n * n: squareDuty\n * o: dutySweep\n * p: repeatSpeed\n * q: phaserOffset\n * r: phaserSweep\n * s: lpFilterCutoff\n * t: lpFilterCutoffSweep\n * u: lpFilterResonance\n * v: hpFilterCutoff\n * w: hpFilterCutoffSweep\n * x: masterVolume\n * @return If the string successfully parsed\n */\n this.setSettings = function(values) {\n for (let i = 0; i < 24; i++) {\n this[String.fromCharCode(97 + i)] = values[i] || 0;\n }\n\n // I moved this here from the reset(true) function\n if (this.c < 0.01) {\n this.c = 0.01;\n }\n\n const totalTime = this.c + this.e;\n if (totalTime < 0.18) {\n const multiplier = 0.18 / totalTime;\n this.c *= multiplier;\n this.e *= multiplier;\n }\n };\n}\n\n/**\n * SfxrSynth\n *\n * Copyright 2010 Thomas Vian\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * @author Thomas Vian\n */\nfunction SfxrSynth() {\n // All variables are kept alive through function closures\n\n //--------------------------------------------------------------------------\n //\n // Sound Parameters\n //\n //--------------------------------------------------------------------------\n\n this._params = new SfxrParams(); // Params instance\n\n //--------------------------------------------------------------------------\n //\n // Synth Variables\n //\n //--------------------------------------------------------------------------\n\n let _envelopeLength0, // Length of the attack stage\n _envelopeLength1, // Length of the sustain stage\n _envelopeLength2, // Length of the decay stage\n _period, // Period of the wave\n _maxPeriod, // Maximum period before sound stops (from minFrequency)\n _slide, // Note slide\n _deltaSlide, // Change in slide\n _changeAmount, // Amount to change the note by\n _changeTime, // Counter for the note change\n _changeLimit, // Once the time reaches this limit, the note changes\n _squareDuty, // Offset of center switching point in the square wave\n _dutySweep; // Amount to change the duty by\n\n //--------------------------------------------------------------------------\n //\n // Synth Methods\n //\n //--------------------------------------------------------------------------\n\n /**\n * Resets the runing variables from the params\n * Used once at the start (total reset) and for the repeat effect (partial reset)\n */\n this.reset = function() {\n // Shorter reference\n const p = this._params;\n\n _period = 100 / (p.f * p.f + 0.001);\n _maxPeriod = 100 / (p.g * p.g + 0.001);\n\n _slide = 1 - p.h * p.h * p.h * 0.01;\n _deltaSlide = -p.i * p.i * p.i * 0.000001;\n\n if (!p.a) {\n _squareDuty = 0.5 - p.n / 2;\n _dutySweep = -p.o * 0.00005;\n }\n\n _changeAmount = p.l > 0 ? 1 - p.l * p.l * 0.9 : 1 + p.l * p.l * 10;\n _changeTime = 0;\n _changeLimit = p.m == 1 ? 0 : (1 - p.m) * (1 - p.m) * 20000 + 32;\n };\n\n // I split the reset() function into two functions for better readability\n this.totalReset = function() {\n this.reset();\n\n // Shorter reference\n const p = this._params;\n\n // Calculating the length is all that remained here, everything else moved somewhere\n _envelopeLength0 = 0;\n _envelopeLength1 = p.c * p.c * 100000;\n _envelopeLength2 = p.e * p.e * 100000 + 10;\n // Full length of the volume envelop (and therefore sound)\n return (_envelopeLength0 + _envelopeLength1 + _envelopeLength2) | 0;\n };\n\n /**\n * Writes the wave to the supplied buffer ByteArray\n * @param buffer A ByteArray to write the wave to\n * @return If the wave is finished\n */\n this.synthWave = function(buffer, length) {\n // Shorter reference\n const p = this._params;\n\n // If the filters are active\n const _filters = p.s != 1 || p.v;\n\n // Cutoff multiplier which adjusts the amount the wave position can move\n\n let _hpFilterCutoff = p.v * p.v * 0.1;\n\n // Speed of the high-pass cutoff multiplier\n\n const _hpFilterDeltaCutoff = 0.0003;\n\n // Cutoff multiplier which adjusts the amount the wave position can move\n\n let _lpFilterCutoff = p.s * p.s * p.s * 0.1;\n\n // Speed of the low-pass cutoff multiplier\n\n const _lpFilterDeltaCutoff = 0.0001;\n\n // If the low pass filter is active\n\n const _lpFilterOn = p.s != 1;\n\n // masterVolume * masterVolume (for quick calculations)\n\n const _masterVolume = p.x * p.x;\n\n // Minimum frequency before stopping\n\n const _minFreqency = p.g;\n\n // If the phaser is active\n\n const _phaser = p.q || p.r;\n\n // Change in phase offset\n\n const _phaserDeltaOffset = p.r * p.r * p.r * 0.2;\n\n // Phase offset for phaser effect\n\n let _phaserOffset = p.q * p.q * (p.q < 0 ? -1020 : 1020);\n\n // Once the time reaches this limit, some of the iables are reset\n\n // The punch factor (louder at begining of sustain)\n\n const _sustainPunch = p.d;\n\n // The type of wave to generate\n\n const _waveType = p.a;\n\n let _envelopeLength = _envelopeLength0;\n // Length of the current envelope stage\n\n const _envelopeOverLength0 = 1 / _envelopeLength0;\n // (for quick calculations)\n\n const _envelopeOverLength1 = 1 / _envelopeLength1;\n // (for quick calculations)\n\n const _envelopeOverLength2 = 1 / _envelopeLength2; // (for quick calculations)\n\n // Damping muliplier which restricts how fast the wave position can move\n let _lpFilterDamping = 5 * (0.01 + _lpFilterCutoff);\n if (_lpFilterDamping > 0.8) {\n _lpFilterDamping = 0.8;\n }\n _lpFilterDamping = 1 - _lpFilterDamping;\n\n let _finished = false;\n // If the sound has finished\n\n let _envelopeStage = 0;\n // Current stage of the envelope (attack, sustain, decay, end)\n\n let _envelopeTime = 0;\n // Current time through current enelope stage\n\n let _envelopeVolume = 0;\n // Current volume of the envelope\n\n let _hpFilterPos = 0;\n // Adjusted wave position after high-pass filter\n\n let _lpFilterDeltaPos = 0;\n // Change in low-pass wave position, as allowed by the cutoff and damping\n\n let _lpFilterOldPos,\n\n\n // Previous low-pass wave position\n\n\n _lpFilterPos = 0;\n\n\n\n // Adjusted wave position after low-pass filter\n\n\n\n let _periodTemp,\n\n\n // Period modified by vibrato\n\n _phase = 0;\n\n\n // Phase through the wave\n\n\n let _phaserInt;\n\n // Integer phaser offset, for bit maths\n\n let _phaserPos = 0;\n\n // Position through the phaser buffer\n\n let _pos,\n\n\n\n // Phase expresed as a Number from 0-1, used for fast sin approx\n\n\n\n\n _repeatTime = 0;\n\n\n\n\n // Counter for the repeats\n\n\n\n\n\n var _sample;\n\n\n\n\n // Sub-sample calculated 8 times per actual sample, averaged out to get the super sample\n\n\n\n\n\n var _superSample;\n // Actual sample writen to the wave\n\n let _vibratoPhase = 0; // Phase through the vibrato sine wave\n\n // Buffer of wave values used to create the out of phase second wave\n const _phaserBuffer = new Array(1024);\n\n // Buffer of random values used to generate noise\n\n const _noiseBuffer = new Array(32);\n for (var i = _phaserBuffer.length; i--; ) {\n _phaserBuffer[i] = 0;\n }\n for (var i = _noiseBuffer.length; i--; ) {\n _noiseBuffer[i] = Math.random() * 2 - 1;\n }\n\n for (var i = 0; i < length; i++) {\n if (_finished) {\n return i;\n }\n\n // If _changeLimit is reached, shifts the pitch\n if (_changeLimit) {\n if (++_changeTime >= _changeLimit) {\n _changeLimit = 0;\n _period *= _changeAmount;\n }\n }\n\n // Acccelerate and apply slide\n _slide += _deltaSlide;\n _period *= _slide;\n\n // Checks for frequency getting too low, and stops the sound if a minFrequency was set\n if (_period > _maxPeriod) {\n _period = _maxPeriod;\n if (_minFreqency > 0) {\n _finished = true;\n }\n }\n\n _periodTemp = _period;\n\n _periodTemp |= 0;\n if (_periodTemp < 8) {\n _periodTemp = 8;\n }\n\n // Sweeps the square duty\n if (!_waveType) {\n _squareDuty += _dutySweep;\n if (_squareDuty < 0) {\n _squareDuty = 0;\n } else if (_squareDuty > 0.5) {\n _squareDuty = 0.5;\n }\n }\n\n // Moves through the different stages of the volume envelope\n if (++_envelopeTime > _envelopeLength) {\n _envelopeTime = 0;\n\n switch (++_envelopeStage) {\n case 1:\n _envelopeLength = _envelopeLength1;\n break;\n case 2:\n _envelopeLength = _envelopeLength2;\n }\n }\n\n // Sets the volume based on the position in the envelope\n switch (_envelopeStage) {\n case 0:\n _envelopeVolume = _envelopeTime * _envelopeOverLength0;\n break;\n case 1:\n _envelopeVolume = 1 + (1 - _envelopeTime * _envelopeOverLength1) * 2 * _sustainPunch;\n break;\n case 2:\n _envelopeVolume = 1 - _envelopeTime * _envelopeOverLength2;\n break;\n case 3:\n _envelopeVolume = 0;\n _finished = true;\n }\n\n // Moves the phaser offset\n if (_phaser) {\n _phaserOffset += _phaserDeltaOffset;\n _phaserInt = _phaserOffset | 0;\n if (_phaserInt < 0) {\n _phaserInt = -_phaserInt;\n } else if (_phaserInt > 1023) {\n _phaserInt = 1023;\n }\n }\n\n // Moves the high-pass filter cutoff\n if (_filters && _hpFilterDeltaCutoff) {\n _hpFilterCutoff *= _hpFilterDeltaCutoff;\n if (_hpFilterCutoff < 0.00001) {\n _hpFilterCutoff = 0.00001;\n } else if (_hpFilterCutoff > 0.1) {\n _hpFilterCutoff = 0.1;\n }\n }\n\n _superSample = 0;\n for (let j = 8; j--; ) {\n // Cycles through the period\n _phase++;\n if (_phase >= _periodTemp) {\n _phase %= _periodTemp;\n\n // Generates new random noise for this period\n if (_waveType == 3) {\n for (let n = _noiseBuffer.length; n--; ) {\n _noiseBuffer[n] = Math.random() * 2 - 1;\n }\n }\n }\n\n // Gets the sample from the oscillator\n switch (_waveType) {\n case 0: // Square wave\n _sample = _phase / _periodTemp < _squareDuty ? 0.5 : -0.5;\n break;\n case 1: // Saw wave\n _sample = 1 - (_phase / _periodTemp) * 2;\n break;\n case 2: // Sine wave (fast and accurate approx)\n _pos = _phase / _periodTemp;\n _pos = _pos > 0.5 ? (_pos - 1) * 6.28318531 : _pos * 6.28318531;\n _sample =\n _pos < 0\n ? 1.27323954 * _pos + 0.405284735 * _pos * _pos\n : 1.27323954 * _pos - 0.405284735 * _pos * _pos;\n _sample =\n _sample < 0\n ? 0.225 * (_sample * -_sample - _sample) + _sample\n : 0.225 * (_sample * _sample - _sample) + _sample;\n break;\n case 3: // Noise\n _sample = _noiseBuffer[Math.abs(((_phase * 32) / _periodTemp) | 0)];\n }\n\n // Applies the low and high pass filters\n if (_filters) {\n _lpFilterOldPos = _lpFilterPos;\n _lpFilterCutoff *= _lpFilterDeltaCutoff;\n if (_lpFilterCutoff < 0) {\n _lpFilterCutoff = 0;\n } else if (_lpFilterCutoff > 0.1) {\n _lpFilterCutoff = 0.1;\n }\n\n if (_lpFilterOn) {\n _lpFilterDeltaPos += (_sample - _lpFilterPos) * _lpFilterCutoff;\n _lpFilterDeltaPos *= _lpFilterDamping;\n } else {\n _lpFilterPos = _sample;\n _lpFilterDeltaPos = 0;\n }\n\n _lpFilterPos += _lpFilterDeltaPos;\n\n _hpFilterPos += _lpFilterPos - _lpFilterOldPos;\n _hpFilterPos *= 1 - _hpFilterCutoff;\n _sample = _hpFilterPos;\n }\n\n // Applies the phaser effect\n if (_phaser) {\n _phaserBuffer[_phaserPos % 1024] = _sample;\n _sample += _phaserBuffer[(_phaserPos - _phaserInt + 1024) % 1024];\n _phaserPos++;\n }\n\n _superSample += _sample;\n }\n\n // Averages out the super samples and applies volumes\n _superSample *= 0.125 * _envelopeVolume * _masterVolume;\n\n // Clipping if too loud\n buffer[i] = _superSample >= 1 ? 32767 : _superSample <= -1 ? -32768 : (_superSample * 32767) | 0;\n }\n\n return length;\n };\n}\n\n// Adapted from http://codebase.es/riffwave/\nconst synth = new SfxrSynth();\n// Export for the Closure Compiler\nexport default function(settings) {\n // Initialize SfxrParams\n synth._params.setSettings(settings);\n // Synthesize Wave\n const envelopeFullLength = synth.totalReset();\n const data = new Uint8Array((((envelopeFullLength + 1) / 2) | 0) * 4 + 44);\n let used = synth.synthWave(new Uint16Array(data.buffer, 44), envelopeFullLength) * 2;\n const dv = new Uint32Array(data.buffer, 0, 44);\n // Initialize header\n dv[0] = 0x46464952; // \"RIFF\"\n dv[1] = used + 36; // put total size here\n dv[2] = 0x45564157; // \"WAVE\"\n dv[3] = 0x20746d66; // \"fmt \"\n dv[4] = 0x00000010; // size of the following\n dv[5] = 0x00010001; // Mono: 1 channel, PCM format\n dv[6] = 0x0000ac44; // 44,100 samples per second\n dv[7] = 0x00015888; // byte rate: two bytes per sample\n dv[8] = 0x00100002; // 16 bits per sample, aligned on every two bytes\n dv[9] = 0x61746164; // \"data\"\n dv[10] = used; // put number of samples here\n\n // Base64 encoding written by me, @maettig\n used += 44;\n let i = 0;\n\n let output = 'data:audio/wav;base64,';\n for (; i < used; i += 3) {\n const a = (data[i] << 16) | (data[i + 1] << 8) | data[i + 2];\n output +=\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[a >> 18] +\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[(a >> 12) & 63] +\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[(a >> 6) & 63] +\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[a & 63];\n }\n i -= used;\n return output.slice(0, output.length - i) + '=='.slice(0, i);\n}\n","import jsfxr from '../../vendor/sfxr.js';\nimport generateSounds from './sounds.js';\n\nexport default function ArcadeAudio() {\n this.sounds = {};\n generateSounds(this);\n}\n\nArcadeAudio.prototype.add = function(key, count, settings) {\n this.sounds[key] = [];\n settings.forEach(function(elem, index) {\n this.sounds[key].push({\n tick: 0,\n count,\n pool: []\n });\n for (let i = 0; i < count; i++) {\n const audio = new Audio();\n audio.src = jsfxr(elem);\n this.sounds[key][index].pool.push(audio);\n }\n }, this);\n};\n\nArcadeAudio.prototype.play = function(key) {\n const sound = this.sounds[key];\n const soundData = sound.length > 1 ? sound[Math.floor(Math.random() * sound.length)] : sound[0];\n soundData.pool[soundData.tick].play();\n if (soundData.tick < soundData.count - 1) {\n soundData.tick++;\n } else {\n soundData.tick = 0;\n }\n};\n","/* eslint-disable no-sparse-arrays */\nexport default function generateSounds(aa) {\n aa.add('infected', 3, [\n [2, , 0.2916, , 0.2587, 0.9356, 0.3909, -0.2493, , , , , , 0.3583, 0.1617, , , , 1, , , 0.1217, , 0.5]\n ]);\n\n aa.add('drop-bomb', 3, [[0, , 0.0641, 0.5296, 0.1228, 0.4195, , , , , , 0.3029, 0.6261, , , , , , 1, , , , , 0.5]]);\n\n aa.add('drop-ship', 1, [\n [0, , 0.57, , 0.1398, 0.61, , -0.26, 0.1, , , 0.02, , 0.3325, , , , , 0.9793, , , , , 0.5]\n ]);\n\n aa.add('explode', 3, [[3, , 0.4, 0.91, 0.25, 0.21, , -0.38, , , , , , , , , -0.0403, -0.186, 1, , , , , 0.5]]);\n}\n/* eslint-enable no-alert, no-console */\n","import { pubsub, DROP_BOMB, BOMB_EXPLODES, INFECTED, DROP_SHIP } from '../pubsub/index.js';\nimport ArcadeAudio from './ArcadeAudio.js';\n\nconst aa = new ArcadeAudio();\n\nexport function initAudio() {\n /* permanent subscribing OK here */\n pubsub.subscribe(DROP_BOMB, () => aa.play('drop-bomb'), true);\n pubsub.subscribe(BOMB_EXPLODES, () => aa.play('explode'), true);\n pubsub.subscribe(INFECTED, () => aa.play('infected'), true);\n pubsub.subscribe(DROP_SHIP, () => aa.play('drop-ship'), true);\n\n /*\n * GENERATE NEW SOUNDS ON http://www.superflashbros.net/as3sfxr/\n * CMD + C copies the values\n *\n * */\n}\n","export const canvasWidth = 800;\nexport const canvasHeight = 600;\n\n/* map */\nexport const tileWidth = 100;\nexport const tileHeight = 100;\nexport const mapPadding = 4;\n\n/* virus */\nexport const virusBlipInterval = 1000;\nexport const virusBlipTtl = 180;\n\n/* colors */\nexport const lightGreen = '#75a042';\nexport const darkGreen = '#365b1d';\nexport const lightBlue = '#52638a';\nexport const darkBlue = '#2b3653';\nexport const lightRed = '#cd3926';\nexport const darkRed = '#7a2431';\n\nexport const collisionRadius = 30;\nexport const bombCooldown = 100;\nexport const teleportCooldownTimeout = 600;\n","/* global kontra */\n\nimport { collisionRadius, tileHeight, tileWidth } from '../config.js';\nimport { drawBomb, updateBomb } from './index.js';\nimport { FUSE_BURNING } from './index.js';\n\nexport default (map, { row, col }) => {\n const { x, y } = map.getXAndY({ row, col });\n return {\n context: kontra.context,\n x,\n y,\n collisionRadius,\n fuseLength: 100,\n status: FUSE_BURNING,\n shrapnel: [],\n explosionDuration: 0,\n map,\n mapX: col * tileWidth,\n mapY: row * tileHeight,\n row,\n col,\n update() {\n ({\n status: this.status,\n fuseLength: this.fuseLength,\n explosionDuration: this.explosionDuration,\n x: this.x,\n y: this.y\n } = updateBomb(this));\n },\n render() {\n drawBomb(this);\n }\n };\n};\n","export const FUSE_BURNING = 0;\nexport const EXPLODING = 1;\nexport const EXPLODED = 2;\n","import { EXPLODING, FUSE_BURNING } from './constants.js';\nimport { drawBombWithFuse } from './index.js';\n\nexport default sprite => {\n const { status, shrapnel } = sprite;\n switch (status) {\n case FUSE_BURNING:\n drawBombWithFuse(sprite);\n break;\n case EXPLODING:\n shrapnel.forEach(s => s.render());\n break;\n default:\n }\n};\n","import { tileHeight, tileWidth, canvasWidth, canvasHeight } from '../config.js';\n\nexport default ({ col, row }) => ({\n sx: col * tileWidth - canvasWidth / 2 + tileWidth / 2,\n sy: row * tileHeight - canvasHeight / 2 + tileHeight / 2\n});\n","export const N = 'N';\nexport const E = 'E';\nexport const S = 'S';\nexport const W = 'W';\n","import { directionSwitchMap, getNextTile } from './index.js';\nimport { isValidTile } from '../utils/index.js';\n\nexport default (map, { x, y }, direction) => {\n const tile = map.tileAtLayer('main', { x, y });\n if (!isValidTile(tile) || !directionSwitchMap[tile].allowed.includes(direction)) {\n return false;\n }\n const nextTile = getNextTile(map, { x, y }, direction);\n return isValidTile(nextTile);\n};\n","import { directionSwitchMap, directionIsAllowed } from './index.js';\nimport { isValidTile, getRandomInt } from '../utils/index.js';\n\nexport default (map, { x, y }, curr) => {\n const tile = map.tileAtLayer('main', { x, y });\n /* player accidentally stepped onto a broken conduit tile */\n if (!isValidTile(tile)) {\n throw new Error('dropped');\n }\n const nextDirection = directionSwitchMap[tile].change[curr] || curr;\n if (directionIsAllowed(map, { x, y }, nextDirection)) {\n return nextDirection;\n }\n const otherDirections = directionSwitchMap[tile].allowed.filter(dir => directionIsAllowed(map, { x, y }, dir));\n switch (otherDirections.length) {\n case 0:\n /* oh no, player locked themselves in! */\n throw new Error('locked in');\n case 1:\n return otherDirections[0];\n default:\n return otherDirections[getRandomInt(0, otherDirections.length - 1)];\n }\n};\n","import { N, E, S, W } from './index.js';\n\nexport default {\n // curve from S to E\n 1: {\n allowed: [S, E],\n change: {\n [N]: E,\n [W]: S\n }\n },\n // curve from W to S\n 2: {\n allowed: [W, S],\n change: {\n [N]: W,\n [E]: S\n }\n },\n // straight from N to S\n 3: {\n allowed: [N, S],\n change: {}\n },\n // T section W, N, E\n 4: {\n allowed: [W, N, E],\n change: {\n [S]: N\n }\n },\n // T section N, E, S\n 5: {\n allowed: [N, E, S],\n change: {\n [W]: E\n }\n },\n // T section W, E, S\n 6: {\n allowed: [W, E, S],\n change: {\n [N]: S\n }\n },\n // curve from N to E\n 9: {\n allowed: [N, E],\n change: {\n [S]: E,\n [W]: N\n }\n },\n // curve from W to N\n 10: {\n allowed: [W, N],\n change: {\n [E]: N,\n [S]: W\n }\n },\n // straight from W to E\n 11: {\n allowed: [W, E],\n change: {}\n },\n // crossing\n 12: {\n allowed: [N, E, S, W],\n change: {}\n },\n // T section N, S, W\n 13: {\n allowed: [N, S, W],\n change: {\n [E]: W\n }\n },\n // terminus S\n 7: {\n allowed: [S],\n change: {\n [N]: S\n }\n },\n // terminus W\n 8: {\n allowed: [W],\n change: {\n [E]: W\n }\n },\n // terminus N\n 15: {\n allowed: [N],\n change: {\n [S]: N\n }\n },\n // terminus E\n 16: {\n allowed: [E],\n change: {\n [W]: E\n }\n }\n};\n","import { directionSwitchMap } from './index.js';\n\nconst intersectionTiles = [];\nfor (const [tile, { allowed }] of Object.entries(directionSwitchMap)) {\n if (allowed.length > 2) {\n intersectionTiles.push(Number(tile));\n }\n}\n\nexport default tile => intersectionTiles.includes(tile);\n","import { N, E, S, W } from './index.js';\nimport { tileHeight, tileWidth } from '../config.js';\n\nexport default (map, { x, y }, direction) =>\n map.tileAtLayer('main', {\n x: direction === E ? x + tileWidth : direction === W ? x - tileWidth : x,\n y: direction === N ? y - tileHeight : direction === S ? y + tileHeight : y\n });\n","export default degrees => (degrees * Math.PI) / 180;\n","export default (a, b) => {\n const min = Math.min(a, b);\n const max = Math.max(a, b);\n return Math.floor(Math.random() * (max - min + 1)) + min;\n};\n","import { collides } from './index.js';\n\nexport default (arr1, arr2) => {\n const collisions = [];\n for (let i1 = 0; i1 < arr1.length; i1++) {\n const sprite1 = arr1[i1];\n for (let i2 = 0; i2 < arr2.length; i2++) {\n const sprite2 = arr2[i2];\n if (collides(sprite1, sprite2)) {\n collisions.push([sprite1, sprite2]);\n }\n }\n }\n return collisions;\n};\n","export default (sprite1, sprite2) => {\n const dx = sprite1.x - sprite2.x;\n const dy = sprite1.y - sprite2.y;\n return Math.sqrt(dx * dx + dy * dy) < sprite1.collisionRadius + sprite2.collisionRadius;\n};\n","export default tile => tile >= 1 && tile <= 16;\n","import { lightRed, lightBlue, darkBlue } from '../config.js';\nimport { getRandomInt as ri } from '../utils/index.js';\nimport { degreesToRadians as deg2rad } from '../utils/index.js';\n\nexport default sprite => {\n const { context: ctx, x, y, fuseLength } = sprite;\n ctx.save();\n ctx.translate(x, y);\n ctx.rotate(deg2rad(-45));\n\n ctx.lineWidth = 3;\n ctx.strokeStyle = lightBlue;\n ctx.fillStyle = darkBlue;\n\n /* bomb */\n ctx.beginPath();\n ctx.moveTo(23, -10);\n ctx.lineTo(40, -10);\n ctx.lineTo(40, 10);\n ctx.lineTo(23, 10);\n ctx.arc(0, 0, 25, deg2rad(19), deg2rad(341));\n ctx.fill();\n ctx.stroke();\n\n /* fuse */\n const fuseRad = 25; // radius of the fuse arc\n const fuseDeg = (fuseLength / 100) * 90; // length of the fuse arc in degrees\n ctx.beginPath();\n ctx.moveTo(40, 0);\n ctx.arc(40, 25, fuseRad, deg2rad(270), deg2rad(270 + fuseDeg));\n ctx.stroke();\n\n /* sparks */\n const sparkCX = Math.cos(deg2rad(fuseDeg - 90)) * fuseRad + 40; // X-coord of sparks center\n const sparkCY = Math.sin(deg2rad(fuseDeg - 90)) * fuseRad + 25; // Y-coord of sparks centers\n const sparkRad = 15; // radius of the sparks circle\n ctx.fillStyle = lightRed;\n for (let i = 0; i < 10; i++) {\n const sparkX = Math.cos(deg2rad(ri(0, 360))) * ri(0, sparkRad) + sparkCX;\n const sparkY = Math.sin(deg2rad(ri(0, 360))) * ri(0, sparkRad) + sparkCY;\n ctx.fillRect(sparkX - 1, sparkY - 1, 3, 3);\n }\n\n ctx.restore();\n};\n","class MessageBox {\n constructor() {\n this.timeoutHandler = null;\n this.div = document.createElement('div');\n this.div.setAttribute('id', 'mbx');\n const wrapper = document.getElementById('wrapper');\n wrapper.appendChild(this.div);\n }\n\n show(message) {\n clearTimeout(this.timeoutHandler);\n this.div.style.transition = '3s';\n this.div.innerHTML = `<div>${message}</div>`;\n this.div.style.opacity = 1;\n }\n\n flash(message) {\n clearTimeout(this.timeoutHandler);\n this.div.style.transition = '0.5s';\n this.div.innerHTML = `<div>${message}</div>`;\n this.div.style.opacity = 1;\n this.timeoutHandler = setTimeout(() => (this.div.style.opacity = 0), 500);\n }\n\n clear() {\n clearTimeout(this.timeoutHandler);\n this.div.style.transition = '0.5s';\n this.div.style.opacity = 0;\n }\n}\nexport default new MessageBox();\n","import { createVirus } from './index.js';\nimport { servers } from '../server/index.js';\nimport { GAME_OVER, LEVEL_COMPLETED, USERS_POSSIBLY_OFFLINE, pubsub } from '../pubsub/index.js';\nimport { messageBox } from '../messageBox/index.js';\n\nclass Viruses {\n constructor() {\n this.viruses = [];\n this.gameInactive = true;\n const cb = () => (this.gameInactive = true);\n pubsub.subscribe(GAME_OVER, cb, true);\n pubsub.subscribe(LEVEL_COMPLETED, cb, true);\n }\n init(map, virusConfig) {\n this.viruses = [];\n this.gameInactive = false;\n this.map = map;\n this.virusConfig = virusConfig;\n }\n update() {\n this.viruses.forEach(virus => virus.update());\n const activeViruses = this.viruses.filter(virus => !virus.dropped);\n\n // if virus was dropped, remove it and spawn a fresh one\n if (activeViruses.length < this.viruses.length) {\n setTimeout(() => this.spawn(), 3000);\n messageBox.flash('Nice one! Virus dropped');\n this.viruses = activeViruses;\n }\n }\n render() {\n this.viruses.forEach(virus => virus.render());\n }\n spawn() {\n const server = servers.getRandom();\n if (!server) {\n return;\n }\n const { row, col } = server;\n const { speed, max } = this.virusConfig;\n if (this.viruses.length < max) {\n this.viruses.push(createVirus({ map: this.map, row, col, speed }));\n }\n }\n getAll() {\n return this.viruses;\n }\n getAllWithRowAndCol() {\n return this.viruses.map(virus => ({\n ...virus,\n ...this.map.getRowAndCol({ x: virus.x, y: virus.y })\n }));\n }\n startSpawning() {\n const { interval, max } = this.virusConfig;\n\n this.intervalId = setInterval(() => {\n if (this.viruses.length < max) {\n this.spawn();\n this.checkGameStatusWhenAllSpawned();\n } else {\n clearInterval(this.intervalId);\n }\n }, interval);\n }\n checkGameStatusWhenAllSpawned() {\n if (this.viruses.length >= this.virusConfig.max) {\n // wait for virus to appear on the screen\n setTimeout(() => pubsub.publish(USERS_POSSIBLY_OFFLINE), 1000);\n }\n }\n reset() {\n clearInterval(this.intervalId);\n }\n}\n\nexport default new Viruses();\n","/* global kontra */\n\nimport { tileWidth, tileHeight, collisionRadius } from '../config.js';\nimport { drawVirus, updateVirus, Blips } from './index.js';\nimport { switchDirection } from '../directions/index.js';\n\nexport default ({ map, col, row, speed }) => {\n const { x, y } = map.getXAndY({ row, col });\n const blips = new Blips();\n const virus = {\n context: kontra.context,\n visits: Array(map.height)\n .fill()\n .map(() => Array(map.width).fill(0)),\n x,\n y,\n speed,\n collisionRadius,\n dropped: false,\n map,\n mapX: col * tileWidth,\n mapY: row * tileHeight,\n direction: switchDirection(map, { x, y }, 'S'),\n blips,\n update() {\n try {\n ({ x: this.x, y: this.y, mapX: this.mapX, mapY: this.mapY, direction: this.direction } = updateVirus(\n this\n ));\n this.blips.update();\n } catch ({ message }) {\n if (message === 'dropped') {\n this.dropped = true;\n }\n }\n },\n render() {\n drawVirus(this);\n this.blips.render();\n }\n };\n blips.start(virus);\n\n return virus;\n};\n","import { virusBlipInterval } from '../config.js';\nimport { createBlip } from './index.js';\n\nexport default class {\n constructor() {\n this.blips = [];\n }\n\n start(virus) {\n setInterval(() => {\n this.blips.push(createBlip({ x: virus.x, y: virus.y }));\n }, virusBlipInterval);\n }\n update() {\n this.blips.forEach(blip => blip.update());\n this.blips = this.blips.filter(blip => blip.ttl > 0);\n }\n render() {\n this.blips.forEach(blip => blip.render());\n }\n}\n","import {\n switchDirection,\n isIntersection,\n directionSwitchMap,\n getOppositeDirection,\n directionIsAllowed\n} from '../directions/index.js';\nimport { getRandomInt } from '../utils/index.js';\nimport { isInTheMiddle, moveVirus, getBestDirection } from './utils/index.js';\n\nexport default sprite => {\n let { direction } = sprite;\n const { map, visits } = sprite;\n const { mapX, mapY } = moveVirus(sprite);\n const { x, y } = map.getXAndY({ mapX, mapY });\n if (isInTheMiddle({ mapX, mapY })) {\n const tile = map.tileAtLayer('main', { x, y });\n const { col, row } = map.getRowAndCol({ x, y });\n visits[row][col]++;\n if (isIntersection(tile)) {\n const { allowed } = directionSwitchMap[tile];\n const viable = allowed.filter(\n dir => dir !== getOppositeDirection(direction) && directionIsAllowed(map, { x, y }, dir)\n );\n const bestDirections = getBestDirection({ viable, visits, row, col });\n direction = bestDirections[getRandomInt(0, bestDirections.length - 1)];\n } else {\n try {\n direction = switchDirection(map, { x, y }, direction);\n } catch ({ message }) {\n throw new Error(message);\n }\n }\n }\n return {\n direction,\n mapY,\n mapX,\n x,\n y\n };\n};\n","import { N, E, S, W } from '../../directions/index.js';\n\nexport default ({ mapX, mapY, direction, speed }) => {\n switch (direction) {\n case N:\n return { mapX, mapY: mapY - speed };\n case E:\n return { mapX: mapX + speed, mapY };\n case S:\n return { mapX, mapY: mapY + speed };\n case W:\n return { mapX: mapX - speed, mapY };\n default:\n return { mapX, mapY };\n }\n};\n","import { tileHeight, tileWidth } from '../../config.js';\n\nexport default ({ mapX, mapY }) => mapX % tileWidth === 0 && mapY % tileHeight === 0;\n","import { N, E, S, W } from '../../directions/index.js';\n\nexport default ({ viable, visits, row, col }) => {\n let minVis = Number.MAX_SAFE_INTEGER;\n return viable\n .map(dir => {\n let vis;\n switch (dir) {\n case N:\n vis = visits[row - 1][col];\n break;\n case E:\n vis = visits[row][col + 1];\n break;\n case S:\n vis = visits[row + 1][col];\n break;\n case W:\n vis = visits[row][col - 1];\n break;\n default:\n }\n minVis = vis < minVis ? vis : minVis;\n return { dir, vis };\n })\n .filter(({ vis }) => vis === minVis)\n .map(({ dir }) => dir);\n};\n","import { N, E, S, W } from './index.js';\n\nexport default direction => {\n switch (direction) {\n case N:\n return S;\n case E:\n return W;\n case S:\n return N;\n case W:\n return W;\n default:\n return null;\n }\n};\n","import { lightRed, darkRed } from '../config.js';\nimport { getRandomInt as ri } from '../utils/index.js';\n\nexport default sprite => {\n const { context: ctx, x, y } = sprite;\n ctx.save();\n ctx.translate(x, y);\n\n ctx.lineWidth = 3;\n ctx.strokeStyle = lightRed;\n ctx.fillStyle = darkRed;\n ctx.beginPath();\n ctx.moveTo(ri(-5, 5), ri(-5, -25)); // 1\n ctx.lineTo(ri(5, 50), ri(-5, -50)); // 2\n ctx.lineTo(ri(5, 25), ri(-5, 5)); // 3\n ctx.lineTo(ri(5, 50), ri(5, 50)); // 4\n ctx.lineTo(ri(-5, 5), ri(5, 25)); // 5\n ctx.lineTo(ri(-5, -50), ri(5, 50)); // 6\n ctx.lineTo(ri(-5, -25), ri(-5, 5)); // 7\n ctx.lineTo(ri(-5, -50), ri(-5, -50)); // 8\n ctx.closePath();\n ctx.fill();\n ctx.stroke();\n\n ctx.restore();\n};\n","/* global kontra */\n\nimport { tileHeight, virusBlipTtl } from '../config.js';\nimport { drawBlip } from './index.js';\n\nexport default ({ x, y }) => ({\n context: kontra.context,\n x,\n y,\n ttl: virusBlipTtl,\n radius: tileHeight,\n update() {\n this.radius += 10;\n this.ttl--;\n },\n render() {\n drawBlip(this);\n }\n});\n","import { lightRed } from '../config.js';\nimport { degreesToRadians as deg2rad } from '../utils/index.js';\n\nexport default sprite => {\n const { context: ctx, x, y, radius } = sprite;\n ctx.save();\n ctx.translate(x, y);\n\n ctx.lineWidth = 1;\n ctx.strokeStyle = lightRed;\n ctx.beginPath();\n ctx.arc(0, 0, radius, deg2rad(0), deg2rad(360));\n ctx.closePath();\n ctx.stroke();\n\n ctx.restore();\n};\n","import { createServer } from './index.js';\nimport { multiCollides } from '../utils/index.js';\nimport { messageBox } from '../messageBox/index.js';\nimport { GAME_OVER, LEVEL_COMPLETED, SERVER_INFECTED, SERVER_DESTROYED, pubsub } from '../pubsub/index.js';\nimport { viruses } from '../virus/index.js';\nimport { switchDirection } from '../directions/index.js';\n\nclass Servers {\n constructor() {\n this.servers = [];\n this.gameInactive = true;\n const cb = () => (this.gameInactive = true);\n pubsub.subscribe(GAME_OVER, cb, true);\n pubsub.subscribe(LEVEL_COMPLETED, cb, true);\n }\n /* called at the beginning of every level */\n init(map, serverCoordinates = []) {\n this.servers = [];\n this.gameInactive = false;\n this.map = map;\n this.nextServerPointer = 0;\n serverCoordinates.forEach(({ col, row }) => this.servers.push(createServer({ map, row, col })));\n }\n update() {\n this.servers.forEach(server => server.update());\n }\n render() {\n this.servers.forEach(server => server.render());\n }\n destroy({ col, row }) {\n const server = this.find({ col, row });\n if (server) {\n server.broken = true;\n pubsub.publish(SERVER_DESTROYED);\n }\n }\n infect() {\n const allViruses = viruses.getAll();\n const availableServers = this.getAvailableServers();\n const collisions = multiCollides(availableServers, allViruses);\n\n if (collisions.length === 0) {\n return;\n }\n\n collisions.forEach(([server]) => {\n /* eslint-disable no-param-reassign */\n server.infected = true;\n pubsub.publish(SERVER_INFECTED);\n });\n\n if (this.gameInactive) {\n return;\n }\n\n if (this.getAvailableServers().length === 0) {\n messageBox.flash('all servers destroyed or infected – be careful');\n return;\n }\n\n messageBox.flash('server infected!');\n }\n find({ col, row }) {\n return this.servers.find(server => server.col === col && server.row === row);\n }\n getAvailableServers() {\n return this.servers.filter(server => !(server.broken || server.infected));\n }\n // get servers from where player or virus can still move\n getAvailableServersForDirection() {\n const availableServers = this.getAvailableServers();\n\n return availableServers.filter(server => {\n // check if server location allows to set direction\n try {\n switchDirection(this.map, server, 'S');\n return true;\n } catch (error) {\n return false;\n }\n });\n }\n getRandom() {\n const availableServers = this.getAvailableServersForDirection();\n return availableServers[Math.floor(Math.random() * availableServers.length)];\n }\n getNext() {\n const availableServers = this.getAvailableServersForDirection();\n const isNextPointerInRange = this.nextServerPointer + 1 < availableServers.length;\n this.nextServerPointer = isNextPointerInRange ? this.nextServerPointer + 1 : 0;\n return availableServers[this.nextServerPointer];\n }\n getInfectedServers() {\n return this.servers.filter(server => server.infected);\n }\n}\n\nexport default new Servers();\n","/* global kontra */\n\nimport { drawServer } from './index.js';\nimport { tileWidth, tileHeight, collisionRadius } from '../config.js';\n\nexport default ({ map, row, col }) => {\n const { x, y } = map.getXAndY({ row, col });\n return {\n context: kontra.context,\n x,\n y,\n row,\n col,\n map,\n mapX: col * tileWidth,\n mapY: row * tileHeight,\n broken: false,\n infected: false,\n collisionRadius,\n update() {\n ({ x: this.x, y: this.y } = map.getXAndY({ mapX: this.mapX, mapY: this.mapY }));\n },\n render() {\n drawServer(this);\n }\n };\n};\n","/* creates canvas moveTo and lineTo commands from arrays; doing this mostly to save a couple of bytes */\nexport default (ctx, data) => data.forEach(([draw, x, y]) => ctx[draw ? 'lineTo' : 'moveTo'](x, y));\n","/* eslint-disable no-param-reassign */\nimport { darkBlue, lightBlue, darkRed, lightRed } from '../config.js';\nimport { krakel } from '../map/tilesheet/utils/index.js';\n\nexport default sprite => {\n const { context: ctx, x, y, broken, infected } = sprite;\n ctx.save();\n ctx.translate(x, y);\n ctx.lineWidth = 3;\n ctx.strokeStyle = infected ? lightRed : lightBlue;\n ctx.fillStyle = infected ? darkRed : darkBlue;\n ctx.beginPath();\n krakel(ctx, [\n [0, 30, -48],\n [1, 48, -30],\n [1, 48, 30],\n [1, 30, 48],\n [1, -30, 48],\n [1, -48, 30],\n [1, -48, -30],\n [1, -30, -48],\n [1, 30, -48]\n ]);\n ctx.fill();\n ctx.stroke();\n if (broken) {\n ctx.lineWidth = 2;\n krakel(ctx, [\n [0, 10, -48],\n [1, 0, -40],\n [0, 24, -48],\n [1, 20, -30],\n [0, 48, -27],\n [1, 20, -20],\n [0, -10, -30],\n [1, 10, -30],\n [1, 30, -10],\n [1, 20, 0],\n [1, 10, 0],\n [0, 48, 7],\n [1, 30, 10],\n [0, 20, 0],\n [1, 30, 10],\n [1, 10, 20],\n [0, 30, 48],\n [1, 30, 30],\n [1, 10, 30],\n [0, 20, 20],\n [1, 20, 30],\n [0, -10, 48],\n [1, -10, 20],\n [1, 0, 10],\n [0, -20, 0],\n [1, -20, 20],\n [1, -10, 30],\n [0, -30, 48],\n [1, -20, 40],\n [1, -20, 30],\n [0, -30, 30],\n [1, -20, 40],\n [0, -48, 20],\n [1, -30, 20],\n [0, -40, 20],\n [1, -40, 10],\n [0, -48, 0],\n [1, -30, 0],\n [1, -20, -10],\n [0, -40, 0],\n [1, -30, 10],\n [0, -48, -17],\n [1, -40, -30],\n [1, -30, -20],\n [0, -30, -48],\n [1, -10, -20],\n [1, -10, -10],\n [0, -20, -30],\n [1, -20, -20],\n [1, -30, -10]\n ]);\n ctx.stroke();\n }\n ctx.restore();\n};\n","/* global kontra */\n\nimport { FUSE_BURNING, EXPLODING, EXPLODED } from './index.js';\nimport { createShrapnel } from './index.js';\nimport { pubsub, MAP_CHANGED, USERS_POSSIBLY_OFFLINE, BOMB_EXPLODES } from '../pubsub/index.js';\nimport { servers } from '../server/index.js';\n\nexport default sprite => {\n let { status, fuseLength, explosionDuration, x, y } = sprite;\n const { shrapnel, map, mapX, mapY, row, col } = sprite;\n\n ({ x, y } = map.getXAndY({ mapX, mapY }));\n switch (status) {\n case FUSE_BURNING:\n fuseLength -= 1;\n if (fuseLength < 0) {\n status = EXPLODING;\n pubsub.publish(BOMB_EXPLODES);\n for (let i = 0; i < 50; i++) {\n shrapnel.push(createShrapnel({ x, y }));\n }\n if (servers.find({ row, col })) {\n servers.destroy({ row, col });\n } else {\n const tile = map.tileAtLayer('main', { row, col });\n map.changeTile('main', { row, col }, tile + 16);\n pubsub.publish(MAP_CHANGED, map);\n pubsub.publish(USERS_POSSIBLY_OFFLINE);\n }\n }\n break;\n case EXPLODING:\n shrapnel.forEach(s => s.update());\n explosionDuration++;\n if (explosionDuration === 200) {\n status = EXPLODED;\n }\n break;\n default:\n }\n return {\n status,\n fuseLength,\n explosionDuration,\n x,\n y\n };\n};\n","/* global kontra */\nimport { getRandomInt as ri } from '../utils/index.js';\nimport { degreesToRadians as deg2rad } from '../utils/index.js';\nimport { drawShrapnel } from './index.js';\n\nexport default ({ x, y }) => {\n const dir = ri(0, 360);\n const speed = ri(5, 15);\n return {\n context: kontra.context,\n x,\n y,\n dx: Math.cos(deg2rad(dir)) * speed,\n dy: Math.sin(deg2rad(dir)) * speed,\n rotation: ri(0, 360),\n rotationDir: [ri(-10, -1), ri(1, 10)][ri(0, 1)],\n update() {\n this.x += this.dx;\n this.y += this.dy;\n this.rotation += this.rotationDir;\n },\n render() {\n drawShrapnel(this);\n }\n };\n};\n","import { lightBlue, darkBlue } from '../config.js';\nimport { degreesToRadians as deg2rad } from '../utils/index.js';\n\nexport default sprite => {\n const { context: ctx, x, y, rotation } = sprite;\n ctx.save();\n ctx.translate(x, y);\n ctx.rotate(deg2rad(rotation));\n ctx.lineWidth = 3;\n ctx.strokeStyle = lightBlue;\n ctx.fillStyle = darkBlue;\n ctx.beginPath();\n ctx.moveTo(0, -10);\n ctx.lineTo(10, 5);\n ctx.lineTo(-10, 5);\n ctx.closePath();\n ctx.fill();\n ctx.stroke();\n ctx.restore();\n};\n","import { pubsub, DROP_BOMB } from '../pubsub/index.js';\nimport { EXPLODED } from './constants.js';\nimport { createBomb } from './index.js';\n\nexport default class {\n constructor(map) {\n this.map = map;\n this.bombs = [];\n pubsub.subscribe(DROP_BOMB, mapCoords => this.dropBomb(mapCoords));\n }\n dropBomb(mapCoords) {\n if (\n this.bombs.length > 0 &&\n this.bombs.find(({ col, row }) => col === mapCoords.col && row === mapCoords.row)\n ) {\n // don't drop a bomb where there already is one waiting to explode\n return;\n }\n this.bombs.push(createBomb(this.map, mapCoords));\n }\n update() {\n this.bombs = this.bombs.filter(bomb => {\n bomb.update();\n return bomb.status !== EXPLODED;\n });\n }\n render() {\n this.bombs.forEach(bomb => bomb.render());\n }\n}\n","import { N, E, S, W } from '../../directions/index.js';\n\nexport default ({ map, direction, speed }) => {\n switch (direction) {\n case N:\n // eslint-disable-next-line no-param-reassign\n map.sy -= speed;\n break;\n case E:\n // eslint-disable-next-line no-param-reassign\n map.sx += speed;\n break;\n case S:\n // eslint-disable-next-line no-param-reassign\n map.sy += speed;\n break;\n case W:\n // eslint-disable-next-line no-param-reassign\n map.sx -= speed;\n break;\n default:\n }\n};\n","export default (predecessors, end) => {\n const nodes = [];\n let u = end;\n\n while (u !== undefined) {\n nodes.push(u);\n u = predecessors.get(u);\n }\n\n nodes.reverse();\n return nodes;\n};\n","import { findPaths, extractShortest } from './index.js';\n\nexport default (graph, nodes) => {\n let start = nodes.shift();\n const path = [];\n let end, predecessors, shortest;\n\n while (nodes.length) {\n end = nodes.shift();\n predecessors = findPaths(graph, start, end);\n\n if (predecessors) {\n shortest = extractShortest(predecessors, end);\n if (nodes.length) {\n path.push.apply(path, shortest.slice(0, -1));\n } else {\n return path.concat(shortest);\n }\n } else {\n return null;\n }\n\n start = end;\n }\n return null;\n};\n","export default (data, start, end) => {\n const costs = new Map([[start, 0]]);\n const open = new Map([[0, [start]]]);\n const predecessors = new Map();\n\n function addToOpen(cost, vertex) {\n let vertices = open.get(cost);\n if (!vertices) {\n vertices = [];\n open.set(cost, vertices);\n }\n vertices.push(vertex);\n }\n\n while (open.size > 0) {\n const currentCost = Array.from(open.keys()).sort((a, b) => a - b)[0];\n\n const bucket = open.get(currentCost);\n const node = bucket.shift();\n const adjacentNodes = data.get(node) || new Map();\n\n if (bucket.length === 0) {\n open.delete(currentCost);\n }\n\n for (const [vertex, cost] of adjacentNodes) {\n const totalCost = cost + currentCost;\n const vertexCost = costs.get(vertex);\n\n if (vertexCost === undefined || vertexCost > totalCost) {\n costs.set(vertex, totalCost);\n addToOpen(totalCost, vertex);\n predecessors.set(vertex, node);\n }\n }\n }\n\n return costs.get(end) === undefined ? null : predecessors;\n};\n","import { getNodeByCoords, initGraphAndAllowed } from './index.js';\nimport { N, S, W, E } from '../../directions/index.js';\n\nexport default ({ width, layers }, layer) => {\n const { graph, allowed } = initGraphAndAllowed(layers[layer].data, width);\n for (const [node, adjacent] of graph) {\n const currAllowed = allowed.get(node);\n const { row, col } = node;\n let target;\n for (const dir of currAllowed) {\n switch (dir) {\n case N:\n target = getNodeByCoords(graph, { row: row - 1, col });\n if (target) {\n adjacent.set(target, 1);\n }\n break;\n case E:\n target = getNodeByCoords(graph, { row, col: col + 1 });\n if (target) {\n adjacent.set(target, 1);\n }\n break;\n case S:\n target = getNodeByCoords(graph, { row: row + 1, col });\n if (target) {\n adjacent.set(target, 1);\n }\n break;\n case W:\n target = getNodeByCoords(graph, { row, col: col - 1 });\n if (target) {\n adjacent.set(target, 1);\n }\n break;\n default:\n }\n }\n }\n return graph;\n};\n","export default (graph, { row, col }) => {\n for (const [node] of graph) {\n if (row === node.row && col === node.col) {\n return node;\n }\n }\n return null;\n};\n","import { directionSwitchMap } from '../../directions/index.js';\nimport { isValidTile } from '../../utils/index.js';\n\nexport default (layerData, width) => {\n const graph = new Map();\n const allowed = new Map();\n let row = 0;\n let col = 0;\n let index = 0;\n for (const tile of layerData) {\n if (isValidTile(tile)) {\n const node = { row, col };\n allowed.set(node, directionSwitchMap[tile].allowed);\n graph.set(node, new Map());\n }\n if (++index % width === 0) {\n row++;\n col = 0;\n } else {\n col++;\n }\n }\n return { graph, allowed };\n};\n","import { findShortestPath, convertMapToGraph, getNodeByCoords } from './utils/index.js';\n\nexport class Pathfinder {\n constructor(graph = null) {\n this.graph = graph;\n }\n\n setDataFromMap(map, layer) {\n this.graph = convertMapToGraph(map, layer);\n }\n\n getNodeByCoords(coords) {\n return getNodeByCoords(this.graph, coords);\n }\n\n isReachable(a, b) {\n return findShortestPath(this.graph, [this.getNodeByCoords(a), this.getNodeByCoords(b)]) !== null;\n }\n}\n\nexport default new Pathfinder();\n","import { pathfinder } from './index.js';\nimport { pubsub, MAP_CHANGED } from '../pubsub/index.js';\n\n// permanent subscription OK here\nexport default () => pubsub.subscribe(MAP_CHANGED, changedMap => pathfinder.setDataFromMap(changedMap, 'main'), true);\n","import { users } from '../user/index.js';\nimport { pubsub, SCORE, INFECTED } from '../pubsub/index.js';\n\nconst LSKEY = 'KATAMOV';\nclass ScoreBoard {\n constructor() {\n this.div = document.createElement('div');\n this.div.setAttribute('id', 'scb');\n const wrapper = document.getElementById('wrapper');\n wrapper.appendChild(this.div);\n this.score = 0;\n this.highScore = localStorage.getItem(LSKEY) || 0;\n pubsub.subscribe(SCORE, points => this.winPoints(points), true);\n pubsub.subscribe(INFECTED, () => this.render());\n }\n\n startGame() {\n this.score = 0;\n this.render();\n }\n\n /* called at the beginning of every level */\n initLevel() {\n this.render();\n }\n\n winPoints(points) {\n this.score += points;\n this.highScore = Math.max(this.score, this.highScore);\n localStorage.setItem(LSKEY, this.highScore);\n this.render();\n }\n render() {\n const { infected, online, offline } = users.getStats();\n this.div.innerHTML =\n `${online} online | ` +\n `${offline} offline | ` +\n `${infected} infected | ` +\n `Score: ${this.score} | ` +\n `Highscore: ${this.highScore}`;\n }\n}\n\nexport default new ScoreBoard();\n","import { ONLINE, OFFLINE } from './index.js';\nimport { createUser, INFECTED } from './index.js';\nimport { multiCollides } from '../utils/index.js';\nimport { pubsub, GAME_OVER, LEVEL_COMPLETED, SCORE } from '../pubsub/index.js';\nimport { messageBox } from '../messageBox/index.js';\nimport { pathfinder } from '../pathfinder/index.js';\nimport scoreBoard from '../scoreBoard/scoreBoard.js';\nimport { viruses } from '../virus/index.js';\n\nclass Users {\n constructor() {\n this.users = [];\n this.gameInactive = true;\n const cb = () => (this.gameInactive = true);\n pubsub.subscribe(GAME_OVER, cb, true);\n pubsub.subscribe(LEVEL_COMPLETED, cb, true);\n }\n\n /* called at the beginning of every level */\n init(map) {\n this.users = [];\n this.gameInactive = false;\n this.map = map;\n for (let row = 0; row < map.height; row++) {\n for (let col = 0; col < map.width; col++) {\n const tile = map.tileAtLayer('main', { row, col });\n if (tile === 7 || tile === 8 || tile === 15 || tile === 16) {\n this.users.push(createUser({ map, row, col }));\n }\n }\n }\n }\n\n updateOnlineStatus() {\n const virusesWithRowAndCol = viruses.getAllWithRowAndCol();\n if (virusesWithRowAndCol.length === 0) {\n return;\n }\n\n let goneOffline = 0;\n for (const user of this.getOnlineUsers()) {\n if (virusesWithRowAndCol.filter(virus => pathfinder.isReachable(user, virus)).length === 0) {\n goneOffline++;\n user.status = OFFLINE;\n pubsub.publish(SCORE, 100);\n }\n }\n if (goneOffline > 0) {\n const ended = this.endLevelOrGame();\n if (!ended) {\n messageBox.flash(`${goneOffline} users went offline<br>good job!`);\n }\n }\n }\n\n endLevelOrGame() {\n const { online, offline, infected } = this.getStats();\n if (online > 0) {\n return false;\n }\n if (infected < offline) {\n pubsub.publish(SCORE, offline * 200);\n if (infected === 0) {\n pubsub.publish(SCORE, 500);\n }\n messageBox.show(\n 'level completed<br>' +\n `offline users: ${offline}<br>` +\n `infected users: ${infected}<br>` +\n `score: ${scoreBoard.score}<br><br>` +\n 'press any key'\n );\n pubsub.publish(LEVEL_COMPLETED);\n return true;\n }\n messageBox.show(\n 'game over – too many infected users!<br>' +\n `offline users: ${offline}<br>` +\n `infected users: ${infected}<br>` +\n `score: ${scoreBoard.score}<br><br>` +\n 'press any key to start again'\n );\n pubsub.publish(GAME_OVER);\n return true;\n }\n\n getOnlineUsers() {\n return this.users.filter(({ status }) => status === ONLINE);\n }\n\n getStats() {\n return this.users.reduce(\n (acc, { status }) => ({\n online: acc.online + (status === ONLINE ? 1 : 0),\n offline: acc.offline + (status === OFFLINE ? 1 : 0),\n infected: acc.infected + (status === INFECTED ? 1 : 0)\n }),\n { online: 0, offline: 0, infected: 0 }\n );\n }\n\n update() {\n this.users.forEach(user => user.update());\n }\n\n render() {\n this.users.forEach(user => user.render());\n }\n\n infect() {\n const allViruses = viruses.getAll();\n const { users, gameInactive } = this;\n const userVirusCollisions = multiCollides(users, allViruses).filter(([user]) => user.status !== INFECTED);\n if (userVirusCollisions.length === 0) {\n return;\n }\n userVirusCollisions.forEach(([user]) => user.infect());\n if (gameInactive) {\n return;\n }\n const ended = this.endLevelOrGame();\n if (!ended) {\n messageBox.flash('user infected!');\n }\n }\n\n infectAllReachable(someViruses) {\n if (someViruses.length === 0) {\n return;\n }\n\n const allOnlineUsers = this.getOnlineUsers();\n\n someViruses.forEach(virus => {\n allOnlineUsers.forEach(user => {\n if (pathfinder.isReachable(user, virus)) {\n user.infect();\n }\n });\n });\n\n this.endLevelOrGame();\n }\n}\n\nexport default new Users();\n","/* global kontra */\n\nimport { drawUser, INFECTED } from './index.js';\nimport { tileWidth, tileHeight, collisionRadius } from '../config.js';\nimport { ONLINE } from './index.js';\nimport { pubsub, INFECTED as INFECTED_EVENT } from '../pubsub/index.js';\n\nexport default ({ map, row, col }) => {\n const { x, y } = map.getXAndY({ row, col });\n return {\n context: kontra.context,\n x,\n y,\n collisionRadius,\n infected: false,\n map,\n mapX: col * tileWidth,\n mapY: row * tileHeight,\n row,\n col,\n status: ONLINE,\n update() {\n ({ x: this.x, y: this.y } = map.getXAndY({ mapX: this.mapX, mapY: this.mapY }));\n },\n render() {\n drawUser(this);\n },\n infect() {\n this.status = INFECTED;\n pubsub.publish(INFECTED_EVENT);\n }\n };\n};\n","export const ONLINE = 0;\nexport const OFFLINE = 1;\nexport const INFECTED = 2;\n","/* global kontra */\nimport { lightBlue, darkBlue, lightGreen, darkGreen, lightRed, darkRed } from '../config.js';\nimport { ONLINE, OFFLINE, INFECTED } from './constants.js';\nimport { degreesToRadians as deg2rad } from '../utils/index.js';\n\nconst spriteMapping = {\n [ONLINE]: { fg: lightBlue, bg: darkBlue },\n [OFFLINE]: { fg: lightGreen, bg: darkGreen },\n [INFECTED]: { fg: lightRed, bg: darkRed }\n};\n\nexport default sprite => {\n const { context: ctx, x, y, status } = sprite;\n const { fg, bg } = spriteMapping[status];\n ctx.save();\n ctx.translate(x, y);\n ctx.lineWidth = 3;\n ctx.strokeStyle = fg;\n ctx.fillStyle = bg;\n ctx.beginPath();\n ctx.moveTo(-40, 40);\n ctx.lineTo(-40, 20);\n ctx.arc(-20, 20, 20, deg2rad(180), deg2rad(270));\n ctx.moveTo(-20, 0);\n ctx.lineTo(20, 0);\n ctx.arc(20, 20, 20, deg2rad(270), deg2rad(0));\n ctx.lineTo(40, 40);\n ctx.lineTo(-40, 40);\n ctx.moveTo(-23, 20);\n ctx.lineTo(-23, 40);\n ctx.moveTo(23, 20);\n ctx.lineTo(23, 40);\n ctx.fill();\n ctx.stroke();\n ctx.beginPath();\n ctx.arc(0, -15, 25, deg2rad(0), deg2rad(360));\n ctx.fill();\n ctx.stroke();\n ctx.restore();\n};\n","/* global kontra */\n\nimport { moveCamera } from './utils/index.js';\nimport { pubsub, DROP_SHIP } from '../pubsub/index.js';\nimport { servers } from '../server/index.js';\nimport { viruses } from '../virus/index.js';\nimport { users } from '../user/index.js';\n\nexport default ({ map, player, bombs }) => {\n const times = [];\n let fps;\n let shipMoving = true;\n pubsub.subscribe(DROP_SHIP, () => (shipMoving = false));\n\n return kontra.gameLoop({\n update() {\n viruses.update();\n player.update();\n player.infect([...servers.getInfectedServers(), ...viruses.getAll()]); // TODO\n player.teleport();\n if (shipMoving) {\n moveCamera({ map, ...player });\n }\n users.update();\n users.infect();\n bombs.update();\n servers.update();\n servers.infect();\n },\n render() {\n map.render();\n users.render();\n servers.render();\n bombs.render();\n player.render();\n viruses.render();\n if (process.env.NODE_ENV === 'development') {\n const now = performance.now();\n while (times.length > 0 && times[0] <= now - 1000) {\n times.shift();\n }\n times.push(now);\n fps = times.length;\n const { row, col } = map.getRowAndCol({ x: 400, y: 300 });\n\n // eslint-disable-next-line no-param-reassign\n window.devbox.innerHTML = `${fps} fps – sx=${map.sx}, sy=${map.sy}, row=${row}, col=${col}`;\n }\n }\n });\n};\n","/* eslint-disable no-param-reassign */\nimport { degreesToRadians as deg2rad } from '../../utils/index.js';\nimport { tileHeight, tileWidth, lightBlue } from '../../config.js';\n\nfunction calculatePointOnArc(deg, r) {\n return [Math.cos(deg2rad(deg)) * r + 50, Math.sin(deg2rad(deg)) * r + 50];\n}\n\nexport default ({ ctx, row, col, deg, broken = false }) => {\n ctx.save();\n ctx.translate((col - 1) * tileWidth + tileWidth / 2, (row - 1) * tileHeight + tileHeight / 2);\n ctx.rotate(deg2rad(deg));\n ctx.lineWidth = 3;\n ctx.strokeStyle = lightBlue;\n ctx.beginPath();\n if (broken) {\n ctx.moveTo(20, 50);\n ctx.arc(50, 50, 30, deg2rad(180), deg2rad(190));\n ctx.moveTo(...calculatePointOnArc(190, 30));\n ctx.lineTo(10, 45);\n ctx.lineTo(10, 35);\n ctx.lineTo(-10, 40);\n ctx.lineTo(...calculatePointOnArc(190, 70));\n ctx.arc(50, 50, 70, deg2rad(190), deg2rad(180), true);\n ctx.moveTo(50, 20);\n ctx.arc(50, 50, 30, deg2rad(270), deg2rad(260), true);\n ctx.moveTo(...calculatePointOnArc(260, 30));\n ctx.lineTo(40, 10);\n ctx.lineTo(45, 0);\n ctx.lineTo(35, 0);\n ctx.lineTo(...calculatePointOnArc(260, 70));\n ctx.arc(50, 50, 70, deg2rad(260), deg2rad(270));\n } else {\n ctx.moveTo(20, 50);\n ctx.arc(50, 50, 30, deg2rad(180), deg2rad(270));\n ctx.moveTo(-20, 50);\n ctx.arc(50, 50, 70, deg2rad(180), deg2rad(270));\n }\n ctx.stroke();\n ctx.restore();\n};\n","/* eslint-disable no-param-reassign */\nimport { tileWidth, tileHeight, lightBlue } from '../../config.js';\nimport { degreesToRadians as deg2rad } from '../../utils/index.js';\nimport { krakel } from './utils/index.js';\n\nexport default ({ ctx, row, col, deg, broken = false }) => {\n ctx.save();\n ctx.translate((col - 1) * tileWidth + tileWidth / 2, (row - 1) * tileHeight + tileHeight / 2);\n ctx.rotate(deg2rad(deg));\n ctx.lineWidth = 3;\n ctx.strokeStyle = lightBlue;\n ctx.beginPath();\n if (broken) {\n krakel(ctx, [\n [0, -20, 50],\n [1, -20, 30],\n [1, -10, 40],\n [1, 0, 25],\n [1, 10, 35],\n [1, 20, 30],\n [1, 20, 50],\n [0, -20, -50],\n [1, -20, -40],\n [1, -10, -25],\n [1, 0, -35],\n [1, 10, -30],\n [1, 20, -40],\n [1, 20, -50]\n ]);\n } else {\n krakel(ctx, [[0, -20, -50], [1, -20, 50], [0, 20, -50], [1, 20, 50]]);\n }\n ctx.stroke();\n ctx.restore();\n};\n","/* eslint-disable no-param-reassign */\nimport { tileWidth, tileHeight, lightBlue } from '../../config.js';\nimport { degreesToRadians as deg2rad } from '../../utils/index.js';\nimport { krakel } from './utils/index.js';\n\nexport default ({ ctx, row, col, deg, broken = false }) => {\n ctx.save();\n ctx.translate((col - 1) * tileWidth + tileWidth / 2, (row - 1) * tileHeight + tileHeight / 2);\n ctx.rotate(deg2rad(deg));\n ctx.lineWidth = 3;\n ctx.strokeStyle = lightBlue;\n ctx.beginPath();\n if (broken) {\n krakel(ctx, [\n [0, 50, 20],\n [1, 40, 20],\n [1, 45, 10],\n [1, 40, -10],\n [1, 45, -20],\n [1, 50, -20],\n [0, 20, -50],\n [1, 20, -35],\n [1, 10, -40],\n [1, 0, -30],\n [1, -10, -40],\n [1, -20, -35],\n [1, -20, -50],\n [0, -50, -20],\n [1, -40, -20],\n [1, -35, -10],\n [1, -45, 0],\n [1, -30, 10],\n [1, -35, 20],\n [1, -50, 20]\n ]);\n } else {\n krakel(ctx, [\n [0, -20, -50],\n [1, -20, -20],\n [1, -50, -20],\n [0, 20, -50],\n [1, 20, -20],\n [1, 50, -20],\n [0, -50, 20],\n [1, 50, 20]\n ]);\n }\n ctx.stroke();\n ctx.restore();\n};\n","/* eslint-disable no-param-reassign */\nimport { tileWidth, tileHeight, lightBlue } from '../../config.js';\nimport { krakel } from './utils/index.js';\n\nexport default ({ ctx, row, col, broken = false }) => {\n ctx.save();\n ctx.translate((col - 1) * tileWidth + tileWidth / 2, (row - 1) * tileHeight + tileHeight / 2);\n ctx.lineWidth = 3;\n ctx.strokeStyle = lightBlue;\n ctx.beginPath();\n if (broken) {\n krakel(ctx, [\n [0, -20, 50],\n [1, -20, 45],\n [1, -10, 40],\n [1, 0, 45],\n [1, 10, 35],\n [1, 20, 40],\n [1, 20, 50],\n [0, 50, 20],\n [1, 40, 20],\n [1, 45, 10],\n [1, 40, -10],\n [1, 45, -20],\n [1, 50, -20],\n [0, 20, -50],\n [1, 20, -35],\n [1, 10, -40],\n [1, 0, -30],\n [1, -10, -40],\n [1, -20, -35],\n [1, -20, -50],\n [0, -50, -20],\n [1, -40, -20],\n [1, -35, -10],\n [1, -45, 0],\n [1, -30, 10],\n [1, -35, 20],\n [1, -50, 20]\n ]);\n } else {\n krakel(ctx, [\n [0, -20, -50],\n [1, -20, -20],\n [1, -50, -20],\n [0, 20, -50],\n [1, 20, -20],\n [1, 50, -20],\n [0, -50, 20],\n [1, -20, 20],\n [1, -20, 50],\n [0, 50, 20],\n [1, 20, 20],\n [1, 20, 50]\n ]);\n }\n ctx.stroke();\n ctx.restore();\n};\n","/* eslint-disable no-param-reassign */\nimport { tileWidth, tileHeight, lightBlue } from '../../config.js';\nimport { degreesToRadians as deg2rad } from '../../utils/index.js';\nimport { krakel } from './utils/index.js';\n\nexport default ({ ctx, row, col, deg, broken = false }) => {\n ctx.save();\n ctx.translate((col - 1) * tileWidth + tileWidth / 2, (row - 1) * tileHeight + tileHeight / 2);\n ctx.rotate(deg2rad(deg));\n ctx.lineWidth = 3;\n ctx.strokeStyle = lightBlue;\n ctx.beginPath();\n if (broken) {\n krakel(ctx, [[0, -20, 50], [1, -20, 40], [1, -10, 45], [1, 0, 35], [1, 10, 45], [1, 20, 40], [1, 20, 50]]);\n } else {\n krakel(ctx, [[0, -20, 50], [1, -20, 0], [1, 20, 0], [1, 20, 50]]);\n }\n ctx.stroke();\n ctx.restore();\n};\n","/* global kontra */\n\n/**\n * A tile engine for rendering tilesets. Works well with the tile engine program Tiled.\n * @memberof kontra\n *\n * @param {object} properties - Properties of the tile engine.\n * @param {number} [properties.tileWidth=32] - Width of a tile.\n * @param {number} [properties.tileHeight=32] - Height of a tile.\n * @param {number} properties.width - Width of the map (in tiles).\n * @param {number} properties.height - Height of the map (in tiles).\n * @param {number} [properties.x=0] - X position to draw.\n * @param {number} [properties.y=0] - Y position to draw.\n * @param {number} [properties.sx=0] - X position to clip the tileset.\n * @param {number} [properties.sy=0] - Y position to clip the tileset.\n * @param {Context} [properties.context=kontra.context] - Provide a context for the tile engine to draw on.\n */\nexport default (properties = {}) => {\n if (process.env.NODE_ENV === 'development' && (!properties.width || !properties.height)) {\n throw Error('You must provide width and height properties');\n }\n\n const width = properties.width;\n const height = properties.height;\n\n // size of the tiles. Most common tile size on opengameart.org seems to be 32x32,\n // followed by 16x16\n // Tiled names the property tilewidth and tileheight\n const tileWidth = properties.tileWidth || 32;\n const tileHeight = properties.tileHeight || 32;\n\n const mapWidth = width * tileWidth;\n const mapHeight = height * tileHeight;\n\n const context = properties.context || kontra.context;\n const canvasWidth = context.canvas.width;\n const canvasHeight = context.canvas.height;\n\n // create an off-screen canvas for pre-rendering the map\n // @see http://jsperf.com/render-vs-prerender\n const offscreenCanvas = document.createElement('canvas');\n const offscreenContext = offscreenCanvas.getContext('2d');\n\n // when clipping an image, sx and sy must within the image region, otherwise\n // Firefox and Safari won't draw it.\n // @see http://stackoverflow.com/questions/19338032/canvas-indexsizeerror-index-or-size-is-negative-or-greater-than-the-allowed-a\n const sxMax = Math.max(0, mapWidth - canvasWidth);\n const syMax = Math.max(0, mapHeight - canvasHeight);\n\n let _sx, _sy;\n\n // draw order of layers (by name)\n const layerOrder = [];\n\n const tileEngine = {\n width,\n height,\n\n tileWidth,\n tileHeight,\n\n mapWidth,\n mapHeight,\n\n context,\n\n x: properties.x || 0,\n y: properties.y || 0,\n\n tilesets: [],\n layers: {},\n\n /**\n * Add an tileset for the tile engine to use.\n * @memberof kontra.tileEngine\n */\n addTilesets: function addTilesets(tilesets) {\n [].concat(tilesets).forEach(tileset => {\n const tilesetImage = tileset.image;\n let image, firstGrid, lastTileset, tiles;\n\n // @see https://github.com/jed/140bytes/wiki/Byte-saving-techniques#coercion-to-test-for-types\n if (`${tilesetImage}` === tilesetImage) {\n let i = Infinity;\n\n while (i >= 0) {\n i = tilesetImage.lastIndexOf('/', i);\n const path = i < 0 ? tilesetImage : tilesetImage.substr(i);\n\n if (kontra.assets.images[path]) {\n image = kontra.assets.images[path];\n break;\n }\n\n i--;\n }\n } else {\n image = tilesetImage;\n }\n\n firstGrid = tileset.firstGrid;\n\n // if the width or height of the provided image is smaller than the tile size,\n // default calculation to 1\n const numTiles = ((image.width / tileWidth) | 0 || 1) * ((image.height / tileHeight) | 0 || 1);\n\n if (!firstGrid) {\n // only calculate the first grid if the tile map has a tileset already\n if (tileEngine.tilesets.length > 0) {\n lastTileset = tileEngine.tilesets[tileEngine.tilesets.length - 1];\n tiles =\n ((lastTileset.image.width / tileWidth) | 0) * ((lastTileset.image.height / tileHeight) | 0);\n\n firstGrid = lastTileset.firstGrid + tiles;\n }\n // otherwise this is the first tile added to the tile map\n else {\n firstGrid = 1;\n }\n }\n\n tileEngine.tilesets.push({\n firstGrid,\n lastGrid: firstGrid + numTiles - 1,\n image\n });\n\n // sort the tile map so we can perform a binary search when drawing\n tileEngine.tilesets.sort((a, b) => a.firstGrid - b.firstGrid);\n });\n },\n\n /**\n * Add a layer to the tile engine.\n * @memberof kontra.tileEngine\n */\n addLayers: function addLayers(layers) {\n [].concat(layers).forEach(layer => {\n // eslint-disable-next-line no-param-reassign\n layer.render = layer.render === undefined ? true : layer.render;\n\n let data, row, c, value;\n\n // flatten a 2D array into a single array\n if (Array.isArray(layer.data[0])) {\n data = [];\n\n // eslint-disable-next-line no-cond-assign\n for (let r = 0; (row = layer.data[r]); r++) {\n for (c = 0; c < width; c++) {\n data.push(row[c] || 0);\n }\n }\n } else {\n data = layer.data;\n }\n\n tileEngine.layers[layer.name] = {\n data,\n zIndex: layer.zIndex || 0,\n render: layer.render\n };\n\n // merge properties of layer onto layer object\n for (const prop in layer.properties) {\n if (layer.properties.hasOwnProperty(prop)) {\n value = layer.properties[prop];\n\n try {\n value = JSON.parse(value);\n } catch (e) {\n /* intentionally empty */\n }\n\n tileEngine.layers[layer.name][prop] = value;\n }\n }\n\n // only add the layer to the layer order if it should be drawn\n if (tileEngine.layers[layer.name].render) {\n layerOrder.push(layer.name);\n\n layerOrder.sort((a, b) => tileEngine.layers[a].zIndex - tileEngine.layers[b].zIndex);\n }\n });\n\n preRenderImage();\n },\n\n changeTile(layerId, position, tile) {\n const dataIndex = getIndex(position);\n const layer = tileEngine.layers[layerId];\n layer.data[dataIndex] = tile;\n renderTile(layer, dataIndex, true);\n },\n\n /**\n * Get the tile from the specified layer at x, y or row, col.\n * @memberof kontra.tileEngine\n *\n * @param {string} name - Name of the layer.\n * @param {object} position - Position of the tile in either x, y or row, col.\n * @param {number} position.x - X coordinate of the tile.\n * @param {number} position.y - Y coordinate of the tile.\n * @param {number} position.row - Row of the tile.\n * @param {number} position.col - Col of the tile.\n *\n * @returns {number}\n */\n tileAtLayer(name, position) {\n const index = getIndex(position);\n\n if (index >= 0) {\n return tileEngine.layers[name].data[index];\n }\n return undefined;\n },\n\n /**\n * Render the pre-rendered canvas.\n * @memberof kontra.tileEngine\n */\n render() {\n tileEngine.context.drawImage(\n offscreenCanvas,\n tileEngine.sx,\n tileEngine.sy,\n canvasWidth,\n canvasHeight,\n tileEngine.x,\n tileEngine.y,\n canvasWidth,\n canvasHeight\n );\n },\n\n /**\n * Render a specific layer.\n * @memberof kontra.tileEngine\n *\n * @param {string} name - Name of the layer to render.\n */\n renderLayer: function renderLayer(name) {\n const layer = tileEngine.layers[name];\n\n // calculate the starting tile\n let row = tileEngine.getRow();\n const col = tileEngine.getCol();\n let index = getIndex({ row, col });\n\n // calculate where to start drawing the tile relative to the drawing canvas\n const startX = col * tileWidth - tileEngine.sx;\n const startY = row * tileHeight - tileEngine.sy;\n\n // calculate how many tiles the drawing canvas can hold\n const viewWidth = Math.min(Math.ceil(canvasWidth / tileWidth) + 1, width);\n const viewHeight = Math.min(Math.ceil(canvasHeight / tileHeight) + 1, height);\n const numTiles = viewWidth * viewHeight;\n\n let count = 0;\n let x, y, tile, tileset, image, tileOffset, w, sx, sy;\n\n // draw just enough of the layer to fit inside the drawing canvas\n while (count < numTiles) {\n tile = layer.data[index];\n\n if (tile) {\n tileset = getTileset(tile);\n image = tileset.image;\n\n x = startX + (count % viewWidth) * tileWidth;\n y = startY + ((count / viewWidth) | 0) * tileHeight;\n\n tileOffset = tile - tileset.firstGrid;\n w = image.width / tileWidth;\n\n sx = (tileOffset % w) * tileWidth;\n sy = ((tileOffset / w) | 0) * tileHeight;\n\n tileEngine.context.drawImage(image, sx, sy, tileWidth, tileHeight, x, y, tileWidth, tileHeight);\n }\n\n if (++count % viewWidth === 0) {\n index = col + ++row * width;\n } else {\n index++;\n }\n }\n },\n\n getRowAndCol({ x, y }) {\n return {\n row: this.getRow(y),\n col: this.getCol(x)\n };\n },\n\n getXAndY({ row, col, mapX, mapY }) {\n return {\n x: (col ? col * tileWidth : mapX) - tileEngine.sx + tileWidth / 2,\n y: (row ? row * tileHeight : mapY) - tileEngine.sy + tileHeight / 2\n };\n },\n\n /**\n * Get the row from the y coordinate.\n * @memberof kontra.tileEngine\n *\n * @param {number} y - Y coordinate.\n *\n * @return {number}\n */\n getRow(y = 0) {\n return ((tileEngine.sy + y) / tileHeight) | 0;\n },\n\n /**\n * Get the col from the x coordinate.\n * @memberof kontra.tileEngine\n *\n * @param {number} x - X coordinate.\n *\n * @return {number}\n */\n getCol(x = 0) {\n return ((tileEngine.sx + x) / tileWidth) | 0;\n },\n\n get sx() {\n return _sx;\n },\n\n get sy() {\n return _sy;\n },\n\n // ensure sx and sy are within the image region\n set sx(value) {\n _sx = Math.min(Math.max(0, value), sxMax);\n },\n\n set sy(value) {\n _sy = Math.min(Math.max(0, value), syMax);\n }\n };\n\n // set here so we use setter function\n tileEngine.sx = properties.sx || 0;\n tileEngine.sy = properties.sy || 0;\n\n // make the off-screen canvas the full size of the map\n offscreenCanvas.width = mapWidth;\n offscreenCanvas.height = mapHeight;\n\n // merge properties of the tile engine onto the tile engine itself\n for (const prop in properties.properties) {\n if (properties.properties.hasOwnProperty(prop)) {\n let value = properties.properties[prop];\n\n try {\n value = JSON.parse(value);\n } catch (e) {\n /* intentionally empty */\n }\n\n // passed in properties override properties.properties\n tileEngine[prop] = tileEngine[prop] || value;\n }\n }\n\n if (properties.tilesets) {\n tileEngine.addTilesets(properties.tilesets);\n }\n\n if (properties.layers) {\n tileEngine.addLayers(properties.layers);\n }\n\n /**\n * Get the index of the x, y or row, col.\n * @memberof kontra.tileEngine\n * @private\n *\n * @param {number} position.x - X coordinate of the tile.\n * @param {number} position.y - Y coordinate of the tile.\n * @param {number} position.row - Row of the tile.\n * @param {number} position.col - Col of the tile.\n *\n * @return {number} Returns the tile index or -1 if the x, y or row,\n * col is outside the dimensions of the tile engine.\n */\n function getIndex(position) {\n let row, col;\n\n if (typeof position.x !== 'undefined' && typeof position.y !== 'undefined') {\n row = tileEngine.getRow(position.y);\n col = tileEngine.getCol(position.x);\n } else {\n row = position.row;\n col = position.col;\n }\n\n // don't calculate out of bound numbers\n if (row < 0 || col < 0 || row >= height || col >= width) {\n return -1;\n }\n\n return col + row * width;\n }\n\n /**\n * Modified binary search that will return the tileset associated with the tile\n * @memberof kontra.tileEngine\n * @private\n *\n * @param {number} tile - Tile grid.\n *\n * @return {object}\n */\n function getTileset(tile) {\n let min = 0;\n let max = tileEngine.tilesets.length - 1;\n let index, currTile;\n\n while (min <= max) {\n index = ((min + max) / 2) | 0;\n currTile = tileEngine.tilesets[index];\n\n if (tile >= currTile.firstGrid && tile <= currTile.lastGrid) {\n return currTile;\n } else if (currTile.lastGrid < tile) {\n min = index + 1;\n } else {\n max = index - 1;\n }\n }\n return undefined;\n }\n\n /**\n * Pre-render the tiles to make drawing fast.\n * @memberof kontra.tileEngine\n * @private\n */\n function preRenderImage() {\n // draw each layer in order\n // eslint-disable-next-line no-cond-assign\n for (let layerIndex = 0, layer; (layer = tileEngine.layers[layerOrder[layerIndex]]); layerIndex++) {\n for (let dataIndex = 0, len = layer.data.length; dataIndex < len; dataIndex++) {\n renderTile(layer, dataIndex);\n }\n }\n }\n\n function renderTile(layer, dataIndex, clear = false) {\n const tile = layer.data[dataIndex];\n\n // skip empty tiles (0)\n if (!tile) {\n return;\n }\n\n const tileset = getTileset(tile);\n const image = tileset.image;\n\n const x = (dataIndex % width) * tileWidth;\n const y = ((dataIndex / width) | 0) * tileHeight;\n\n const tileOffset = tile - tileset.firstGrid;\n const w = image.width / tileWidth;\n\n const sx = (tileOffset % w) * tileWidth;\n const sy = ((tileOffset / w) | 0) * tileHeight;\n\n if (clear) {\n offscreenContext.clearRect(x, y, tileWidth, tileHeight);\n }\n offscreenContext.drawImage(image, sx, sy, tileWidth, tileHeight, x, y, tileWidth, tileHeight);\n }\n\n return tileEngine;\n};\n","/* global kontra */\n\nimport { tileHeight, tileWidth, mapPadding } from '../config.js';\nimport { calculateCameraCoordinates } from '../utils/index.js';\nimport { addPadding } from './utils/index.js';\nimport { createTilesheet } from './tilesheet/index.js';\nimport { createTileEngine } from '../tileEngine/index.js';\n\nexport default async ({ data, width, height, col, row }) => {\n const { sx, sy } = calculateCameraCoordinates({ col, row });\n const map = createTileEngine({\n // tile size\n tileWidth,\n tileHeight,\n\n // map size in tiles\n width: width + mapPadding * 2,\n height: height + mapPadding * 2,\n\n sx,\n sy\n });\n\n const paddedMap = addPadding(data, width, height, mapPadding);\n const image = await createTilesheet();\n map.addTilesets({ image });\n map.addLayers([\n {\n name: 'main',\n data: paddedMap\n }\n ]);\n return map;\n};\n","export default (arr, w, h, pad) => {\n const retVal = [];\n let idx = 0;\n for (let row = 0; row < h + pad * 2; row++) {\n for (let col = 0; col < w + pad * 2; col++) {\n if (row < pad || row >= pad + h || col < pad || col >= pad + w) {\n retVal.push(0);\n continue;\n }\n retVal.push(arr[idx++]);\n }\n }\n return retVal;\n};\n","import { tileHeight, tileWidth } from '../../config.js';\nimport { drawCurve, drawStraight, drawTSection, drawCrossing, drawTerminus } from './index.js';\n\nexport default () => {\n const canvas = document.createElement('canvas');\n canvas.width = 8 * tileWidth;\n canvas.height = 8 * tileHeight;\n const ctx = canvas.getContext('2d');\n drawCurve({ ctx, row: 1, col: 1, deg: 0 });\n drawCurve({ ctx, row: 1, col: 2, deg: 90 });\n drawCurve({ ctx, row: 2, col: 1, deg: 270 });\n drawCurve({ ctx, row: 2, col: 2, deg: 180 });\n drawStraight({ ctx, row: 1, col: 3, deg: 0 });\n drawStraight({ ctx, row: 2, col: 3, deg: 90 });\n drawTSection({ ctx, row: 1, col: 4, deg: 0 });\n drawTSection({ ctx, row: 1, col: 5, deg: 90 });\n drawTSection({ ctx, row: 1, col: 6, deg: 180 });\n drawTSection({ ctx, row: 2, col: 5, deg: 270 });\n drawCrossing({ ctx, row: 2, col: 4 });\n drawTerminus({ ctx, row: 1, col: 7, deg: 0 });\n drawTerminus({ ctx, row: 1, col: 8, deg: 90 });\n drawTerminus({ ctx, row: 2, col: 7, deg: 180 });\n drawTerminus({ ctx, row: 2, col: 8, deg: 270 });\n drawCurve({ ctx, row: 3, col: 1, deg: 0, broken: true });\n drawCurve({ ctx, row: 3, col: 2, deg: 90, broken: true });\n drawCurve({ ctx, row: 4, col: 1, deg: 270, broken: true });\n drawCurve({ ctx, row: 4, col: 2, deg: 180, broken: true });\n drawStraight({ ctx, row: 3, col: 3, deg: 0, broken: true });\n drawStraight({ ctx, row: 4, col: 3, deg: 90, broken: true });\n drawTSection({ ctx, row: 3, col: 4, deg: 0, broken: true });\n drawTSection({ ctx, row: 3, col: 5, deg: 90, broken: true });\n drawTSection({ ctx, row: 3, col: 6, deg: 180, broken: true });\n drawTSection({ ctx, row: 4, col: 5, deg: 270, broken: true });\n drawCrossing({ ctx, row: 4, col: 4, broken: true });\n drawTerminus({ ctx, row: 3, col: 7, deg: 0, broken: true });\n drawTerminus({ ctx, row: 3, col: 8, deg: 90, broken: true });\n drawTerminus({ ctx, row: 4, col: 7, deg: 180, broken: true });\n drawTerminus({ ctx, row: 4, col: 8, deg: 270, broken: true });\n\n const image = new Image();\n image.src = canvas.toDataURL('image/png');\n return new Promise(resolve => setTimeout(() => resolve(image), 100));\n};\n","/* global kontra */\n\nimport { drawPlayer, updatePlayer } from './index.js';\nimport { canvasHeight, canvasWidth, collisionRadius, teleportCooldownTimeout } from '../config.js';\nimport {\n pubsub,\n GAME_OVER,\n LEVEL_COMPLETED,\n DROP_SHIP,\n MAP_CHANGED,\n SERVER_INFECTED,\n SERVER_DESTROYED,\n PLAYER_TELEPORTED\n} from '../pubsub/index.js';\nimport { multiCollides } from '../utils/index.js';\nimport { messageBox } from '../messageBox/index.js';\nimport { calculateCameraCoordinates } from '../utils/index.js';\nimport { directionIsAllowed, switchDirection } from '../directions/index.js';\nimport { servers } from '../server/index.js';\nimport { viruses } from '../virus/index.js';\nimport { users } from '../user/index.js';\nimport { pathfinder } from '../pathfinder/index.js';\n\nexport default ({ map, direction, speed }) => {\n const player = {\n context: kontra.context,\n x: canvasWidth / 2,\n y: canvasHeight / 2,\n collisionRadius,\n map,\n speed,\n infected: false,\n gameInactive: true,\n direction,\n nextDirection: null,\n dropBomb: false,\n scale: 1,\n dropping: false,\n bombCoolingDown: false,\n teleportToServer: false,\n teleportCoolingDown: false,\n\n update() {\n ({\n nextDirection: this.nextDirection,\n direction: this.direction,\n dropBomb: this.dropBomb,\n scale: this.scale,\n bombCoolingDown: this.bombCoolingDown,\n teleportToServer: this.teleportToServer\n } = updatePlayer(this, pubsub, messageBox));\n },\n\n render() {\n drawPlayer(this);\n },\n\n infect(virusesOrServers) {\n const collisions = multiCollides(virusesOrServers, [this]);\n\n if (collisions.length > 0) {\n // eslint-disable-next-line no-param-reassign\n this.infected = true;\n if (!this.gameInactive) {\n messageBox.show('player infected<br>game over<br><br>press any key to start again');\n pubsub.publish(GAME_OVER);\n }\n }\n },\n\n teleport() {\n if (this.teleportToServer && !this.teleportCoolingDown) {\n this.teleportCoolingDown = true;\n\n const nextServer = servers.getNext();\n if (nextServer) {\n ({ sx: this.map.sx, sy: this.map.sy } = calculateCameraCoordinates(nextServer));\n if (!directionIsAllowed(this.map, { x: this.x, y: this.y }, this.direction)) {\n this.direction = switchDirection(this.map, { x: this.x, y: this.y }, this.direction);\n }\n pubsub.publish(PLAYER_TELEPORTED);\n } else {\n messageBox.flash('all servers are destroyed or infected');\n }\n\n setTimeout(() => {\n this.teleportCoolingDown = false;\n }, teleportCooldownTimeout);\n }\n this.teleportToServer = false;\n },\n\n enableControls() {\n this.gameInactive = false;\n },\n\n canReachVirus() {\n // check if player can reach all viruses by path\n const playerWithRowAndCol = {\n ...this,\n ...this.map.getRowAndCol(this)\n };\n const virusesWithRowAndCol = viruses.getAllWithRowAndCol();\n\n if (virusesWithRowAndCol.length === 0) {\n return;\n }\n\n const playerCannotReachTheseVirusesByPath = virusesWithRowAndCol.filter(\n virus => !pathfinder.isReachable(playerWithRowAndCol, virus)\n );\n\n // check if viruses can be reached from servers\n const availableServers = servers.getAvailableServers();\n const playerCanReachTheseVirusesFromServers = [];\n\n playerCannotReachTheseVirusesByPath.forEach(virus => {\n availableServers.forEach(server => {\n if (pathfinder.isReachable(server, virus)) {\n playerCanReachTheseVirusesFromServers.push(virus);\n }\n });\n });\n\n // from playerCannotReachTheseVirusesByPath remove the ones that playerCanReachTheseVirusesFromServers\n const playerCannotReachTheseVirusesAtAll = playerCannotReachTheseVirusesByPath.filter(virusByPath => {\n const found = playerCanReachTheseVirusesFromServers.find(\n virusServer => virusByPath.x === virusServer.x && virusByPath.y === virusServer.y\n );\n return !found;\n });\n\n if (playerCannotReachTheseVirusesAtAll.length === 0) {\n return;\n }\n\n // if there are any viruses not reachable, then infect all users the virus can reach\n users.infectAllReachable(playerCannotReachTheseVirusesAtAll);\n }\n };\n\n pubsub.subscribe(GAME_OVER, () => (player.gameInactive = true));\n pubsub.subscribe(LEVEL_COMPLETED, () => (player.gameInactive = true));\n pubsub.subscribe(DROP_SHIP, () => (player.dropping = true));\n pubsub.subscribe(MAP_CHANGED, () => player.canReachVirus());\n pubsub.subscribe(SERVER_INFECTED, () => player.canReachVirus());\n pubsub.subscribe(SERVER_DESTROYED, () => player.canReachVirus());\n pubsub.subscribe(PLAYER_TELEPORTED, () => player.canReachVirus());\n\n return player;\n};\n","import { lightGreen, darkGreen, lightRed, darkRed } from '../config.js';\nimport { calculateRotation } from '../utils/index.js';\n\nexport default sprite => {\n const { context: ctx, x, y, direction, infected, scale } = sprite;\n ctx.save();\n ctx.translate(x, y);\n ctx.scale(scale, scale);\n ctx.rotate(calculateRotation(direction));\n ctx.lineWidth = 3;\n ctx.strokeStyle = infected ? lightRed : lightGreen;\n ctx.fillStyle = infected ? darkRed : darkGreen;\n ctx.beginPath();\n ctx.moveTo(-15, 25);\n ctx.lineTo(0, -25);\n ctx.lineTo(15, 25);\n ctx.closePath();\n ctx.fill();\n ctx.stroke();\n ctx.restore();\n};\n","import { degreesToRadians } from './index.js';\nimport { N, E, S, W } from '../directions/index.js';\n\nexport default direction => {\n switch (direction) {\n case N:\n return degreesToRadians(0);\n case E:\n return degreesToRadians(90);\n case S:\n return degreesToRadians(180);\n case W:\n return degreesToRadians(270);\n default:\n return null;\n }\n};\n","import { directionIsAllowed, switchDirection } from '../directions/index.js';\nimport { pubsub, DROP_BOMB, DROP_SHIP, GAME_OVER } from '../pubsub/index.js';\nimport { getKey, isInTheMiddle } from './utils/index.js';\nimport { messageBox } from '../messageBox/index.js';\nimport { bombCooldown } from '../config.js';\n\nexport default sprite => {\n let { nextDirection, direction, dropBomb, scale, bombCoolingDown, teleportToServer } = sprite;\n const { dropping, map, gameInactive, x, y } = sprite;\n if (dropping) {\n if (scale > 0) {\n scale -= 0.01;\n } else {\n messageBox.show('You fell into the abyss<br>Game over<br><br>press any key to start again');\n pubsub.publish(GAME_OVER);\n }\n return { direction, nextDirection, dropBomb, scale, bombCoolingDown, teleportToServer };\n }\n if (!gameInactive) {\n ({ nextDirection, dropBomb, teleportToServer } = getKey(sprite));\n if (bombCoolingDown) {\n dropBomb = false;\n }\n }\n if (!isInTheMiddle({ x: map.sx, y: map.sy })) {\n return { direction, nextDirection, dropBomb, scale, bombCoolingDown, teleportToServer };\n }\n if (nextDirection && directionIsAllowed(map, { x, y }, nextDirection)) {\n direction = nextDirection;\n nextDirection = null;\n } else {\n try {\n direction = switchDirection(map, { x, y }, direction);\n } catch ({ message }) {\n if (message === 'dropped') {\n pubsub.publish(DROP_SHIP);\n }\n }\n }\n if (dropBomb) {\n pubsub.publish(DROP_BOMB, map.getRowAndCol({ x, y }));\n dropBomb = false;\n bombCoolingDown = true;\n setTimeout(() => {\n // eslint-disable-next-line no-param-reassign\n sprite.bombCoolingDown = false;\n }, bombCooldown);\n }\n return { direction, nextDirection, dropBomb, scale, bombCoolingDown, teleportToServer };\n};\n","/* global kontra */\n\nimport { N, E, S, W } from '../../directions/index.js';\n\nexport default sprite => {\n let { nextDirection, dropBomb, teleportToServer } = sprite;\n if (kontra.keys.pressed('right')) {\n nextDirection = E;\n }\n if (kontra.keys.pressed('left')) {\n nextDirection = W;\n }\n if (kontra.keys.pressed('up')) {\n nextDirection = N;\n }\n if (kontra.keys.pressed('down')) {\n nextDirection = S;\n }\n if (kontra.keys.pressed('space')) {\n dropBomb = true;\n }\n if (kontra.keys.pressed('enter')) {\n teleportToServer = true;\n }\n\n return { nextDirection, dropBomb, teleportToServer };\n};\n","import { tileHeight, tileWidth } from '../../config.js';\n\nexport default ({ x, y }) => (x - tileWidth / 2) % tileWidth === 0 && (y - tileHeight / 2) % tileHeight === 0;\n","import { canvasHeight, canvasWidth, lightBlue } from '../config.js';\n\nexport default () => {\n const canvas = document.createElement('canvas');\n canvas.width = canvasWidth;\n canvas.height = canvasHeight;\n canvas.style.cssText = `\n border: 4px solid ${lightBlue};\n `;\n const wrapper = document.getElementById('wrapper');\n wrapper.appendChild(canvas);\n};\n","import { N, W, S, E } from '../directions/index.js';\n\nexport default [\n {\n player: {\n col: 7,\n row: 7,\n direction: N,\n speed: 5\n },\n virus: {\n speed: 2.5,\n max: 1,\n interval: 3000\n },\n servers: [{ row: 7, col: 4 }, { row: 7, col: 10 }],\n map: {\n width: 7,\n height: 7,\n // prettier-ignore\n data:\n ' 6 ' +\n ' 2 01' +\n '0aac03c' +\n '2 0b9 2' +\n '4594aa9' +\n '89 2 ' +\n ' e '\n }\n },\n {\n player: {\n col: 6,\n row: 8,\n direction: S,\n speed: 5\n },\n virus: {\n speed: 2.5,\n max: 1,\n interval: 3000\n },\n servers: [{ row: 7, col: 4 }, { row: 7, col: 8 }, { row: 8, col: 6 }],\n map: {\n width: 5,\n height: 8,\n // prettier-ignore\n data:\n ' 6 ' +\n ' 626 ' +\n '0b3b1' +\n '22 22' +\n '83b39' +\n '05b51' +\n '8b3b9' +\n ' e e '\n }\n },\n {\n player: {\n col: 9,\n row: 9,\n direction: N,\n speed: 5\n },\n virus: {\n speed: 2.5,\n max: 2,\n interval: 3000\n },\n servers: [{ row: 6, col: 5 }, { row: 7, col: 9 }, { row: 7, col: 9 }, { row: 9, col: 9 }],\n map: {\n width: 9,\n height: 9,\n // prettier-ignore\n data:\n ' 6 6 ' +\n ' 03a31 ' +\n ' 410a3a57' +\n ' 228aaac ' +\n 'fc8aa1 2 ' +\n ' 20aabac ' +\n ' 49 2 47' +\n 'fc05aba9 ' +\n ' 89e e '\n }\n },\n {\n player: {\n col: 12,\n row: 4,\n direction: W,\n speed: 5\n },\n virus: {\n speed: 2.5,\n max: 3,\n interval: 4000\n },\n servers: [{ row: 5, col: 7 }, { row: 4, col: 12 }, { row: 7, col: 9 }, { row: 8, col: 15 }],\n map: {\n width: 13,\n height: 6,\n // prettier-ignore\n data:\n ' 6 0a1 ' +\n ' 4aa1 2 2 6 ' +\n 'fabaaba353a31' +\n ' 47 2 2 fc' +\n ' fbaa9 85aa9' +\n ' e e '\n }\n },\n {\n player: {\n col: 8,\n row: 8,\n direction: E,\n speed: 5\n },\n virus: {\n speed: 2.5,\n max: 4,\n interval: 5000\n },\n servers: [\n { row: 4, col: 7 },\n { row: 4, col: 11 },\n { row: 8, col: 8 },\n { row: 8, col: 10 },\n { row: 15, col: 7 },\n { row: 15, col: 11 },\n { row: 11, col: 8 },\n { row: 11, col: 10 }\n ],\n map: {\n width: 11,\n height: 12,\n // prettier-ignore\n data:\n '0aaaaaaaaa1' +\n '8a5aaaaa5a9' +\n ' fbaa5aab7 ' +\n ' 2 2 2 ' +\n ' 0baabaab1 ' +\n 'fc47 2 fc47' +\n 'fc47 2 fc47' +\n ' 8baabaab9 ' +\n ' 2 2 2 ' +\n ' fbaa3aab7 ' +\n '0a3aaaaa3a1' +\n '8aaaaaaaaa9'\n }\n }\n /* ,\n {\n player: {\n col: 8,\n row: 9,\n direction: S,\n speed: 5\n },\n virus: {\n speed: 2.5,\n max: 2,\n interval: 10000\n },\n servers: [{ row: 9, col: 8 }, { row: 9, col: 12 }, { row: 15, col: 15 }],\n map: {\n width: 20,\n height: 20,\n // prettier-ignore\n data:\n ' 6 6 6 6 6 ' +\n 'f3a1031 4a5ac 0ab1 ' +\n ' 0a98ac 2 2 4ac 22 ' +\n ' 20a5a9 0318ac 8a92 ' +\n ' 22 2 20c 2 47' +\n ' 22 2 0a928a53a51 2 ' +\n ' 22 2 2 2 2 22 2 ' +\n ' 8c 4a9 20a9 22 2 ' +\n ' 2 2 039 24a37' +\n ' 0c 4a1 2 0aaaab9 ' +\n ' 22 2 4ac 8a1 2 07' +\n ' 89 4a9 8aaaba59 2 ' +\n ' 20a10aaa9 2 0a37' +\n 'f55a92 22 018aba1 ' +\n ' 22 2 220a122 2 2 ' +\n ' 431 4a922 4b3aac 47' +\n ' 2 4aba598592 8a9 ' +\n 'f3ac 2 8aac 8a5a55a7' +\n ' 2 2 4aa12 22 ' +\n ' e e e e8a9e '\n }\n }*/\n];\n","function conv(c) {\n const cc = c.charCodeAt(0);\n return cc === 32 ? 0 : cc >= 97 ? cc - 86 : cc - 47;\n}\n\nexport default hex => hex.split('').map(c => conv(c));\n","import data from './data.js';\nimport mapHex2Arr from './mapHex2Arr.js';\n\nexport default levelIndex => {\n const level = data[levelIndex];\n return {\n ...level,\n map: {\n ...level.map,\n data: mapHex2Arr(level.map.data)\n }\n };\n};\n","export default () =>\n new Promise(resolve => setTimeout(() => document.addEventListener('keydown', resolve, { once: true }), 1000));\n","import { messageBox } from '../messageBox/index.js';\nimport pressAnyKey from './pressAnyKey.js';\n\nexport default async () => {\n messageBox.show(\n 'welcome, <span class=\"grn\">captain katamov!</span><br><br>' +\n 'Your shift as chief network security officer is about to begin… all users are online and happy. ' +\n 'in case of virus intrusion, <span class=\"grn\">cut them off</span> from the network ' +\n \"to make sure they don't get infected!<br><br>\" +\n '<table><tr><td class=\"grn\">arrow keys</td><td>…</td><td>change direction</td></tr>' +\n '<tr><td class=\"grn\">space bar</td><td>…</td><td>drop bomb</td></tr>' +\n '<tr><td class=\"grn\">return</td><td>…</td><td>teleport to server</td></tr>' +\n '</table><br>press any key to begin!'\n );\n await pressAnyKey();\n messageBox.clear();\n};\n","/* global kontra */\n\nimport { initAudio } from '../audio/index.js';\nimport { Bombs } from '../bomb/index.js';\nimport { createLoop } from '../loop/index.js';\nimport { createMap } from '../map/index.js';\nimport { createPlayer } from '../player/index.js';\nimport { users } from '../user/index.js';\nimport { viruses } from '../virus/index.js';\nimport { createCanvas } from '../canvas/index.js';\nimport { initPathfinder, pathfinder } from '../pathfinder/index.js';\nimport { pubsub, USERS_POSSIBLY_OFFLINE, LEVEL_COMPLETED, GAME_OVER } from '../pubsub/index.js';\nimport { messageBox } from '../messageBox/index.js';\nimport { servers } from '../server/index.js';\nimport getLevel from '../level/getLevel.js';\nimport levelData from '../level/data.js';\nimport scoreBoard from '../scoreBoard/scoreBoard.js';\nimport showStartScreen from './showStartScreen.js';\nimport pressAnyKey from './pressAnyKey.js';\nimport { canvasHeight, canvasWidth } from '../config.js';\n\nclass GameManager {\n constructor() {\n createCanvas();\n kontra.init();\n initPathfinder();\n initAudio();\n pubsub.subscribe(LEVEL_COMPLETED, () => this.break(this.levelIndex + 1), true);\n pubsub.subscribe(GAME_OVER, async () => this.break(0), true);\n }\n\n async break(nextLevelIndex) {\n pubsub.reset();\n viruses.reset();\n this.loop.stop();\n await pressAnyKey();\n messageBox.clear();\n if (nextLevelIndex === levelData.length) {\n await this.finishGame();\n return;\n }\n this.levelIndex = nextLevelIndex;\n await this.initLevel();\n if (nextLevelIndex === 0) {\n scoreBoard.startGame();\n } else {\n scoreBoard.initLevel();\n }\n await this.startLevel();\n }\n\n async startGame() {\n this.levelIndex = 0;\n await this.initLevel();\n await showStartScreen();\n scoreBoard.startGame();\n this.startLevel();\n }\n\n async finishGame() {\n messageBox.show('All levels completed!<br>You are awesome!<br><br>Press any key to start again');\n await pressAnyKey();\n messageBox.clear();\n kontra.context.clearRect(0, 0, canvasWidth, canvasHeight);\n this.startGame();\n }\n\n async initLevel() {\n const level = getLevel(this.levelIndex);\n const map = await createMap({ ...level.map, col: level.player.col, row: level.player.row });\n this.player = createPlayer({ map, ...level.player });\n const bombs = new Bombs(map);\n viruses.init(map, level.virus);\n pathfinder.setDataFromMap(map, 'main');\n users.init(map);\n servers.init(map, level.servers);\n this.loop = createLoop({ map, player: this.player, bombs });\n pubsub.subscribe(USERS_POSSIBLY_OFFLINE, () => users.updateOnlineStatus());\n\n map.render();\n users.render();\n servers.render();\n bombs.render();\n this.player.render();\n }\n\n startLevel() {\n this.loop.start();\n viruses.startSpawning();\n setTimeout(() => this.player.enableControls(), 500);\n }\n}\n\nexport default new GameManager();\n","import { gameManager } from './gameManager/index.js';\n\n// will be removed by tree shaking\nimport createDevbox from './devbox/createDevbox.js';\nif (process.env.NODE_ENV === 'development') {\n createDevbox();\n}\n\ngameManager.startGame();\n"]}