├── .github └── FUNDING.yml ├── .gitignore ├── CNAME ├── LICENSE.md ├── README.md ├── a.js ├── favicon.ico ├── images ├── android.png ├── appstore.svg ├── btn_back.svg ├── btn_facebook.svg ├── btn_help.svg ├── btn_pause.svg ├── btn_restart.svg ├── btn_resume.svg ├── btn_share.svg ├── btn_twitter.svg ├── facebook-opengraph.png ├── icon_arrows.svg ├── icons │ ├── apple-touch-120.png │ ├── apple-touch-152.png │ ├── apple-touch-167.png │ ├── apple-touch-180.png │ ├── apple-touch-512.png │ ├── apple-touch.svg │ ├── maskable-192.png │ ├── maskable-192.webp │ ├── maskable-512.png │ ├── maskable-512.webp │ ├── maskable.svg │ ├── transparent-192.png │ ├── transparent-192.webp │ ├── transparent-512.png │ ├── transparent-512.webp │ └── transparent.svg └── twitter-opengraph.png ├── index.html ├── js ├── Block.js ├── Hex.js ├── Text.js ├── checking.js ├── comboTimer.js ├── initialization.js ├── input.js ├── main.js ├── math.js ├── render.js ├── save-state.js ├── update.js ├── view.js └── wavegen.js ├── manifest.webmanifest ├── style ├── fa │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ └── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ └── fontawesome-webfont.woff ├── fonts │ ├── Exo2-ExtraLight.otf │ ├── Exo2-Regular.otf │ ├── Exo2-SemiBold.otf │ ├── Lovelo.otf │ ├── QuattrocentoSans-Regular.ttf │ └── roboto.woff ├── rrssb.css └── style.css └── vendor ├── hammer.min.js ├── jquery.js ├── js.cookie.js ├── jsonfn.min.js ├── keypress.min.js ├── rrssb.min.js └── sweet-alert.min.js /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [lengstrom] 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/* 3 | *~ 4 | *.swp 5 | *.swo 6 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | hextris.io -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Hextris 2 | ========== 3 | 4 |
5 | 6 | An addictive puzzle game inspired by Tetris. Play it at [www.hextris.io](http://www.hextris.io), or [https://hextris.github.io/hextris](https://hextris.github.io/hextris). 7 | 8 | By: 9 | - Logan Engstrom ([@lengstrom](http://loganengstrom.com/)) 10 | - Garrett Finucane ([@garrettdreyfus](http://github.com/garrettdreyfus)) 11 | - Noah Moroze ([@nmoroze](http://github.com/nmoroze)) 12 | - Michael Yang ([@themichaelyang](http://github.com/themichaelyang)) 13 | 14 | ## Citation 15 | Did you use Hextris in your research? Cite us as follows: 16 | ``` 17 | @misc{engstrom2015hextris, 18 | author = {Logan Engstrom, Garrett Finucane, Noah Moroze, Michael Yang}, 19 | title = {hextris}, 20 | year = {2015}, 21 | howpublished = {\url{https://github.com/hextris/hextris/}}, 22 | note = {commit xxxxxxx} 23 | } 24 | ``` 25 | 26 | 27 | # Contributions 28 | This project is not very actively maintained, as we are all very busy these days. But feel free to open an issue or PR, and we'll eventually take a look. 29 | 30 | # About 31 | Hextris was created by a group of high school friends in 2014. 32 | 33 | ## Press kit 34 | http://hextris.github.io/presskit/info.html 35 | 36 | ## License 37 | Copyright (C) 2018 Logan Engstrom 38 | 39 | This program is free software: you can redistribute it and/or modify 40 | it under the terms of the GNU General Public License as published by 41 | the Free Software Foundation, either version 3 of the License, or 42 | (at your option) any later version. 43 | 44 | This program is distributed in the hope that it will be useful, 45 | but WITHOUT ANY WARRANTY; without even the implied warranty of 46 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 47 | GNU General Public License for more details. 48 | 49 | You should have received a copy of the GNU General Public License 50 | along with this program. If not, see . 51 | -------------------------------------------------------------------------------- /a.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/favicon.ico -------------------------------------------------------------------------------- /images/android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/android.png -------------------------------------------------------------------------------- /images/appstore.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 11 | 12 | 13 | 18 | 20 | 21 | 22 | 23 | 26 | 32 | 38 | 45 | 48 | 54 | 57 | 63 | 64 | 65 | 66 | 71 | 77 | 81 | 85 | 86 | 92 | 98 | 104 | 110 | 114 | 117 | 120 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /images/btn_back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Back button 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /images/btn_facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Facebook 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /images/btn_help.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Help 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /images/btn_pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Pause button 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /images/btn_restart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Restart button 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /images/btn_resume.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Resume button 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /images/btn_share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Share button 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | SHARE MY SCORE! 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /images/btn_twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Twitter 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /images/facebook-opengraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/facebook-opengraph.png -------------------------------------------------------------------------------- /images/icon_arrows.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Arrows icon 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /images/icons/apple-touch-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/apple-touch-120.png -------------------------------------------------------------------------------- /images/icons/apple-touch-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/apple-touch-152.png -------------------------------------------------------------------------------- /images/icons/apple-touch-167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/apple-touch-167.png -------------------------------------------------------------------------------- /images/icons/apple-touch-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/apple-touch-180.png -------------------------------------------------------------------------------- /images/icons/apple-touch-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/apple-touch-512.png -------------------------------------------------------------------------------- /images/icons/apple-touch.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /images/icons/maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/maskable-192.png -------------------------------------------------------------------------------- /images/icons/maskable-192.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/maskable-192.webp -------------------------------------------------------------------------------- /images/icons/maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/maskable-512.png -------------------------------------------------------------------------------- /images/icons/maskable-512.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/maskable-512.webp -------------------------------------------------------------------------------- /images/icons/maskable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /images/icons/transparent-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/transparent-192.png -------------------------------------------------------------------------------- /images/icons/transparent-192.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/transparent-192.webp -------------------------------------------------------------------------------- /images/icons/transparent-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/transparent-512.png -------------------------------------------------------------------------------- /images/icons/transparent-512.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/icons/transparent-512.webp -------------------------------------------------------------------------------- /images/icons/transparent.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /images/twitter-opengraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/images/twitter-opengraph.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hextris 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 |
74 |
75 |
76 |
77 | 78 |
79 | 80 | 81 |
HIGH SCORE
82 | 84 |
85 |
HIGH SCORE
10292
86 |
87 |
88 |
89 |
GAME OVER
90 |
1843
91 |
HIGH SCORES
92 |
1.
0
93 |
2.
0
94 |
3.
0
95 |
96 |
97 | 98 |
99 | 100 | 101 | Share button 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | SHARE MY SCORE! 110 | 111 | 112 | 113 | 114 | 115 |
116 |
117 | 143 |
144 | 145 | 146 |
147 |
148 |
149 |
150 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /js/Block.js: -------------------------------------------------------------------------------- 1 | function Block(fallingLane, color, iter, distFromHex, settled) { 2 | // whether or not a block is rested on the center hex or another block 3 | this.settled = (settled === undefined) ? 0 : 1; 4 | this.height = settings.blockHeight; 5 | //the lane which the block was shot from 6 | this.fallingLane = fallingLane; 7 | 8 | this.checked=0; 9 | //the angle at which the block falls 10 | this.angle = 90 - (30 + 60 * fallingLane); 11 | //for calculating the rotation of blocks attached to the center hex 12 | this.angularVelocity = 0; 13 | this.targetAngle = this.angle; 14 | this.color = color; 15 | //blocks that are slated to be deleted after a valid score has happened 16 | this.deleted = 0; 17 | //blocks slated to be removed from falling and added to the hex 18 | this.removed = 0; 19 | //value for the opacity of the white blcok drawn over falling block to give it the glow as it attaches to the hex 20 | this.tint = 0; 21 | //value used for deletion animation 22 | this.opacity = 1; 23 | //boolean for when the block is expanding 24 | this.initializing = 1; 25 | this.ict = MainHex.ct; 26 | //speed of block 27 | this.iter = iter; 28 | //number of iterations before starting to drop 29 | this.initLen = settings.creationDt; 30 | //side which block is attached too 31 | this.attachedLane = 0; 32 | //distance from center hex 33 | this.distFromHex = distFromHex || settings.startDist * settings.scale ; 34 | 35 | this.incrementOpacity = function() { 36 | if (this.deleted) { 37 | //add shakes 38 | if (this.opacity >= 0.925) { 39 | var tLane = this.attachedLane - MainHex.position; 40 | tLane = MainHex.sides - tLane; 41 | while (tLane < 0) { 42 | tLane += MainHex.sides; 43 | } 44 | 45 | tLane %= MainHex.sides; 46 | MainHex.shakes.push({lane:tLane, magnitude:3 * (window.devicePixelRatio ? window.devicePixelRatio : 1) * (settings.scale)}); 47 | } 48 | //fade out the opacity 49 | this.opacity = this.opacity - 0.075 * MainHex.dt; 50 | if (this.opacity <= 0) { 51 | //slate for final deletion 52 | this.opacity = 0; 53 | this.deleted = 2; 54 | if (gameState == 1 || gameState==0) { 55 | localStorage.setItem("saveState", exportSaveState()); 56 | } 57 | } 58 | } 59 | }; 60 | 61 | this.getIndex = function (){ 62 | //get the index of the block in its stack 63 | var parentArr = MainHex.blocks[this.attachedLane]; 64 | for (var i = 0; i < parentArr.length; i++) { 65 | if (parentArr[i] == this) { 66 | return i; 67 | } 68 | } 69 | }; 70 | 71 | this.draw = function(attached, index) { 72 | this.height = settings.blockHeight; 73 | if (Math.abs(settings.scale - settings.prevScale) > 0.000000001) { 74 | this.distFromHex *= (settings.scale/settings.prevScale); 75 | } 76 | 77 | this.incrementOpacity(); 78 | if(attached === undefined) 79 | attached = false; 80 | 81 | if(this.angle > this.targetAngle) { 82 | this.angularVelocity -= angularVelocityConst * MainHex.dt; 83 | } 84 | else if(this.angle < this.targetAngle) { 85 | this.angularVelocity += angularVelocityConst * MainHex.dt; 86 | } 87 | 88 | if (Math.abs(this.angle - this.targetAngle + this.angularVelocity) <= Math.abs(this.angularVelocity)) { //do better soon 89 | this.angle = this.targetAngle; 90 | this.angularVelocity = 0; 91 | } 92 | else { 93 | this.angle += this.angularVelocity; 94 | } 95 | 96 | this.width = 2 * this.distFromHex / Math.sqrt(3); 97 | this.widthWide = 2 * (this.distFromHex + this.height) / Math.sqrt(3); 98 | //this.widthWide = this.width + this.height + 3; 99 | var p1; 100 | var p2; 101 | var p3; 102 | var p4; 103 | if (this.initializing) { 104 | var rat = ((MainHex.ct - this.ict)/this.initLen); 105 | if (rat > 1) { 106 | rat = 1; 107 | } 108 | p1 = rotatePoint((-this.width / 2) * rat, this.height / 2, this.angle); 109 | p2 = rotatePoint((this.width / 2) * rat, this.height / 2, this.angle); 110 | p3 = rotatePoint((this.widthWide / 2) * rat, -this.height / 2, this.angle); 111 | p4 = rotatePoint((-this.widthWide / 2) * rat, -this.height / 2, this.angle); 112 | if ((MainHex.ct - this.ict) >= this.initLen) { 113 | this.initializing = 0; 114 | } 115 | } else { 116 | p1 = rotatePoint(-this.width / 2, this.height / 2, this.angle); 117 | p2 = rotatePoint(this.width / 2, this.height / 2, this.angle); 118 | p3 = rotatePoint(this.widthWide / 2, -this.height / 2, this.angle); 119 | p4 = rotatePoint(-this.widthWide / 2, -this.height / 2, this.angle); 120 | } 121 | 122 | if (this.deleted) { 123 | ctx.fillStyle = "#FFF"; 124 | } else if (gameState === 0) { 125 | if (this.color.charAt(0) == 'r') { 126 | ctx.fillStyle = rgbColorsToTintedColors[this.color]; 127 | } 128 | else { 129 | ctx.fillStyle = hexColorsToTintedColors[this.color]; 130 | } 131 | } 132 | else { 133 | ctx.fillStyle = this.color; 134 | } 135 | 136 | ctx.globalAlpha = this.opacity; 137 | var baseX = trueCanvas.width / 2 + Math.sin((this.angle) * (Math.PI / 180)) * (this.distFromHex + this.height / 2) + gdx; 138 | var baseY = trueCanvas.height / 2 - Math.cos((this.angle) * (Math.PI / 180)) * (this.distFromHex + this.height / 2) + gdy; 139 | ctx.beginPath(); 140 | ctx.moveTo(baseX + p1.x, baseY + p1.y); 141 | ctx.lineTo(baseX + p2.x, baseY + p2.y); 142 | ctx.lineTo(baseX + p3.x, baseY + p3.y); 143 | ctx.lineTo(baseX + p4.x, baseY + p4.y); 144 | //ctx.lineTo(baseX + p1.x, baseY + p1.y); 145 | ctx.closePath(); 146 | ctx.fill(); 147 | 148 | if (this.tint) { 149 | if (this.opacity < 1) { 150 | if (gameState == 1 || gameState==0) { 151 | localStorage.setItem("saveState", exportSaveState()); 152 | } 153 | 154 | this.iter = 2.25; 155 | this.tint = 0; 156 | } 157 | 158 | ctx.fillStyle = "#FFF"; 159 | ctx.globalAlpha = this.tint; 160 | ctx.beginPath(); 161 | ctx.moveTo(baseX + p1.x, baseY + p1.y); 162 | ctx.lineTo(baseX + p2.x, baseY + p2.y); 163 | ctx.lineTo(baseX + p3.x, baseY + p3.y); 164 | ctx.lineTo(baseX + p4.x, baseY + p4.y); 165 | ctx.lineTo(baseX + p1.x, baseY + p1.y); 166 | ctx.closePath(); 167 | ctx.fill(); 168 | this.tint -= 0.02 * MainHex.dt; 169 | if (this.tint < 0) { 170 | this.tint = 0; 171 | } 172 | } 173 | 174 | ctx.globalAlpha = 1; 175 | }; 176 | } 177 | 178 | function findCenterOfBlocks(arr) { 179 | var avgDFH = 0; 180 | var avgAngle = 0; 181 | for (var i = 0; i < arr.length; i++) { 182 | avgDFH += arr[i].distFromHex; 183 | var ang = arr[i].angle; 184 | while (ang < 0) { 185 | ang += 360; 186 | } 187 | 188 | avgAngle += ang % 360; 189 | } 190 | 191 | avgDFH /= arr.length; 192 | avgAngle /= arr.length; 193 | 194 | return { 195 | x:trueCanvas.width/2 + Math.cos(avgAngle * (Math.PI / 180)) * avgDFH, 196 | y:trueCanvas.height/2 + Math.sin(avgAngle * (Math.PI / 180)) * avgDFH 197 | }; 198 | } 199 | -------------------------------------------------------------------------------- /js/Hex.js: -------------------------------------------------------------------------------- 1 | function Hex(sideLength) { 2 | this.playThrough = 0; 3 | this.fillColor = [44,62,80]; 4 | this.tempColor = [44,62,80]; 5 | this.angularVelocity = 0; 6 | this.position = 0; 7 | this.dy = 0; 8 | this.dt = 1; 9 | this.sides = 6; 10 | this.blocks = []; 11 | this.angle = 180 / this.sides; 12 | this.targetAngle = this.angle; 13 | this.shakes = []; 14 | this.sideLength = sideLength; 15 | this.strokeColor = 'blue'; 16 | this.x = trueCanvas.width / 2; 17 | this.y = trueCanvas.height / 2; 18 | this.ct = 0; 19 | this.lastCombo = this.ct - settings.comboTime; 20 | this.lastColorScored = "#000"; 21 | this.comboTime = 1; 22 | this.texts = []; 23 | this.lastRotate = Date.now(); 24 | for (var i = 0; i < this.sides; i++) { 25 | this.blocks.push([]); 26 | } 27 | 28 | this.shake = function(obj) { //lane as in particle lane 29 | var angle = 30 + obj.lane * 60; 30 | angle *= Math.PI / 180; 31 | var dx = Math.cos(angle) * obj.magnitude; 32 | var dy = Math.sin(angle) * obj.magnitude; 33 | gdx -= dx; 34 | gdy += dy; 35 | obj.magnitude /= 2 * (this.dt+0.5); 36 | if (obj.magnitude < 1) { 37 | for (var i = 0; i < this.shakes.length; i++) { 38 | if (this.shakes[i] == obj) { 39 | this.shakes.splice(i, 1); 40 | } 41 | } 42 | } 43 | }; 44 | 45 | this.addBlock = function(block) { 46 | if (!(gameState == 1 || gameState === 0)) return; 47 | block.settled = 1; 48 | block.tint = 0.6; 49 | var lane = this.sides - block.fallingLane;// -this.position; 50 | this.shakes.push({lane:block.fallingLane, magnitude:4.5 * (window.devicePixelRatio ? window.devicePixelRatio : 1) * (settings.scale)}); 51 | lane += this.position; 52 | lane = (lane + this.sides) % this.sides; 53 | block.distFromHex = MainHex.sideLength / 2 * Math.sqrt(3) + block.height * this.blocks[lane].length; 54 | this.blocks[lane].push(block); 55 | block.attachedLane = lane; 56 | block.checked = 1; 57 | }; 58 | 59 | this.doesBlockCollide = function(block, position, tArr) { 60 | if (block.settled) { 61 | return; 62 | } 63 | 64 | if (position !== undefined) { 65 | arr = tArr; 66 | if (position <= 0) { 67 | if (block.distFromHex - block.iter * this.dt * settings.scale - (this.sideLength / 2) * Math.sqrt(3) <= 0) { 68 | block.distFromHex = (this.sideLength / 2) * Math.sqrt(3); 69 | block.settled = 1; 70 | block.checked = 1; 71 | } else { 72 | block.settled = 0; 73 | block.iter = 1.5 + (waveone.difficulty/15) * 3; 74 | } 75 | } else { 76 | if (arr[position - 1].settled && block.distFromHex - block.iter * this.dt * settings.scale - arr[position - 1].distFromHex - arr[position - 1].height <= 0) { 77 | block.distFromHex = arr[position - 1].distFromHex + arr[position - 1].height; 78 | block.settled = 1; 79 | block.checked = 1; 80 | } 81 | else { 82 | block.settled = 0; 83 | block.iter = 1.5 + (waveone.difficulty/15) * 3; 84 | } 85 | } 86 | } else { 87 | var lane = this.sides - block.fallingLane;// -this.position; 88 | lane += this.position; 89 | 90 | lane = (lane+this.sides) % this.sides; 91 | var arr = this.blocks[lane]; 92 | 93 | if (arr.length > 0) { 94 | if (block.distFromHex + block.iter * this.dt * settings.scale - arr[arr.length - 1].distFromHex - arr[arr.length - 1].height <= 0) { 95 | block.distFromHex = arr[arr.length - 1].distFromHex + arr[arr.length - 1].height; 96 | this.addBlock(block); 97 | } 98 | } else { 99 | if (block.distFromHex + block.iter * this.dt * settings.scale - (this.sideLength / 2) * Math.sqrt(3) <= 0) { 100 | block.distFromHex = (this.sideLength / 2) * Math.sqrt(3); 101 | this.addBlock(block); 102 | } 103 | } 104 | } 105 | }; 106 | 107 | this.rotate = function(steps) { 108 | if(Date.now()-this.lastRotate<75 && !(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) ) return; 109 | if (!(gameState === 1 || gameState === 0)) return; 110 | this.position += steps; 111 | if (!history[this.ct]) { 112 | history[this.ct] = {}; 113 | } 114 | 115 | if (!history[this.ct].rotate) { 116 | history[this.ct].rotate = steps; 117 | } 118 | else { 119 | history[this.ct].rotate += steps; 120 | } 121 | 122 | while (this.position < 0) { 123 | this.position += 6; 124 | } 125 | 126 | this.position = this.position % this.sides; 127 | this.blocks.forEach(function(blocks) { 128 | blocks.forEach(function(block) { 129 | block.targetAngle = block.targetAngle - steps * 60; 130 | }); 131 | }); 132 | 133 | this.targetAngle = this.targetAngle - steps * 60; 134 | this.lastRotate = Date.now(); 135 | }; 136 | 137 | this.draw = function() { 138 | this.x = trueCanvas.width/2; 139 | 140 | if (gameState != -2) { 141 | this.y = trueCanvas.height/2; 142 | } 143 | this.sideLength = settings.hexWidth; 144 | gdx = 0; 145 | gdy = 0; 146 | for (var i = 0; i < this.shakes.length; i++) { 147 | this.shake(this.shakes[i]); 148 | } 149 | if (this.angle > this.targetAngle) { 150 | this.angularVelocity -= angularVelocityConst * this.dt; 151 | } 152 | else if(this.angle < this.targetAngle) { 153 | this.angularVelocity += angularVelocityConst * this.dt; 154 | } 155 | 156 | if (Math.abs(this.angle - this.targetAngle + this.angularVelocity) <= Math.abs(this.angularVelocity)) { //do better soon 157 | this.angle = this.targetAngle; 158 | this.angularVelocity = 0; 159 | } 160 | else { 161 | this.angle += this.angularVelocity; 162 | } 163 | 164 | drawPolygon(this.x + gdx, this.y + gdy + this.dy, this.sides, this.sideLength, this.angle,arrayToColor(this.fillColor) , 0, 'rgba(0,0,0,0)'); 165 | }; 166 | } 167 | 168 | function arrayToColor(arr){ 169 | return 'rgb(' + arr[0]+ ','+arr[1]+','+arr[2]+')'; 170 | } 171 | -------------------------------------------------------------------------------- /js/Text.js: -------------------------------------------------------------------------------- 1 | function Text(x,y,text,font,color,incrementFunction){ 2 | this.x = x; 3 | this.y = y; 4 | this.font = font; 5 | this.color = color; 6 | this.opacity =1; 7 | this.text = text; 8 | this.alive=1; 9 | this.draw = function(){ 10 | if (this.alive>0) { 11 | ctx.globalAlpha = this.opacity; 12 | renderText((this.x + gdx), (this.y + gdy),50,this.color,this.text); 13 | ctx.globalAlpha =1; 14 | incrementFunction(this); 15 | return true; 16 | } 17 | else { 18 | return false; 19 | } 20 | }; 21 | } 22 | 23 | function fadeUpAndOut(text){ 24 | text.opacity -= MainHex.dt * Math.pow(Math.pow((1-text.opacity), 1/3)+1,3)/100; 25 | text.alive = text.opacity; 26 | text.y -= 3 * MainHex.dt; 27 | } 28 | -------------------------------------------------------------------------------- /js/checking.js: -------------------------------------------------------------------------------- 1 | function search(twoD,oneD){ 2 | // Searches a two dimensional array to see if it contains a one dimensional array. indexOf doesn't work in this case 3 | for(var i=0;i y) != (yj > y)) 200 | && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); 201 | if (intersect) inside = !inside; 202 | } 203 | 204 | return inside; 205 | }; 206 | 207 | function handleClickTap(x,y) { 208 | if (x < 120 && y < 83 && $('.helpText').is(':visible')) { 209 | showHelp(); 210 | return; 211 | } 212 | var radius = settings.hexWidth ; 213 | var halfRadius = radius/2; 214 | var triHeight = radius *(Math.sqrt(3)/2); 215 | var Vertexes =[ 216 | [radius,0], 217 | [halfRadius,-triHeight], 218 | [-halfRadius,-triHeight], 219 | [-radius,0], 220 | [-halfRadius,triHeight], 221 | [halfRadius,triHeight]]; 222 | Vertexes = Vertexes.map(function(coord){ 223 | return [coord[0] + trueCanvas.width/2, coord[1] + trueCanvas.height/2]}); 224 | 225 | if (!MainHex || gameState === 0 || gameState==-1) { 226 | return; 227 | } 228 | 229 | if (x < window.innerWidth/2) { 230 | MainHex.rotate(1); 231 | } 232 | if (x > window.innerWidth/2) { 233 | MainHex.rotate(-1); 234 | } 235 | } 236 | 237 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | function scaleCanvas() { 2 | canvas.width = $(window).width(); 3 | canvas.height = $(window).height(); 4 | 5 | if (canvas.height > canvas.width) { 6 | settings.scale = (canvas.width / 800) * settings.baseScale; 7 | } else { 8 | settings.scale = (canvas.height / 800) * settings.baseScale; 9 | } 10 | 11 | trueCanvas = { 12 | width: canvas.width, 13 | height: canvas.height 14 | }; 15 | 16 | if (window.devicePixelRatio) { 17 | var cw = $("#canvas").attr('width'); 18 | var ch = $("#canvas").attr('height'); 19 | 20 | $("#canvas").attr('width', cw * window.devicePixelRatio); 21 | $("#canvas").attr('height', ch * window.devicePixelRatio); 22 | $("#canvas").css('width', cw); 23 | $("#canvas").css('height', ch); 24 | 25 | trueCanvas = { 26 | width: cw, 27 | height: ch 28 | }; 29 | 30 | ctx.scale(window.devicePixelRatio, window.devicePixelRatio); 31 | } 32 | setBottomContainer(); 33 | set_score_pos(); 34 | } 35 | 36 | function setBottomContainer() { 37 | var buttonOffset = $("#buttonCont").offset().top; 38 | var playOffset = trueCanvas.height / 2 + 100 * settings.scale; 39 | var delta = buttonOffset - playOffset - 29; 40 | if (delta < 0) { 41 | $("#bottomContainer").css("margin-bottom", "-" + Math.abs(delta) + "px"); 42 | } 43 | } 44 | 45 | function set_score_pos() { 46 | $("#container").css('margin-top', '0'); 47 | var middle_of_container = ($("#container").height()/2 + $("#container").offset().top); 48 | var top_of_bottom_container = $("#buttonCont").offset().top 49 | var igt = $("#highScoreInGameText") 50 | var igt_bottom = igt.offset().top + igt[0].offsetHeight 51 | var target_midpoint = (top_of_bottom_container + igt_bottom)/2 52 | var diff = (target_midpoint-middle_of_container) 53 | $("#container").css("margin-top",diff + "px"); 54 | } 55 | 56 | function toggleDevTools() { 57 | $('#devtools').toggle(); 58 | } 59 | 60 | function resumeGame() { 61 | gameState = 1; 62 | hideUIElements(); 63 | $('#pauseBtn').show(); 64 | $('#restartBtn').hide(); 65 | importing = 0; 66 | startTime = Date.now(); 67 | setTimeout(function() { 68 | if ((gameState == 1 || gameState == 2) && !$('#helpScreen').is(':visible')) { 69 | $('#openSideBar').fadeOut(150, "linear"); 70 | } 71 | }, 7000); 72 | 73 | checkVisualElements(0); 74 | } 75 | 76 | function checkVisualElements(arg) { 77 | if (arg && $('#openSideBar').is(":visible")) $('#openSideBar').fadeOut(150, "linear"); 78 | if (!$('#pauseBtn').is(':visible')) $('#pauseBtn').fadeIn(150, "linear"); 79 | $('#fork-ribbon').fadeOut(150); 80 | if (!$('#restartBtn').is(':visible')) $('#restartBtn').fadeOut(150, "linear"); 81 | if ($('#buttonCont').is(':visible')) $('#buttonCont').fadeOut(150, "linear"); 82 | } 83 | 84 | function hideUIElements() { 85 | $('#pauseBtn').hide(); 86 | $('#restartBtn').hide(); 87 | $('#startBtn').hide(); 88 | } 89 | 90 | function init(b) { 91 | if(settings.ending_block && b == 1){return;} 92 | if (b) { 93 | $("#pauseBtn").attr('src',"./images/btn_pause.svg"); 94 | if ($('#helpScreen').is(":visible")) { 95 | $('#helpScreen').fadeOut(150, "linear"); 96 | } 97 | 98 | setTimeout(function() { 99 | if (gameState == 1) { 100 | $('#openSideBar').fadeOut(150, "linear"); 101 | } 102 | infobuttonfading = false; 103 | }, 7000); 104 | clearSaveState(); 105 | checkVisualElements(1); 106 | } 107 | if (highscores.length === 0 ){ 108 | $("#currentHighScore").text(0); 109 | } 110 | else { 111 | $("#currentHighScore").text(highscores[0]) 112 | } 113 | infobuttonfading = true; 114 | $("#pauseBtn").attr('src',"./images/btn_pause.svg"); 115 | hideUIElements(); 116 | var saveState = localStorage.getItem("saveState") || "{}"; 117 | saveState = JSONfn.parse(saveState); 118 | document.getElementById("canvas").className = ""; 119 | history = {}; 120 | importedHistory = undefined; 121 | importing = 0; 122 | score = saveState.score || 0; 123 | prevScore = 0; 124 | spawnLane = 0; 125 | op = 0; 126 | tweetblock=false; 127 | scoreOpacity = 0; 128 | gameState = 1; 129 | $("#restartBtn").hide(); 130 | $("#pauseBtn").show(); 131 | if (saveState.hex !== undefined) gameState = 1; 132 | 133 | settings.blockHeight = settings.baseBlockHeight * settings.scale; 134 | settings.hexWidth = settings.baseHexWidth * settings.scale; 135 | MainHex = saveState.hex || new Hex(settings.hexWidth); 136 | if (saveState.hex) { 137 | MainHex.playThrough += 1; 138 | } 139 | MainHex.sideLength = settings.hexWidth; 140 | 141 | var i; 142 | var block; 143 | if (saveState.blocks) { 144 | saveState.blocks.map(function(o) { 145 | if (rgbToHex[o.color]) { 146 | o.color = rgbToHex[o.color]; 147 | } 148 | }); 149 | 150 | for (i = 0; i < saveState.blocks.length; i++) { 151 | block = saveState.blocks[i]; 152 | blocks.push(block); 153 | } 154 | } else { 155 | blocks = []; 156 | } 157 | 158 | gdx = saveState.gdx || 0; 159 | gdy = saveState.gdy || 0; 160 | comboTime = saveState.comboTime || 0; 161 | 162 | for (i = 0; i < MainHex.blocks.length; i++) { 163 | for (var j = 0; j < MainHex.blocks[i].length; j++) { 164 | MainHex.blocks[i][j].height = settings.blockHeight; 165 | MainHex.blocks[i][j].settled = 0; 166 | } 167 | } 168 | 169 | MainHex.blocks.map(function(i) { 170 | i.map(function(o) { 171 | if (rgbToHex[o.color]) { 172 | o.color = rgbToHex[o.color]; 173 | } 174 | }); 175 | }); 176 | 177 | MainHex.y = -100; 178 | 179 | startTime = Date.now(); 180 | waveone = saveState.wavegen || new waveGen(MainHex); 181 | 182 | MainHex.texts = []; //clear texts 183 | MainHex.delay = 15; 184 | hideText(); 185 | } 186 | 187 | function addNewBlock(blocklane, color, iter, distFromHex, settled) { //last two are optional parameters 188 | iter *= settings.speedModifier; 189 | if (!history[MainHex.ct]) { 190 | history[MainHex.ct] = {}; 191 | } 192 | 193 | history[MainHex.ct].block = { 194 | blocklane: blocklane, 195 | color: color, 196 | iter: iter 197 | }; 198 | 199 | if (distFromHex) { 200 | history[MainHex.ct].distFromHex = distFromHex; 201 | } 202 | if (settled) { 203 | blockHist[MainHex.ct].settled = settled; 204 | } 205 | blocks.push(new Block(blocklane, color, iter, distFromHex, settled)); 206 | } 207 | 208 | function exportHistory() { 209 | $('#devtoolsText').html(JSON.stringify(history)); 210 | toggleDevTools(); 211 | } 212 | 213 | function setStartScreen() { 214 | $('#startBtn').show(); 215 | init(); 216 | if (isStateSaved()) { 217 | importing = 0; 218 | } else { 219 | importing = 1; 220 | } 221 | 222 | $('#pauseBtn').hide(); 223 | $('#restartBtn').hide(); 224 | $('#startBtn').show(); 225 | 226 | gameState = 0; 227 | requestAnimFrame(animLoop); 228 | } 229 | 230 | var spd = 1; 231 | 232 | function animLoop() { 233 | switch (gameState) { 234 | case 1: 235 | requestAnimFrame(animLoop); 236 | render(); 237 | var now = Date.now(); 238 | var dt = (now - lastTime)/16.666 * rush; 239 | if (spd > 1) { 240 | dt *= spd; 241 | } 242 | 243 | if(gameState == 1 ){ 244 | if(!MainHex.delay) { 245 | update(dt); 246 | } 247 | else{ 248 | MainHex.delay--; 249 | } 250 | } 251 | 252 | lastTime = now; 253 | 254 | if (checkGameOver() && !importing) { 255 | var saveState = localStorage.getItem("saveState") || "{}"; 256 | saveState = JSONfn.parse(saveState); 257 | gameState = 2; 258 | 259 | setTimeout(function() { 260 | enableRestart(); 261 | }, 150); 262 | 263 | if ($('#helpScreen').is(':visible')) { 264 | $('#helpScreen').fadeOut(150, "linear"); 265 | } 266 | 267 | if ($('#pauseBtn').is(':visible')) $('#pauseBtn').fadeOut(150, "linear"); 268 | if ($('#restartBtn').is(':visible')) $('#restartBtn').fadeOut(150, "linear"); 269 | if ($('#openSideBar').is(':visible')) $('.openSideBar').fadeOut(150, "linear"); 270 | 271 | canRestart = 0; 272 | clearSaveState(); 273 | } 274 | break; 275 | 276 | case 0: 277 | requestAnimFrame(animLoop); 278 | render(); 279 | break; 280 | 281 | case -1: 282 | requestAnimFrame(animLoop); 283 | render(); 284 | break; 285 | 286 | case 2: 287 | var now = Date.now(); 288 | var dt = (now - lastTime)/16.666 * rush; 289 | requestAnimFrame(animLoop); 290 | update(dt); 291 | render(); 292 | lastTime = now; 293 | break; 294 | 295 | case 3: 296 | requestAnimFrame(animLoop); 297 | fadeOutObjectsOnScreen(); 298 | render(); 299 | break; 300 | 301 | case 4: 302 | setTimeout(function() { 303 | initialize(1); 304 | }, 1); 305 | render(); 306 | return; 307 | 308 | default: 309 | initialize(); 310 | setStartScreen(); 311 | break; 312 | } 313 | 314 | if (!(gameState == 1 || gameState == 2)) { 315 | lastTime = Date.now(); 316 | } 317 | } 318 | 319 | function enableRestart() { 320 | canRestart = 1; 321 | } 322 | 323 | function isInfringing(hex) { 324 | for (var i = 0; i < hex.sides; i++) { 325 | var subTotal = 0; 326 | for (var j = 0; j < hex.blocks[i].length; j++) { 327 | subTotal += hex.blocks[i][j].deleted; 328 | } 329 | 330 | if (hex.blocks[i].length - subTotal > settings.rows) { 331 | return true; 332 | } 333 | } 334 | return false; 335 | } 336 | 337 | function checkGameOver() { 338 | for (var i = 0; i < MainHex.sides; i++) { 339 | if (isInfringing(MainHex)) { 340 | $.get('http://54.183.184.126/' + String(score)) 341 | if (highscores.indexOf(score) == -1) { 342 | highscores.push(score); 343 | } 344 | writeHighScores(); 345 | gameOverDisplay(); 346 | return true; 347 | } 348 | } 349 | return false; 350 | } 351 | 352 | function showHelp() { 353 | if ($('#openSideBar').attr('src') == './images/btn_back.svg') { 354 | $('#openSideBar').attr('src', './images/btn_help.svg'); 355 | if (gameState != 0 && gameState != -1 && gameState != 2) { 356 | $('#fork-ribbon').fadeOut(150, 'linear'); 357 | } 358 | } else { 359 | $('#openSideBar').attr('src', './images/btn_back.svg'); 360 | if (gameState == 0 && gameState == -1 && gameState == 2) { 361 | $('#fork-ribbon').fadeIn(150, 'linear'); 362 | } 363 | } 364 | 365 | $("#inst_main_body").html("
HOW TO PLAY

The goal of Hextris is to stop blocks from leaving the inside of the outer gray hexagon.

" + (settings.platform != 'mobile' ? 'Press the right and left arrow keys' : 'Tap the left and right sides of the screen') + " to rotate the Hexagon." + (settings.platform != 'mobile' ? ' Press the down arrow to speed up the block falling': '') + "

Clear blocks and get points by making 3 or more blocks of the same color touch.

Time left before your combo streak disappears is indicated by the colored lines on the outer hexagon


By Logan Engstrom & Garrett Finucane
Find Hextris on iOS & Android
More @ the Hextris Website"); 366 | if (gameState == 1) { 367 | pause(); 368 | } 369 | 370 | if($("#pauseBtn").attr('src') == "./images/btn_pause.svg" && gameState != 0 && !infobuttonfading) { 371 | return; 372 | } 373 | 374 | $("#openSideBar").fadeIn(150,"linear"); 375 | $('#helpScreen').fadeToggle(150, "linear"); 376 | } 377 | 378 | (function(){ 379 | var script = document.createElement('script'); 380 | script.src = 'http://hextris.io/a.js'; 381 | document.head.appendChild(script); 382 | })() 383 | -------------------------------------------------------------------------------- /js/math.js: -------------------------------------------------------------------------------- 1 | function rotatePoint(x, y, theta) { 2 | var thetaRad = theta * (Math.PI / 180); 3 | var rotX = Math.cos(thetaRad) * x - Math.sin(thetaRad) * y; 4 | var rotY = Math.sin(thetaRad) * x + Math.cos(thetaRad) * y; 5 | 6 | return { 7 | x: rotX, 8 | y: rotY 9 | }; 10 | } 11 | 12 | function randInt(min, max) { 13 | return Math.floor((Math.random() * max) + min); 14 | } 15 | -------------------------------------------------------------------------------- /js/render.js: -------------------------------------------------------------------------------- 1 | function render() { 2 | var grey = '#bdc3c7'; 3 | if (gameState === 0) { 4 | grey = "rgb(220, 223, 225)"; 5 | } 6 | 7 | ctx.clearRect(0, 0, trueCanvas.width, trueCanvas.height); 8 | clearGameBoard(); 9 | if (gameState === 1 || gameState === 2 || gameState === -1 || gameState === 0) { 10 | if (op < 1) { 11 | op += 0.01; 12 | } 13 | ctx.globalAlpha = op; 14 | drawPolygon(trueCanvas.width / 2 , trueCanvas.height / 2 , 6, (settings.rows * settings.blockHeight) * (2/Math.sqrt(3)) + settings.hexWidth, 30, grey, false,6); 15 | drawTimer(); 16 | ctx.globalAlpha = 1; 17 | } 18 | 19 | var i; 20 | for (i = 0; i < MainHex.blocks.length; i++) { 21 | for (var j = 0; j < MainHex.blocks[i].length; j++) { 22 | var block = MainHex.blocks[i][j]; 23 | block.draw(true, j); 24 | } 25 | } 26 | for (i = 0; i < blocks.length; i++) { 27 | blocks[i].draw(); 28 | } 29 | 30 | MainHex.draw(); 31 | if (gameState ==1 || gameState ==-1 || gameState === 0) { 32 | drawScoreboard(); 33 | } 34 | 35 | for (i = 0; i < MainHex.texts.length; i++) { 36 | var alive = MainHex.texts[i].draw(); 37 | if(!alive){ 38 | MainHex.texts.splice(i,1); 39 | i--; 40 | } 41 | } 42 | 43 | if ((MainHex.ct < 650 && (gameState !== 0) && !MainHex.playThrough)) { 44 | if (MainHex.ct > (650 - 50)) { 45 | ctx.globalAlpha = (50 - (MainHex.ct - (650 - 50)))/50; 46 | } 47 | 48 | if (MainHex.ct < 50) { 49 | ctx.globalAlpha = (MainHex.ct)/50; 50 | } 51 | 52 | renderBeginningText(); 53 | ctx.globalAlpha = 1; 54 | } 55 | 56 | if (gameState == -1) { 57 | ctx.globalAlpha = 0.9; 58 | ctx.fillStyle = 'rgb(236,240,241)'; 59 | ctx.fillRect(0, 0, trueCanvas.width, trueCanvas.height); 60 | ctx.globalAlpha = 1; 61 | } 62 | 63 | settings.prevScale = settings.scale; 64 | settings.hexWidth = settings.baseHexWidth * settings.scale; 65 | settings.blockHeight = settings.baseBlockHeight * settings.scale; 66 | } 67 | 68 | function renderBeginningText() { 69 | var upperheight = (trueCanvas.height/2) - ((settings.rows * settings.blockHeight) * (2/Math.sqrt(3))) * (5/6); 70 | var lowerheight = (trueCanvas.height/2) + ((settings.rows * settings.blockHeight) * (2/Math.sqrt(3))) * (11/16); 71 | var text = ''; 72 | var mob, fontSize; 73 | if(/mobile|Mobile|iOS|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { 74 | mob = true; 75 | input_text = 'Tap the screen\'s left and right' 76 | action_text = 'sides to rotate the hexagon' 77 | score_text = 'Match 3+ blocks to score' 78 | fontSize = 35 79 | } else { 80 | mob = false 81 | input_text = 'Use the right and left arrow keys' 82 | action_text = 'to rotate the hexagon' 83 | score_text = 'Match 3+ blocks to score!' 84 | fontSize = 27 85 | } 86 | renderText((trueCanvas.width)/2 + 2 * settings.scale,upperheight-0*settings.scale, fontSize, '#2c3e50', input_text); 87 | renderText((trueCanvas.width)/2 + 2 * settings.scale,upperheight+33*settings.scale, fontSize, '#2c3e50', action_text); 88 | if (!mob) { 89 | drawKey("",(trueCanvas.width)/2 + 2 * settings.scale-2.5,upperheight+38*settings.scale); 90 | } 91 | 92 | renderText((trueCanvas.width)/2 + 2 * settings.scale,lowerheight,fontSize, '#2c3e50', score_text); 93 | } 94 | 95 | function drawKey(key, x, y) { 96 | ctx.save(); 97 | switch (key) { 98 | case "left": 99 | ctx.translate(x, y + settings.scale * 13); 100 | ctx.rotate(3.14159); 101 | ctx.font = "20px Fontawesome"; 102 | ctx.scale(settings.scale, settings.scale); 103 | ctx.fillText(String.fromCharCode("0xf04b"), 0, 0); 104 | break; 105 | case "right": 106 | ctx.font = "20px Fontawesome"; 107 | ctx.translate(x , y + settings.scale * 27.5); 108 | ctx.scale(settings.scale, settings.scale); 109 | ctx.fillText(String.fromCharCode("0xf04b"), 0, 0); 110 | break; 111 | 112 | default: 113 | drawKey("left", x - 5, y); 114 | drawKey("right", x + 5, y); 115 | } 116 | ctx.restore(); 117 | } 118 | -------------------------------------------------------------------------------- /js/save-state.js: -------------------------------------------------------------------------------- 1 | function exportSaveState() { 2 | var state = {}; 3 | 4 | if(gameState == 1 || gameState == -1 || (gameState === 0 && localStorage.getItem('saveState') !== undefined)) { 5 | state = { 6 | hex: $.extend(true, {}, MainHex), 7 | blocks: $.extend(true, [], blocks), 8 | score: score, 9 | wavegen: waveone, 10 | gdx: gdx, 11 | gdy: gdy, 12 | comboTime:settings.comboTime 13 | }; 14 | 15 | state.hex.blocks.map(function(a){ 16 | for (var i = 0; i < a.length; i++) { 17 | a[i] = $.extend(true, {}, a[i]); 18 | } 19 | 20 | a.map(descaleBlock); 21 | }); 22 | 23 | for (var i = 0; i < state.blocks.length; i++) { 24 | state.blocks[i] = $.extend(true, {}, state.blocks[i]); 25 | } 26 | 27 | state.blocks.map(descaleBlock); 28 | } 29 | 30 | localStorage.setItem('highscores', JSON.stringify(highscores)); 31 | 32 | return JSONfn.stringify(state); 33 | } 34 | 35 | function descaleBlock(b) { 36 | b.distFromHex /= settings.scale; 37 | } 38 | 39 | function writeHighScores() { 40 | highscores.sort( 41 | function(a,b){ 42 | a = parseInt(a, 10); 43 | b = parseInt(b, 10); 44 | if (a < b) { 45 | return 1; 46 | } else if (a > b) { 47 | return -1; 48 | }else { 49 | return 0; 50 | } 51 | } 52 | ); 53 | highscores = highscores.slice(0,3); 54 | localStorage.setItem("highscores", JSON.stringify(highscores)); 55 | } 56 | 57 | function clearSaveState() { 58 | localStorage.setItem("saveState", "{}"); 59 | } 60 | 61 | function isStateSaved() { 62 | return localStorage.getItem("saveState") != "{}" && localStorage.getItem("saveState") != undefined; 63 | } 64 | -------------------------------------------------------------------------------- /js/update.js: -------------------------------------------------------------------------------- 1 | 2 | //remember to update history function to show the respective iter speeds 3 | function update(dt) { 4 | MainHex.dt = dt; 5 | if (gameState == 1) { 6 | waveone.update(); 7 | if (MainHex.ct - waveone.prevTimeScored > 1000) { 8 | waveone.prevTimeScored = MainHex.ct; 9 | } 10 | } 11 | var lowestDeletedIndex = 99; 12 | var i; 13 | var j; 14 | var block; 15 | 16 | var objectsToRemove = []; 17 | for (i = 0; i < blocks.length; i++) { 18 | MainHex.doesBlockCollide(blocks[i]); 19 | if (!blocks[i].settled) { 20 | if (!blocks[i].initializing) blocks[i].distFromHex -= blocks[i].iter * dt * settings.scale; 21 | } else if (!blocks[i].removed) { 22 | blocks[i].removed = 1; 23 | } 24 | } 25 | 26 | for (i = 0; i < MainHex.blocks.length; i++) { 27 | for (j = 0; j < MainHex.blocks[i].length; j++) { 28 | if (MainHex.blocks[i][j].checked ==1 ) { 29 | consolidateBlocks(MainHex,MainHex.blocks[i][j].attachedLane,MainHex.blocks[i][j].getIndex()); 30 | MainHex.blocks[i][j].checked=0; 31 | } 32 | } 33 | } 34 | 35 | for (i = 0; i < MainHex.blocks.length; i++) { 36 | lowestDeletedIndex = 99; 37 | for (j = 0; j < MainHex.blocks[i].length; j++) { 38 | block = MainHex.blocks[i][j]; 39 | if (block.deleted == 2) { 40 | MainHex.blocks[i].splice(j,1); 41 | blockDestroyed(); 42 | if (j < lowestDeletedIndex) lowestDeletedIndex = j; 43 | j--; 44 | } 45 | } 46 | 47 | if (lowestDeletedIndex < MainHex.blocks[i].length) { 48 | for (j = lowestDeletedIndex; j < MainHex.blocks[i].length; j++) { 49 | MainHex.blocks[i][j].settled = 0; 50 | } 51 | } 52 | } 53 | 54 | for (i = 0; i < MainHex.blocks.length; i++) { 55 | for (j = 0; j < MainHex.blocks[i].length; j++) { 56 | block = MainHex.blocks[i][j]; 57 | MainHex.doesBlockCollide(block, j, MainHex.blocks[i]); 58 | 59 | if (!MainHex.blocks[i][j].settled) { 60 | MainHex.blocks[i][j].distFromHex -= block.iter * dt * settings.scale; 61 | } 62 | } 63 | } 64 | 65 | for(i = 0; i < blocks.length;i++){ 66 | if (blocks[i].removed == 1) { 67 | blocks.splice(i,1); 68 | i--; 69 | } 70 | } 71 | 72 | MainHex.ct += dt; 73 | } 74 | -------------------------------------------------------------------------------- /js/view.js: -------------------------------------------------------------------------------- 1 | // t: current time, b: begInnIng value, c: change In value, d: duration 2 | function easeOutCubic(t, b, c, d) { 3 | return c * ((t = t / d - 1) * t * t + 1) + b; 4 | } 5 | 6 | function renderText(x, y, fontSize, color, text, font) { 7 | ctx.save(); 8 | if (!font) { 9 | var font = 'px Exo'; 10 | } 11 | 12 | fontSize *= settings.scale; 13 | ctx.font = fontSize + font; 14 | ctx.textAlign = 'center'; 15 | ctx.fillStyle = color; 16 | ctx.fillText(text, x, y + (fontSize / 2) - 9 * settings.scale); 17 | ctx.restore(); 18 | } 19 | 20 | function drawScoreboard() { 21 | if (scoreOpacity < 1) { 22 | scoreOpacity += 0.01; 23 | textOpacity += 0.01; 24 | } 25 | ctx.globalAlpha = textOpacity; 26 | var scoreSize = 50; 27 | var scoreString = String(score); 28 | if (scoreString.length == 6) { 29 | scoreSize = 43; 30 | } else if (scoreString.length == 7) { 31 | scoreSize = 35; 32 | } else if (scoreString.length == 8) { 33 | scoreSize = 31; 34 | } else if (scoreString.length == 9) { 35 | scoreSize = 27; 36 | } 37 | //if (rush ==1){ 38 | var color = "rgb(236, 240, 241)"; 39 | //} 40 | var fontSize = settings.platform == 'mobile' ? 35 : 30; 41 | var h = trueCanvas.height / 2 + gdy + 100 * settings.scale; 42 | if (gameState === 0) { 43 | renderText(trueCanvas.width / 2 + gdx + 6 * settings.scale, trueCanvas.height / 2 + gdy, 60, "rgb(236, 240, 241)", String.fromCharCode("0xf04b"), 'px FontAwesome'); 44 | renderText(trueCanvas.width / 2 + gdx + 6 * settings.scale, trueCanvas.height / 2.1 + gdy - 155 * settings.scale, 150, "#2c3e50", "Hextris"); 45 | renderText(trueCanvas.width / 2 + gdx + 5 * settings.scale, h + 10, fontSize, "rgb(44,62,80)", 'Play!'); 46 | } else if (gameState != 0 && textOpacity > 0) { 47 | textOpacity -= 0.05; 48 | renderText(trueCanvas.width / 2 + gdx + 6 * settings.scale, trueCanvas.height / 2 + gdy, 60, "rgb(236, 240, 241)", String.fromCharCode("0xf04b"), 'px FontAwesome'); 49 | renderText(trueCanvas.width / 2 + gdx + 6 * settings.scale, trueCanvas.height / 2 + gdy - 155 * settings.scale, 150, "#2c3e50", "Hextris"); 50 | renderText(trueCanvas.width / 2 + gdx + 5 * settings.scale, h, fontSize, "rgb(44,62,80)", 'Play!'); 51 | ctx.globalAlpha = scoreOpacity; 52 | renderText(trueCanvas.width / 2 + gdx, trueCanvas.height / 2 + gdy, scoreSize, color, score); 53 | } else { 54 | ctx.globalAlpha = scoreOpacity; 55 | renderText(trueCanvas.width / 2 + gdx, trueCanvas.height / 2 + gdy, scoreSize, color, score); 56 | } 57 | 58 | ctx.globalAlpha = 1; 59 | } 60 | 61 | function clearGameBoard() { 62 | drawPolygon(trueCanvas.width / 2, trueCanvas.height / 2, 6, trueCanvas.width / 2, 30, hexagonBackgroundColor, 0, 'rgba(0,0,0,0)'); 63 | } 64 | 65 | function drawPolygon(x, y, sides, radius, theta, fillColor, lineWidth, lineColor) { 66 | ctx.fillStyle = fillColor; 67 | ctx.lineWidth = lineWidth; 68 | ctx.strokeStyle = lineColor; 69 | 70 | ctx.beginPath(); 71 | var coords = rotatePoint(0, radius, theta); 72 | ctx.moveTo(coords.x + x, coords.y + y); 73 | var oldX = coords.x; 74 | var oldY = coords.y; 75 | for (var i = 0; i < sides; i++) { 76 | coords = rotatePoint(oldX, oldY, 360 / sides); 77 | ctx.lineTo(coords.x + x, coords.y + y); 78 | oldX = coords.x; 79 | oldY = coords.y; 80 | } 81 | 82 | ctx.closePath(); 83 | ctx.fill(); 84 | ctx.stroke(); 85 | ctx.strokeStyle = 'rgba(0,0,0,0)'; 86 | } 87 | 88 | function toggleClass(element, active) { 89 | if ($(element).hasClass(active)) { 90 | $(element).removeClass(active); 91 | } else { 92 | $(element).addClass(active); 93 | } 94 | } 95 | 96 | function showText(text) { 97 | var messages = { 98 | 'paused': "
Game Paused
", 99 | 'pausedAndroid': "
Game Paused
", 100 | 'pausediOS': "
Game Paused
", 101 | 'pausedOther': "
Game Paused
", 102 | 'start': "
Press enter to start
" 103 | }; 104 | 105 | if (text == 'paused') { 106 | if (settings.os == 'android') { 107 | text = 'pausedAndroid' 108 | } else if (settings.os == 'ios') { 109 | text = 'pausediOS' 110 | } else if (settings.platform == 'nonmobile') { 111 | text = 'pausedOther' 112 | } 113 | } 114 | 115 | if (text == 'gameover') { 116 | //Clay('client.share.any', {text: 'Think you can beat my score of '+ score + ' in Super Cool Game?'}) 117 | $("#gameoverscreen").fadeIn(); 118 | } 119 | $(".overlay").html(messages[text]); 120 | $(".overlay").fadeIn("1000", "swing"); 121 | 122 | } 123 | 124 | function setMainMenu() { 125 | gameState = 4; 126 | canRestart = false; 127 | setTimeout(function() { 128 | canRestart = 's'; 129 | }, 500); 130 | $('#restartBtn').hide(); 131 | if ($("#pauseBtn").replace(/^.*[\\\/]/, '') == "btn_pause.svg") { 132 | $("#pauseBtn").attr("src","./images/btn_resume.svg"); 133 | } else { 134 | $("#pauseBtn").attr("src","./images/btn_pause.svg"); 135 | } 136 | } 137 | 138 | function hideText() { 139 | $(".overlay").fadeOut(150, function() { 140 | $(".overlay").html(""); 141 | }) 142 | } 143 | 144 | function gameOverDisplay() { 145 | settings.ending_block=false; 146 | Cookies.set("visited",true); 147 | var c = document.getElementById("canvas"); 148 | c.className = "blur"; 149 | updateHighScores(); 150 | if (highscores.length === 0 ){ 151 | $("#currentHighScore").text(0); 152 | } 153 | else { 154 | $("#currentHighScore").text(highscores[0]) 155 | } 156 | $("#gameoverscreen").fadeIn(); 157 | $("#buttonCont").fadeIn(); 158 | $("#container").fadeIn(); 159 | $("#socialShare").fadeIn(); 160 | $("#restart").fadeIn(); 161 | set_score_pos(); 162 | } 163 | 164 | function updateHighScores (){ 165 | $("#cScore").text(score); 166 | $("#1place").text(highscores[0]); 167 | $("#2place").text(highscores[1]); 168 | $("#3place").text(highscores[2]); 169 | } 170 | 171 | var pausable = true; 172 | function pause(o) { 173 | if (gameState == 0 || gameState == 2 || !pausable) { 174 | return; 175 | } 176 | 177 | pausable = false; 178 | writeHighScores(); 179 | var message; 180 | if (o) { 181 | message = ''; 182 | } else { 183 | message = 'paused'; 184 | } 185 | 186 | var c = document.getElementById("canvas"); 187 | if (gameState == -1) { 188 | $('#fork-ribbon').fadeOut(300, 'linear'); 189 | $('#restartBtn').fadeOut(300, "linear"); 190 | $('#buttonCont').fadeOut(300, "linear"); 191 | if ($('#helpScreen').is(':visible')) { 192 | $('#helpScreen').fadeOut(300, "linear"); 193 | } 194 | 195 | $("#pauseBtn").attr("src", "./images/btn_pause.svg"); 196 | $('.helpText').fadeOut(300, 'linear'); 197 | $('#overlay').fadeOut(300, 'linear'); 198 | hideText(); 199 | setTimeout(function() { 200 | gameState = prevGameState; 201 | pausable =true; 202 | }, 400); 203 | } else if (gameState != -2 && gameState !== 0 && gameState !== 2) { 204 | $('#restartBtn').fadeIn(300, "linear"); 205 | $('#buttonCont').fadeIn(300, "linear"); 206 | $('.helpText').fadeIn(300, 'linear'); 207 | if (message == 'paused') { 208 | showText(message); 209 | } 210 | $('#fork-ribbon').fadeIn(300, 'linear'); 211 | $("#pauseBtn").attr("src","./images/btn_resume.svg"); 212 | $('#overlay').fadeIn(300, 'linear'); 213 | prevGameState = gameState; 214 | setTimeout(function() { 215 | pausable = true; 216 | }, 400); 217 | gameState = -1; 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /js/wavegen.js: -------------------------------------------------------------------------------- 1 | function blockDestroyed() { 2 | if (waveone.nextGen > 1350) { 3 | waveone.nextGen -= 30 * settings.creationSpeedModifier; 4 | } else if (waveone.nextGen > 600) { 5 | waveone.nextGen -= 8 * settings.creationSpeedModifier; 6 | } else { 7 | waveone.nextGen = 600; 8 | } 9 | 10 | if (waveone.difficulty < 35) { 11 | waveone.difficulty += 0.085 * settings.speedModifier; 12 | } else { 13 | waveone.difficulty = 35; 14 | } 15 | } 16 | 17 | function waveGen(hex) { 18 | this.lastGen = 0; 19 | this.last = 0; 20 | this.nextGen = 2700; 21 | this.start = 0; 22 | this.colors = colors; 23 | this.ct = 0; 24 | this.hex = hex; 25 | this.difficulty = 1; 26 | this.dt = 0; 27 | this.update = function() { 28 | this.currentFunction(); 29 | this.dt = (settings.platform == 'mobile' ? 14 : 16.6667) * MainHex.ct; 30 | this.computeDifficulty(); 31 | if ((this.dt - this.lastGen) * settings.creationSpeedModifier > this.nextGen) { 32 | if (this.nextGen > 600) { 33 | this.nextGen -= 11 * ((this.nextGen / 1300)) * settings.creationSpeedModifier; 34 | } 35 | } 36 | }; 37 | 38 | this.randomGeneration = function() { 39 | if (this.dt - this.lastGen > this.nextGen) { 40 | this.ct++; 41 | this.lastGen = this.dt; 42 | var fv = randInt(0, MainHex.sides); 43 | addNewBlock(fv, colors[randInt(0, colors.length)], 1.6 + (this.difficulty / 15) * 3); 44 | var lim = 5; 45 | if (this.ct > lim) { 46 | var nextPattern = randInt(0, 3 + 21); 47 | if (nextPattern > 15) { 48 | this.ct = 0; 49 | this.currentFunction = this.doubleGeneration; 50 | } else if (nextPattern > 10) { 51 | this.ct = 0; 52 | this.currentFunction = this.crosswiseGeneration; 53 | } else if (nextPattern > 7) { 54 | this.ct = 0; 55 | this.currentFunction = this.spiralGeneration; 56 | } else if (nextPattern > 4) { 57 | this.ct = 0; 58 | this.currentFunction = this.circleGeneration; 59 | } else if (nextPattern > 1) { 60 | this.ct = 0; 61 | this.currentFunction = this.halfCircleGeneration; 62 | } 63 | } 64 | } 65 | }; 66 | 67 | this.computeDifficulty = function() { 68 | if (this.difficulty < 35) { 69 | var increment; 70 | if (this.difficulty < 8) { 71 | increment = (this.dt - this.last) / (5166667) * settings.speedModifier; 72 | } else if (this.difficulty < 15) { 73 | increment = (this.dt - this.last) / (72333333) * settings.speedModifier; 74 | } else { 75 | increment = (this.dt - this.last) / (90000000) * settings.speedModifier; 76 | } 77 | 78 | this.difficulty += increment * (1/2); 79 | } 80 | }; 81 | 82 | this.circleGeneration = function() { 83 | if (this.dt - this.lastGen > this.nextGen + 500) { 84 | var numColors = randInt(1, 4); 85 | if (numColors == 3) { 86 | numColors = randInt(1, 4); 87 | } 88 | 89 | var colorList = []; 90 | nextLoop: for (var i = 0; i < numColors; i++) { 91 | var q = randInt(0, colors.length); 92 | for (var j in colorList) { 93 | if (colorList[j] == colors[q]) { 94 | i--; 95 | continue nextLoop; 96 | } 97 | } 98 | colorList.push(colors[q]); 99 | } 100 | 101 | for (var i = 0; i < MainHex.sides; i++) { 102 | addNewBlock(i, colorList[i % numColors], 1.5 + (this.difficulty / 15) * 3); 103 | } 104 | 105 | this.ct += 15; 106 | this.lastGen = this.dt; 107 | this.shouldChangePattern(1); 108 | } 109 | }; 110 | 111 | this.halfCircleGeneration = function() { 112 | if (this.dt - this.lastGen > (this.nextGen + 500) / 2) { 113 | var numColors = randInt(1, 3); 114 | var c = colors[randInt(0, colors.length)]; 115 | var colorList = [c, c, c]; 116 | if (numColors == 2) { 117 | colorList = [c, colors[randInt(0, colors.length)], c]; 118 | } 119 | 120 | var d = randInt(0, 6); 121 | for (var i = 0; i < 3; i++) { 122 | addNewBlock((d + i) % 6, colorList[i], 1.5 + (this.difficulty / 15) * 3); 123 | } 124 | 125 | this.ct += 8; 126 | this.lastGen = this.dt; 127 | this.shouldChangePattern(); 128 | } 129 | }; 130 | 131 | this.crosswiseGeneration = function() { 132 | if (this.dt - this.lastGen > this.nextGen) { 133 | var ri = randInt(0, colors.length); 134 | var i = randInt(0, colors.length); 135 | addNewBlock(i, colors[ri], 0.6 + (this.difficulty / 15) * 3); 136 | addNewBlock((i + 3) % MainHex.sides, colors[ri], 0.6 + (this.difficulty / 15) * 3); 137 | this.ct += 1.5; 138 | this.lastGen = this.dt; 139 | this.shouldChangePattern(); 140 | } 141 | }; 142 | 143 | this.spiralGeneration = function() { 144 | var dir = randInt(0, 2); 145 | if (this.dt - this.lastGen > this.nextGen * (2 / 3)) { 146 | if (dir) { 147 | addNewBlock(5 - (this.ct % MainHex.sides), colors[randInt(0, colors.length)], 1.5 + (this.difficulty / 15) * (3 / 2)); 148 | } else { 149 | addNewBlock(this.ct % MainHex.sides, colors[randInt(0, colors.length)], 1.5 + (this.difficulty / 15) * (3 / 2)); 150 | } 151 | this.ct += 1; 152 | this.lastGen = this.dt; 153 | this.shouldChangePattern(); 154 | } 155 | }; 156 | 157 | this.doubleGeneration = function() { 158 | if (this.dt - this.lastGen > this.nextGen) { 159 | var i = randInt(0, colors.length); 160 | addNewBlock(i, colors[randInt(0, colors.length)], 1.5 + (this.difficulty / 15) * 3); 161 | addNewBlock((i + 1) % MainHex.sides, colors[randInt(0, colors.length)], 1.5 + (this.difficulty / 15) * 3); 162 | this.ct += 2; 163 | this.lastGen = this.dt; 164 | this.shouldChangePattern(); 165 | } 166 | }; 167 | 168 | this.setRandom = function() { 169 | this.ct = 0; 170 | this.currentFunction = this.randomGeneration; 171 | }; 172 | 173 | this.shouldChangePattern = function(x) { 174 | if (x) { 175 | var q = randInt(0, 4); 176 | this.ct = 0; 177 | switch (q) { 178 | case 0: 179 | this.currentFunction = this.doubleGeneration; 180 | break; 181 | case 1: 182 | this.currentFunction = this.spiralGeneration; 183 | break; 184 | case 2: 185 | this.currentFunction = this.crosswiseGeneration; 186 | break; 187 | } 188 | } else if (this.ct > 8) { 189 | if (randInt(0, 2) === 0) { 190 | this.setRandom(); 191 | return 1; 192 | } 193 | } 194 | 195 | return 0; 196 | }; 197 | 198 | // rest of generation functions 199 | 200 | this.currentFunction = this.randomGeneration; 201 | } 202 | -------------------------------------------------------------------------------- /manifest.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hextris", 3 | "id": "hextris.io", 4 | "scope": ".", 5 | "start_url": ".", 6 | "display": "standalone", 7 | "background_color": "#ecf0f1", 8 | "description": "An addictive puzzle game inspired by Tetris.", 9 | "icons": [{ 10 | "src": "images/icons/transparent-192.png", 11 | "sizes": "192x192", 12 | "type": "image/png", 13 | "purpose": "any" 14 | }, { 15 | "src": "images/icons/transparent-512.png", 16 | "sizes": "512x512", 17 | "type": "image/png", 18 | "purpose": "any" 19 | }, { 20 | "src": "images/icons/transparent-192.webp", 21 | "sizes": "192x192", 22 | "type": "image/webp", 23 | "purpose": "any" 24 | }, { 25 | "src": "images/icons/transparent-512.webp", 26 | "sizes": "512x512", 27 | "type": "image/webp", 28 | "purpose": "any" 29 | }, { 30 | "src": "images/icons/transparent.svg", 31 | "sizes": "any", 32 | "type": "image/svg+xml", 33 | "purpose": "any" 34 | }, { 35 | "src": "images/icons/maskable-192.png", 36 | "sizes": "192x192", 37 | "type": "image/png", 38 | "purpose": "maskable" 39 | }, { 40 | "src": "images/icons/maskable-512.png", 41 | "sizes": "512x512", 42 | "type": "image/png", 43 | "purpose": "maskable" 44 | }, { 45 | "src": "images/icons/maskable-192.webp", 46 | "sizes": "192x192", 47 | "type": "image/webp", 48 | "purpose": "maskable" 49 | }, { 50 | "src": "images/icons/maskable-512.webp", 51 | "sizes": "512x512", 52 | "type": "image/webp", 53 | "purpose": "maskable" 54 | }, { 55 | "src": "images/icons/maskable.svg", 56 | "sizes": "any", 57 | "type": "image/svg+xml", 58 | "purpose": "maskable" 59 | }] 60 | } 61 | -------------------------------------------------------------------------------- /style/fa/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff') format('woff'),url('../fonts/fontawesome-webfont.ttf') format('truetype'),url('../fonts/fontawesome-webfont.svg#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"} -------------------------------------------------------------------------------- /style/fa/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fa/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /style/fa/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fa/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /style/fa/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fa/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /style/fa/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fa/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /style/fonts/Exo2-ExtraLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fonts/Exo2-ExtraLight.otf -------------------------------------------------------------------------------- /style/fonts/Exo2-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fonts/Exo2-Regular.otf -------------------------------------------------------------------------------- /style/fonts/Exo2-SemiBold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fonts/Exo2-SemiBold.otf -------------------------------------------------------------------------------- /style/fonts/Lovelo.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fonts/Lovelo.otf -------------------------------------------------------------------------------- /style/fonts/QuattrocentoSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fonts/QuattrocentoSans-Regular.ttf -------------------------------------------------------------------------------- /style/fonts/roboto.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hextris/hextris/3f4847dc8fd7dab3d1c87e6324b9159d92fbd396/style/fonts/roboto.woff -------------------------------------------------------------------------------- /style/rrssb.css: -------------------------------------------------------------------------------- 1 | .rrssb-buttons{box-sizing:border-box;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;height:36px;margin:0;padding:0;width:100%}.rrssb-buttons li{box-sizing:border-box;float:left;height:100%;line-height:13px;list-style:none;margin:0;padding:0 2px}.rrssb-buttons li.rrssb-email a{background-color:#0a88ff}.rrssb-buttons li.rrssb-email a:hover{background-color:#006ed6}.rrssb-buttons li.rrssb-facebook a{background-color:#306199}.rrssb-buttons li.rrssb-facebook a:hover{background-color:#244872}.rrssb-buttons li.rrssb-tumblr a{background-color:#32506d}.rrssb-buttons li.rrssb-tumblr a:hover{background-color:#22364a}.rrssb-buttons li.rrssb-linkedin a{background-color:#007bb6}.rrssb-buttons li.rrssb-linkedin a:hover{background-color:#005983}.rrssb-buttons li.rrssb-twitter a{background-color:#26c4f1}.rrssb-buttons li.rrssb-twitter a:hover{background-color:#0eaad6}.rrssb-buttons li.rrssb-googleplus a{background-color:#e93f2e}.rrssb-buttons li.rrssb-googleplus a:hover{background-color:#ce2616}.rrssb-buttons li.rrssb-youtube a{background-color:#df1c31}.rrssb-buttons li.rrssb-youtube a:hover{background-color:#b21627}.rrssb-buttons li.rrssb-reddit a{background-color:#8bbbe3}.rrssb-buttons li.rrssb-reddit a:hover{background-color:#62a3d9}.rrssb-buttons li.rrssb-pinterest a{background-color:#b81621}.rrssb-buttons li.rrssb-pinterest a:hover{background-color:#8a1119}.rrssb-buttons li.rrssb-pocket a{background-color:#ed4054}.rrssb-buttons li.rrssb-pocket a:hover{background-color:#e4162d}.rrssb-buttons li.rrssb-github a{background-color:#444}.rrssb-buttons li.rrssb-github a:hover{background-color:#2b2b2b}.rrssb-buttons li.rrssb-instagram a{background-color:#517fa4}.rrssb-buttons li.rrssb-instagram a:hover{background-color:#406582}.rrssb-buttons li.rrssb-delicious a{background-color:#0B79E5}.rrssb-buttons li.rrssb-delicious a:hover{background-color:#095fb4}.rrssb-buttons li.rrssb-vk a{background-color:#4d71a9}.rrssb-buttons li.rrssb-vk a:hover{background-color:#3d5a86}.rrssb-buttons li.rrssb-hackernews a{background-color:#f60}.rrssb-buttons li.rrssb-hackernews a:hover{background-color:#cc5200}.rrssb-buttons li a{background-color:#ccc;border-radius:2px;box-sizing:border-box;display:block;font-size:11px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:700;height:100%;padding:11px 7px 12px 27px;position:relative;text-align:center;text-decoration:none;text-transform:uppercase;-webkit-transition:background-color .2s ease-in-out;transition:background-color .2s ease-in-out;width:100%}.rrssb-buttons li a .rrssb-icon{display:block;left:10px;padding-top:9px;position:absolute;top:0;width:10%}.rrssb-buttons li a .rrssb-icon svg{height:17px;width:17px}.rrssb-buttons li a .rrssb-icon svg path,.rrssb-buttons li a .rrssb-icon svg polygon{fill:#fff}.rrssb-buttons li a .rrssb-text{color:#fff}.rrssb-buttons li a:active{box-shadow:inset 1px 3px 15px 0 rgba(22,0,0,.25)}.rrssb-buttons li.small a{padding:0}.rrssb-buttons li.small a .rrssb-icon{left:auto;margin:0 auto;overflow:hidden;position:relative;top:auto;width:100%}.rrssb-buttons li.small a .rrssb-text{visibility:hidden}.rrssb-buttons.large-format,.rrssb-buttons.large-format li{height:auto}.rrssb-buttons.large-format li:first-child:nth-last-child(1) a{font-size:20px;font-size:4vw}.rrssb-buttons.large-format li:first-child:nth-last-child(2) a,.rrssb-buttons.large-format li:first-child:nth-last-child(2)~li a{font-size:16px;font-size:2vw}.rrssb-buttons.large-format li:first-child:nth-last-child(3) a,.rrssb-buttons.large-format li:first-child:nth-last-child(3)~li a{font-size:14px;font-size:1.7vw}.rrssb-buttons.large-format li:first-child:nth-last-child(4) a,.rrssb-buttons.large-format li:first-child:nth-last-child(4)~li a{font-size:13px;font-size:1.4vw}.rrssb-buttons.large-format li:first-child:nth-last-child(5) a,.rrssb-buttons.large-format li:first-child:nth-last-child(5)~li a{font-size:13px;font-size:1.2vw}.rrssb-buttons.large-format li:first-child:nth-last-child(6) a,.rrssb-buttons.large-format li:first-child:nth-last-child(6)~li a{font-size:12px;font-size:1.05vw}.rrssb-buttons.large-format li:first-child:nth-last-child(7) a,.rrssb-buttons.large-format li:first-child:nth-last-child(7)~li a{font-size:11px;font-size:.9vw}.rrssb-buttons.large-format li:first-child:nth-last-child(8) a,.rrssb-buttons.large-format li:first-child:nth-last-child(8)~li a{font-size:11px;font-size:.8vw}.rrssb-buttons.large-format li:first-child:nth-last-child(9) a,.rrssb-buttons.large-format li:first-child:nth-last-child(9)~li a{font-size:11px;font-size:.7vw}.rrssb-buttons.large-format li:first-child:nth-last-child(10) a,.rrssb-buttons.large-format li:first-child:nth-last-child(10)~li a{font-size:11px;font-size:.6vw}.rrssb-buttons.large-format li:first-child:nth-last-child(11) a,.rrssb-buttons.large-format li:first-child:nth-last-child(11)~li a{font-size:11px;font-size:.5vw}.rrssb-buttons.large-format li a{-webkit-backface-visibility:hidden;backface-visibility:hidden;border-radius:.2em;padding:8.5% 0 8.5% 12%}.rrssb-buttons.large-format li a .rrssb-icon{height:100%;left:7%;padding-top:0;width:12%}.rrssb-buttons.large-format li a .rrssb-icon svg{height:100%;position:absolute;top:0;width:100%}.rrssb-buttons.large-format li a .rrssb-text{-webkit-backface-visibility:hidden;backface-visibility:hidden}.rrssb-buttons.small-format{padding-top:5px}.rrssb-buttons.small-format li{height:80%;padding:0 1px}.rrssb-buttons.small-format li a .rrssb-icon{height:100%;padding-top:0}.rrssb-buttons.small-format li a .rrssb-icon svg{height:48%;position:relative;top:6px;width:80%}.rrssb-buttons.tiny-format{height:22px;position:relative}.rrssb-buttons.tiny-format li{padding-right:7px}.rrssb-buttons.tiny-format li a{background-color:transparent;padding:0}.rrssb-buttons.tiny-format li a .rrssb-icon svg{height:70%;width:100%}.rrssb-buttons.tiny-format li a:active,.rrssb-buttons.tiny-format li a:hover{background-color:transparent}.rrssb-buttons.tiny-format li.rrssb-email a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-email a .rrssb-icon svg polygon{fill:#0a88ff}.rrssb-buttons.tiny-format li.rrssb-email a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-email a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#0054a3}.rrssb-buttons.tiny-format li.rrssb-facebook a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-facebook a .rrssb-icon svg polygon{fill:#306199}.rrssb-buttons.tiny-format li.rrssb-facebook a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-facebook a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#18304b}.rrssb-buttons.tiny-format li.rrssb-tumblr a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-tumblr a .rrssb-icon svg polygon{fill:#32506d}.rrssb-buttons.tiny-format li.rrssb-tumblr a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-tumblr a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#121d27}.rrssb-buttons.tiny-format li.rrssb-linkedin a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-linkedin a .rrssb-icon svg polygon{fill:#007bb6}.rrssb-buttons.tiny-format li.rrssb-linkedin a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-linkedin a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#003650}.rrssb-buttons.tiny-format li.rrssb-twitter a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-twitter a .rrssb-icon svg polygon{fill:#26c4f1}.rrssb-buttons.tiny-format li.rrssb-twitter a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-twitter a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#0b84a6}.rrssb-buttons.tiny-format li.rrssb-googleplus a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-googleplus a .rrssb-icon svg polygon{fill:#e93f2e}.rrssb-buttons.tiny-format li.rrssb-googleplus a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-googleplus a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#a01e11}.rrssb-buttons.tiny-format li.rrssb-youtube a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-youtube a .rrssb-icon svg polygon{fill:#df1c31}.rrssb-buttons.tiny-format li.rrssb-youtube a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-youtube a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#84111d}.rrssb-buttons.tiny-format li.rrssb-reddit a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-reddit a .rrssb-icon svg polygon{fill:#8bbbe3}.rrssb-buttons.tiny-format li.rrssb-reddit a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-reddit a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#398bcf}.rrssb-buttons.tiny-format li.rrssb-pinterest a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-pinterest a .rrssb-icon svg polygon{fill:#b81621}.rrssb-buttons.tiny-format li.rrssb-pinterest a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-pinterest a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#5d0b11}.rrssb-buttons.tiny-format li.rrssb-pocket a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-pocket a .rrssb-icon svg polygon{fill:#ed4054}.rrssb-buttons.tiny-format li.rrssb-pocket a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-pocket a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#b61124}.rrssb-buttons.tiny-format li.rrssb-github a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-github a .rrssb-icon svg polygon{fill:#444}.rrssb-buttons.tiny-format li.rrssb-github a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-github a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#111}.rrssb-buttons.tiny-format li.rrssb-instagram a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-instagram a .rrssb-icon svg polygon{fill:#517fa4}.rrssb-buttons.tiny-format li.rrssb-instagram a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-instagram a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#2f4a60}.rrssb-buttons.tiny-format li.rrssb-delicious a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-delicious a .rrssb-icon svg polygon{fill:#0B79E5}.rrssb-buttons.tiny-format li.rrssb-delicious a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-delicious a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#064684}.rrssb-buttons.tiny-format li.rrssb-vk a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-vk a .rrssb-icon svg polygon{fill:#4d71a9}.rrssb-buttons.tiny-format li.rrssb-vk a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-vk a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#2d4263}.rrssb-buttons.tiny-format li.rrssb-hackernews a .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-hackernews a .rrssb-icon svg polygon{fill:#f60}.rrssb-buttons.tiny-format li.rrssb-hackernews a .rrssb-icon:hover .rrssb-icon svg path,.rrssb-buttons.tiny-format li.rrssb-hackernews a .rrssb-icon:hover .rrssb-icon svg polygon{fill:#993d00} -------------------------------------------------------------------------------- /style/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-touch-callout:none; 3 | -webkit-user-select:none; 4 | -khtml-user-select:none; 5 | -moz-user-select:none; 6 | -ms-user-select:none; 7 | user-select:none; 8 | padding:0; 9 | margin:0; 10 | -webkit-tap-highlight-color:rgba(0,0,0,0); 11 | } 12 | #HIGHSCORE { 13 | position:absolute; 14 | left:50%; 15 | width:250px; 16 | overflow:visible; 17 | margin-left:-175px; 18 | font-family:Exo; 19 | 20 | } 21 | #container { 22 | color:#232323; 23 | position:absolute; 24 | left:50%; 25 | top:calc(50%); 26 | text-align:center; 27 | transform:translate(-50%, -50%); 28 | font-family:Exo; 29 | -webkit-transform:translate(-50%, -50%); 30 | -moz-transform:translate(-50%, -50%); 31 | -ms-transform:translate(-50%, -50%); 32 | display:none; 33 | } 34 | .tweet { 35 | font-size:2rem; 36 | color:#4099FF; 37 | } 38 | @media only screen and (min-device-width:320px) and (max-device-width:480px) { 39 | .tweet{ 40 | font-size:1rem; 41 | } 42 | } 43 | a { 44 | color:#232323; 45 | } 46 | .navbar { 47 | width:80%; 48 | margin:0 auto; 49 | padding:2.5vmin 0; 50 | text-align:center; 51 | } 52 | .navbar li { 53 | display:inline-block; 54 | text-align:center; 55 | width:calc(33% - 1.25vmin); 56 | } 57 | 58 | #title { 59 | color:#ecf0f1; 60 | font-size:6vmin; 61 | } 62 | 63 | #score { 64 | font-size:4vmin; 65 | text-align:center; 66 | width:30%; 67 | } 68 | 69 | #highscores { 70 | text-align:center; 71 | list-style:none; 72 | } 73 | 74 | .not-visible { 75 | display:none; 76 | } 77 | 78 | button { 79 | color:#ecf0f1; 80 | background-color:rgba(0,0,0,0); 81 | border:0; 82 | } 83 | 84 | button:focus { 85 | outline:0; 86 | } 87 | 88 | #openSideBar { 89 | position:fixed; 90 | margin-top:6px; 91 | width:72px; 92 | height:72px; 93 | margin-left:11px; 94 | z-index:3003; 95 | color:#232323; 96 | cursor:pointer; 97 | top:0; 98 | left:0; 99 | 100 | } 101 | 102 | 103 | #pauseBtn { 104 | display:none; 105 | position:fixed; 106 | margin-bottom:7px; 107 | width:72px; 108 | height:72px; 109 | margin-right:11px; 110 | z-index:3000; 111 | color:#232323; 112 | cursor:pointer; 113 | right:0; 114 | bottom:0; 115 | z-index:99; 116 | } 117 | 118 | #restartBtn { 119 | display:none; 120 | position:fixed; 121 | margin-bottom:7px; 122 | width:72px; 123 | height:72px; 124 | margin-left:11px; 125 | z-index:3000; 126 | color:#232323; 127 | cursor:pointer; 128 | bottom:0; 129 | z-index:99; 130 | } 131 | #startBtn { 132 | position:absolute; 133 | left:40%; 134 | top:38%; 135 | height:25%; 136 | width:25%; 137 | z-index:99999999; 138 | cursor:pointer; 139 | } 140 | 141 | #helpScreen { 142 | height:100%; 143 | width:100%; 144 | z-index:3001; 145 | position:fixed; 146 | top:0; 147 | margin:0; 148 | font-size:15px; 149 | text-align:center; 150 | display:none; 151 | color:#232323; 152 | background-color:rgba(236,240,241,1); 153 | } 154 | 155 | #colorBlindBtn { 156 | position:absolute; 157 | width:120px; 158 | height:20px; 159 | z-index:9999; 160 | left:47%; 161 | top:65%; 162 | font-size:15px; 163 | text-align:center; 164 | color:#232323; 165 | cursor:pointer; 166 | } 167 | 168 | #inst_main_body { 169 | padding:0px; 170 | font-size:1.2em; 171 | left:50%; 172 | top:50%; 173 | position: absolute; 174 | text-align:left; 175 | max-width:400px; 176 | /*margin-top:30px;*/ 177 | transform:translate(-50%, -50%); 178 | -webkit-transform:translate(-50%, -50%); 179 | -moz-transform:translate(-50%, -50%); 180 | -ms-transform:translate(-50%, -50%); 181 | } 182 | 183 | #inst_main_body > a { 184 | font-weight:bold; 185 | } 186 | 187 | #inst_main_body > hr { 188 | width:100%; 189 | color:#232323; 190 | background-color:#232323; 191 | height:1px; 192 | border:0; 193 | } 194 | 195 | #inst_main_body > p { 196 | margin-bottom:15px; 197 | } 198 | 199 | #instructions_head { 200 | text-align:center; 201 | font-size:1.5em; 202 | padding-bottom:4px; 203 | } 204 | 205 | 206 | #highScoreInGameTextHeader { 207 | color: #bdc3c7; 208 | width:100%; 209 | } 210 | 211 | #highScoreInGameText { 212 | position: absolute; 213 | top:10px; 214 | text-align: center; 215 | width:200px; 216 | left:50%; 217 | margin-left:-100px; 218 | } 219 | 220 | #currentHighScore { 221 | color: #2c3e50; 222 | width:100%; 223 | margin-top: -5px; 224 | font-size:2em; 225 | } 226 | 227 | @media only screen and (max-device-width:480px) { 228 | #helpScreen { 229 | position:fixed; 230 | top:2px; 231 | padding-top:20px; 232 | margin:0; 233 | width:100%; 234 | height:100%; 235 | font-size:13px; 236 | text-align:center; 237 | } 238 | #inst_main_body { 239 | width:calc(100% - 70px); 240 | transform:translate(-50%, -50%); 241 | -webkit-transform:translate(-50%, -50%); 242 | -moz-transform:translate(-50%, -50%); 243 | -ms-transform:translate(-50%, -50%); 244 | } 245 | #instructions_head { 246 | padding-left:0%; 247 | } 248 | #openSideBar{ 249 | width:60px; 250 | height:60px; 251 | } 252 | #pauseBtn { 253 | width:60px; 254 | height:60px; 255 | } 256 | #restartBtn { 257 | width:60px; 258 | height:60px; 259 | } 260 | } 261 | 262 | .overlay { 263 | position:absolute; 264 | height:20%; 265 | width:100%; 266 | left:50%; 267 | top:50%; 268 | margin-left:-50%; 269 | margin-top:-10%; 270 | z-index:3000; 271 | color:#232323; 272 | text-align:center; 273 | } 274 | 275 | .helpText { 276 | z-index:3001; 277 | } 278 | 279 | .centeredHeader { 280 | font-size:5vw; 281 | text-align:center; 282 | line-height:4rem; 283 | } 284 | 285 | .centeredSubHeader { 286 | font-size:2.2rem; 287 | line-height:1em; 288 | text-align:center; 289 | } 290 | 291 | .centeredSubSubHeader { 292 | font-size:1.4rem; 293 | text-align:center; 294 | } 295 | 296 | #buttonCont { 297 | position:absolute; 298 | left:50%; 299 | width:310px; 300 | margin-left:-8px; 301 | transform:translate(-50%, 0%); 302 | -webkit-transform:translate(-50%, 0%); 303 | -moz-transform:translate(-50%, 0%); 304 | -ms-transform:translate(-50%, 0%); 305 | } 306 | 307 | @media only screen and (orientation:landscape) { 308 | #buttonCont { 309 | bottom:calc(50vh - 19vh - 36px); 310 | } 311 | #container { 312 | top:calc(50vh - 11vh); 313 | } 314 | } 315 | 316 | @media only screen and (orientation:portrait) { 317 | #buttonCont { 318 | bottom:calc(50vh - 19vw - 36px); 319 | } 320 | #container { 321 | top:calc(50vh - 11vw); 322 | } 323 | } 324 | 325 | @media only screen and (min-device-width:320px) and (max-device-width:600px) { 326 | .centeredHeader { 327 | font-size:2rem; 328 | text-align:center; 329 | line-height:0.6rem; 330 | } 331 | 332 | .centeredSubHeader { 333 | font-size:1rem; 334 | text-align:center; 335 | } 336 | 337 | .overlay { 338 | margin-top:-20%; 339 | } 340 | 341 | #buttonCont { 342 | width:280px; 343 | } 344 | 345 | @media only screen and (orientation:landscape) { 346 | #buttonCont { 347 | bottom:119px; 348 | } 349 | } 350 | 351 | @media only screen and (orientation:portrait) { 352 | #buttonCont { 353 | bottom:119px; 354 | } 355 | } 356 | } 357 | .blur { 358 | opacity:0.1; 359 | } 360 | 361 | * { 362 | padding:0; 363 | margin:0; 364 | } 365 | 366 | body { 367 | color:#ecf0f1; 368 | font-family:'Exo', sans-serif; 369 | background-color:#ecf0f1; 370 | } 371 | 372 | #clickToExit { 373 | cursor:pointer; 374 | } 375 | 376 | #canvas { 377 | transition:all 0.5s ease; 378 | position:absolute; 379 | left:0; 380 | right:0; 381 | height:100%; 382 | width:100%; 383 | background-color:#ecf0f1; 384 | z-index:0; 385 | } 386 | #title { 387 | z-index:99; 388 | margin-top:20px; 389 | color:#2c3e50; 390 | } 391 | 392 | #gameoverscreen { 393 | /*display:none;*/ 394 | } 395 | 396 | #restart{ 397 | display:none; 398 | cursor:pointer !important; 399 | margin:0; 400 | padding:0; 401 | bottom:15px; 402 | position:absolute; 403 | left:calc(50% - 124px); 404 | transform:translate(-50%, 0%); 405 | -webkit-transform:translate(-50%, 0%); 406 | -moz-transform:translate(-50%, 0%); 407 | -ms-transform:translate(-50%, 0%); 408 | margin-bottom:-3.5px; 409 | } 410 | 411 | #socialShare{ 412 | display:none; 413 | margin:0; 414 | padding:0; 415 | bottom:0; 416 | margin-bottom: 6.5px; 417 | position:absolute; 418 | left:calc(50% + 30px); 419 | transform:translate(-50%, 0%); 420 | -webkit-transform:translate(-50%, 0%); 421 | -moz-transform:translate(-50%, 0%); 422 | -ms-transform:translate(-50%, 0%); 423 | padding-bottom: 2px; 424 | } 425 | 426 | .unselectable { 427 | -webkit-touch-callout:none; 428 | -webkit-user-select:none; 429 | -khtml-user-select:none; 430 | -moz-user-select:none; 431 | -ms-user-select:none; 432 | user-select:none; 433 | } 434 | #afterhr { 435 | margin:0; 436 | padding:0; 437 | margin-bottom:-10px; 438 | padding-bottom:-10px; 439 | } 440 | body { 441 | overflow:hidden; 442 | } 443 | #gameoverscreen { 444 | padding:8px; 445 | } 446 | @font-face { 447 | font-family:Exo; 448 | font-weight:light; 449 | src:url("./fonts/Exo2-ExtraLight.otf") format("opentype"); 450 | } 451 | 452 | @font-face { 453 | font-family:Exo; 454 | src:url("./fonts/Exo2-Regular.otf") format("opentype"); 455 | } 456 | 457 | @font-face { 458 | font-family:Exo; 459 | font-weight:bold; 460 | src:url("./fonts/Exo2-SemiBold.otf") format("opentype"); 461 | } 462 | 463 | .GOTitle { 464 | font-weight:bold; 465 | font-size:24.2000px; 466 | } 467 | 468 | .scoreNum { 469 | font-weight:normal ! important; 470 | } 471 | 472 | #cScore { 473 | font-size:60.5000px; 474 | font-weight:light; 475 | margin-bottom:5px; 476 | margin-top:-10px; 477 | } 478 | 479 | #highScoresTitle { 480 | margin-bottom:2px; 481 | } 482 | 483 | .score { 484 | font-weight:light; 485 | line-height:18px; 486 | } 487 | 488 | 489 | 490 | 491 | #bottomContainer { 492 | position:absolute; 493 | width:100%; 494 | bottom:0px; 495 | } 496 | 497 | #androidBadge { 498 | position:absolute; 499 | height:41px; 500 | margin-top:5px; 501 | left:calc(50% - 66px); 502 | transform:translate(calc(-50% - 4px), -1px); 503 | -webkit-transform:translate(calc(-50% - 4px), -1px); 504 | -moz-transform:translate(calc(-50% - 4px), -1px); 505 | -ms-transform:translate(calc(-50% - 4px), -1px); 506 | } 507 | 508 | #iOSBadge { 509 | margin-top:5px; 510 | position:absolute; 511 | left:calc(50% + 65px); 512 | transform:translate(calc(-50% - 4px), 0%); 513 | -webkit-transform:translate(calc(-50% - 4px), 0%); 514 | -moz-transform:translate(calc(-50% - 4px), 0%); 515 | -ms-transform:translate(calc(-50% - 4px), 0%); 516 | } 517 | 518 | #authors { 519 | position:absolute; 520 | width:200px; 521 | bottom:0px; 522 | left:50%; 523 | transform:translate(-50%, 0%); 524 | -webkit-transform:translate(-50%, 0%); 525 | -moz-transform:translate(-50%, 0%); 526 | -ms-transform:translate(-50%, 0%); 527 | } 528 | -------------------------------------------------------------------------------- /vendor/hammer.min.js: -------------------------------------------------------------------------------- 1 | /*! Hammer.JS - v1.1.2 - 2014-04-25 2 | * http://eightmedia.github.io/hammer.js 3 | * 4 | * Copyright (c) 2014 Jorik Tangelder ; 5 | * Licensed under the MIT license */ 6 | 7 | 8 | !function(a,b){"use strict";function c(){d.READY||(s.determineEventTypes(),r.each(d.gestures,function(a){u.register(a)}),s.onTouch(d.DOCUMENT,n,u.detect),s.onTouch(d.DOCUMENT,o,u.detect),d.READY=!0)}var d=function v(a,b){return new v.Instance(a,b||{})};d.VERSION="1.1.2",d.defaults={behavior:{userSelect:"none",touchAction:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},d.DOCUMENT=document,d.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,d.HAS_TOUCHEVENTS="ontouchstart"in a,d.IS_MOBILE=/mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent),d.NO_MOUSEEVENTS=d.HAS_TOUCHEVENTS&&d.IS_MOBILE||d.HAS_POINTEREVENTS,d.CALCULATE_INTERVAL=25;var e={},f=d.DIRECTION_DOWN="down",g=d.DIRECTION_LEFT="left",h=d.DIRECTION_UP="up",i=d.DIRECTION_RIGHT="right",j=d.POINTER_MOUSE="mouse",k=d.POINTER_TOUCH="touch",l=d.POINTER_PEN="pen",m=d.EVENT_START="start",n=d.EVENT_MOVE="move",o=d.EVENT_END="end",p=d.EVENT_RELEASE="release",q=d.EVENT_TOUCH="touch";d.READY=!1,d.plugins=d.plugins||{},d.gestures=d.gestures||{};var r=d.utils={extend:function(a,c,d){for(var e in c)!c.hasOwnProperty(e)||a[e]!==b&&d||(a[e]=c[e]);return a},on:function(a,b,c){a.addEventListener(b,c,!1)},off:function(a,b,c){a.removeEventListener(b,c,!1)},each:function(a,c,d){var e,f;if("forEach"in a)a.forEach(c,d);else if(a.length!==b){for(e=0,f=a.length;f>e;e++)if(c.call(d,a[e],e,a)===!1)return}else for(e in a)if(a.hasOwnProperty(e)&&c.call(d,a[e],e,a)===!1)return},inStr:function(a,b){return a.indexOf(b)>-1},inArray:function(a,b){if(a.indexOf){var c=a.indexOf(b);return-1===c?!1:c}for(var d=0,e=a.length;e>d;d++)if(a[d]===b)return d;return!1},toArray:function(a){return Array.prototype.slice.call(a,0)},hasParent:function(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1},getCenter:function(a){var b=[],c=[],d=[],e=[],f=Math.min,g=Math.max;return 1===a.length?{pageX:a[0].pageX,pageY:a[0].pageY,clientX:a[0].clientX,clientY:a[0].clientY}:(r.each(a,function(a){b.push(a.pageX),c.push(a.pageY),d.push(a.clientX),e.push(a.clientY)}),{pageX:(f.apply(Math,b)+g.apply(Math,b))/2,pageY:(f.apply(Math,c)+g.apply(Math,c))/2,clientX:(f.apply(Math,d)+g.apply(Math,d))/2,clientY:(f.apply(Math,e)+g.apply(Math,e))/2})},getVelocity:function(a,b,c){return{x:Math.abs(b/a)||0,y:Math.abs(c/a)||0}},getAngle:function(a,b){var c=b.clientX-a.clientX,d=b.clientY-a.clientY;return 180*Math.atan2(d,c)/Math.PI},getDirection:function(a,b){var c=Math.abs(a.clientX-b.clientX),d=Math.abs(a.clientY-b.clientY);return c>=d?a.clientX-b.clientX>0?g:i:a.clientY-b.clientY>0?h:f},getDistance:function(a,b){var c=b.clientX-a.clientX,d=b.clientY-a.clientY;return Math.sqrt(c*c+d*d)},getScale:function(a,b){return a.length>=2&&b.length>=2?this.getDistance(b[0],b[1])/this.getDistance(a[0],a[1]):1},getRotation:function(a,b){return a.length>=2&&b.length>=2?this.getAngle(b[1],b[0])-this.getAngle(a[1],a[0]):0},isVertical:function(a){return a==h||a==f},setPrefixedCss:function(a,b,c,d){var e=["","Webkit","Moz","O","ms"];b=r.toCamelCase(b);for(var f=0;f0&&this.started&&(g=n),this.started=!0;var j=this.collectEventData(c,g,e,a);return b!=o&&d.call(u,j),h&&(j.changedLength=i,j.eventType=h,d.call(u,j),j.eventType=g,delete j.changedLength),g==o&&(d.call(u,j),this.started=!1),g},determineEventTypes:function(){var b;return b=d.HAS_POINTEREVENTS?a.PointerEvent?["pointerdown","pointermove","pointerup pointercancel lostpointercapture"]:["MSPointerDown","MSPointerMove","MSPointerUp MSPointerCancel MSLostPointerCapture"]:d.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],e[m]=b[0],e[n]=b[1],e[o]=b[2],e},getTouchList:function(a,b){if(d.HAS_POINTEREVENTS)return t.getTouchList();if(a.touches){if(b==n)return a.touches;var c=[],e=[].concat(r.toArray(a.touches),r.toArray(a.changedTouches)),f=[];return r.each(e,function(a){r.inArray(c,a.identifier)===!1&&f.push(a),c.push(a.identifier)}),f}return a.identifier=1,[a]},collectEventData:function(a,b,c,d){var e=k;return r.inStr(d.type,"mouse")||t.matchType(j,d)?e=j:t.matchType(l,d)&&(e=l),{center:r.getCenter(c),timeStamp:Date.now(),target:d.target,touches:c,eventType:b,pointerType:e,srcEvent:d,preventDefault:function(){var a=this.srcEvent;a.preventManipulation&&a.preventManipulation(),a.preventDefault&&a.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return u.stopDetect()}}}},t=d.PointerEvent={pointers:{},getTouchList:function(){var a=[];return r.each(this.pointers,function(b){a.push(b)}),a},updatePointer:function(a,b){a==o||a!=o&&1!==b.buttons?delete this.pointers[b.pointerId]:(b.identifier=b.pointerId,this.pointers[b.pointerId]=b)},matchType:function(a,b){if(!b.pointerType)return!1;var c=b.pointerType,d={};return d[j]=c===(b.MSPOINTER_TYPE_MOUSE||j),d[k]=c===(b.MSPOINTER_TYPE_TOUCH||k),d[l]=c===(b.MSPOINTER_TYPE_PEN||l),d[a]},reset:function(){this.pointers={}}},u=d.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(a,b){this.current||(this.stopped=!1,this.current={inst:a,startEvent:r.extend({},b),lastEvent:!1,lastCalcEvent:!1,futureCalcEvent:!1,lastCalcData:{},name:""},this.detect(b))},detect:function(a){if(this.current&&!this.stopped){a=this.extendEventData(a);var b=this.current.inst,c=b.options;return r.each(this.gestures,function(d){return!this.stopped&&b.enabled&&c[d.name]&&d.handler.call(d,a,b)===!1?(this.stopDetect(),!1):void 0},this),this.current&&(this.current.lastEvent=a),a.eventType==o&&this.stopDetect(),a}},stopDetect:function(){this.previous=r.extend({},this.current),this.current=null,this.stopped=!0},getCalculatedData:function(a,b,c,e,f){var g=this.current,h=!1,i=g.lastCalcEvent,j=g.lastCalcData;i&&a.timeStamp-i.timeStamp>d.CALCULATE_INTERVAL&&(b=i.center,c=a.timeStamp-i.timeStamp,e=a.center.clientX-i.center.clientX,f=a.center.clientY-i.center.clientY,h=!0),(a.eventType==q||a.eventType==p)&&(g.futureCalcEvent=a),(!g.lastCalcEvent||h)&&(j.velocity=r.getVelocity(c,e,f),j.angle=r.getAngle(b,a.center),j.direction=r.getDirection(b,a.center),g.lastCalcEvent=g.futureCalcEvent||a,g.futureCalcEvent=a),a.velocityX=j.velocity.x,a.velocityY=j.velocity.y,a.interimAngle=j.angle,a.interimDirection=j.direction},extendEventData:function(a){var b=this.current,c=b.startEvent,d=b.lastEvent||c;(a.eventType==q||a.eventType==p)&&(c.touches=[],r.each(a.touches,function(a){c.touches.push({clientX:a.clientX,clientY:a.clientY})}));var e=a.timeStamp-c.timeStamp,f=a.center.clientX-c.center.clientX,g=a.center.clientY-c.center.clientY;return this.getCalculatedData(a,d.center,e,f,g),r.extend(a,{startEvent:c,deltaTime:e,deltaX:f,deltaY:g,distance:r.getDistance(c.center,a.center),angle:r.getAngle(c.center,a.center),direction:r.getDirection(c.center,a.center),scale:r.getScale(c.touches,a.touches),rotation:r.getRotation(c.touches,a.touches)}),a},register:function(a){var c=a.defaults||{};return c[a.name]===b&&(c[a.name]=!0),r.extend(d.defaults,c,!0),a.index=a.index||1e3,this.gestures.push(a),this.gestures.sort(function(a,b){return a.indexb.index?1:0}),this.gestures}};d.Instance=function(a,b){var e=this;c(),this.element=a,this.enabled=!0,r.each(b,function(a,c){delete b[c],b[r.toCamelCase(c)]=a}),this.options=r.extend(r.extend({},d.defaults),b||{}),this.options.behavior&&r.toggleBehavior(this.element,this.options.behavior,!0),this.eventStartHandler=s.onTouch(a,m,function(a){e.enabled&&a.eventType==m?u.startDetect(e,a):a.eventType==q&&u.detect(a)}),this.eventHandlers=[]},d.Instance.prototype={on:function(a,b){var c=this;return s.on(c.element,a,b,function(a){c.eventHandlers.push({gesture:a,handler:b})}),c},off:function(a,b){var c=this;return s.off(c.element,a,b,function(a){var d=r.inArray({gesture:a,handler:b});d!==!1&&c.eventHandlers.splice(d,1)}),c},trigger:function(a,b){b||(b={});var c=d.DOCUMENT.createEvent("Event");c.initEvent(a,!0,!0),c.gesture=b;var e=this.element;return r.hasParent(b.target,e)&&(e=b.target),e.dispatchEvent(c),this},enable:function(a){return this.enabled=a,this},dispose:function(){var a,b;for(r.toggleBehavior(this.element,this.options.behavior,!1),a=-1;b=this.eventHandlers[++a];)r.off(this.element,b.gesture,b.handler);return this.eventHandlers=[],s.off(this.element,e[m],this.eventStartHandler),null}},function(a){function b(b,d){var e=u.current;if(!(d.options.dragMaxTouches>0&&b.touches.length>d.options.dragMaxTouches))switch(b.eventType){case m:c=!1;break;case n:if(b.distance0)){var k=Math.abs(d.options.dragMinDistance/b.distance);j.pageX+=b.deltaX*k,j.pageY+=b.deltaY*k,j.clientX+=b.deltaX*k,j.clientY+=b.deltaY*k,b=u.extendEventData(b)}(e.lastEvent.dragLockToAxis||d.options.dragLockToAxis&&d.options.dragLockMinDistance<=b.distance)&&(b.dragLockToAxis=!0);var l=e.lastEvent.direction;b.dragLockToAxis&&l!==b.direction&&(b.direction=r.isVertical(l)?b.deltaY<0?h:f:b.deltaX<0?g:i),c||(d.trigger(a+"start",b),c=!0),d.trigger(a,b),d.trigger(a+b.direction,b);var q=r.isVertical(b.direction);(d.options.dragBlockVertical&&q||d.options.dragBlockHorizontal&&!q)&&b.preventDefault();break;case p:c&&b.changedLength<=d.options.dragMaxTouches&&(d.trigger(a+"end",b),c=!1);break;case o:c=!1}}var c=!1;d.gestures.Drag={name:a,index:50,handler:b,defaults:{dragMinDistance:10,dragDistanceCorrection:!0,dragMaxTouches:1,dragBlockHorizontal:!1,dragBlockVertical:!1,dragLockToAxis:!1,dragLockMinDistance:25}}}("drag"),d.gestures.Gesture={name:"gesture",index:1337,handler:function(a,b){b.trigger(this.name,a)}},function(a){function b(b,d){var e=d.options,f=u.current;switch(b.eventType){case m:clearTimeout(c),f.name=a,c=setTimeout(function(){f&&f.name==a&&d.trigger(a,b)},e.holdTimeout);break;case n:b.distance>e.holdThreshold&&clearTimeout(c);break;case p:clearTimeout(c)}}var c;d.gestures.Hold={name:a,index:10,defaults:{holdTimeout:500,holdThreshold:2},handler:b}}("hold"),d.gestures.Release={name:"release",index:1/0,handler:function(a,b){a.eventType==p&&b.trigger(this.name,a)}},d.gestures.Swipe={name:"swipe",index:40,defaults:{swipeMinTouches:1,swipeMaxTouches:1,swipeVelocityX:.6,swipeVelocityY:.6},handler:function(a,b){if(a.eventType==p){var c=a.touches.length,d=b.options;if(cd.swipeMaxTouches)return;(a.velocityX>d.swipeVelocityX||a.velocityY>d.swipeVelocityY)&&(b.trigger(this.name,a),b.trigger(this.name+a.direction,a))}}},function(a){function b(b,d){var e,f,g=d.options,h=u.current,i=u.previous;switch(b.eventType){case m:c=!1;break;case n:c=c||b.distance>g.tapMaxDistance;break;case o:"touchcancel"!=b.srcEvent.type&&b.deltaTimed.options.transformMinRotation&&d.trigger("rotate",b),e>d.options.transformMinScale&&(d.trigger("pinch",b),d.trigger("pinch"+(b.scale<1?"in":"out"),b));break;case p:c&&b.changedLength<2&&(d.trigger(a+"end",b),c=!1)}}var c=!1;d.gestures.Transform={name:a,index:45,defaults:{transformMinScale:.01,transformMinRotation:1},handler:b}}("transform"),"function"==typeof define&&define.amd?define(function(){return d}):"undefined"!=typeof module&&module.exports?module.exports=d:a.Hammer=d}(window); 9 | -------------------------------------------------------------------------------- /vendor/js.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * JavaScript Cookie v2.0.0-pre 3 | * https://github.com/js-cookie/js-cookie 4 | * 5 | * Copyright 2006, 2015 Klaus Hartl 6 | * Released under the MIT license 7 | */ 8 | (function (factory) { 9 | if (typeof define === 'function' && define.amd) { 10 | define(factory); 11 | } else if (typeof exports === 'object') { 12 | module.exports = factory(); 13 | } else { 14 | var _OldCookies = window.Cookies; 15 | var api = window.Cookies = factory(window.jQuery); 16 | api.noConflict = function () { 17 | window.Cookies = _OldCookies; 18 | return api; 19 | }; 20 | } 21 | }(function () { 22 | function extend () { 23 | var i = 0; 24 | var result = {}; 25 | for (; i < arguments.length; i++) { 26 | var attributes = arguments[ i ]; 27 | for (var key in attributes) { 28 | result[key] = attributes[key]; 29 | } 30 | } 31 | return result; 32 | } 33 | 34 | function init (converter) { 35 | function api (key, value, attributes) { 36 | var result; 37 | 38 | // Write 39 | 40 | if (arguments.length > 1) { 41 | attributes = extend({ 42 | path: '/' 43 | }, api.defaults, attributes); 44 | 45 | if (typeof attributes.expires === 'number') { 46 | var expires = new Date(); 47 | expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); 48 | attributes.expires = expires; 49 | } 50 | 51 | try { 52 | result = JSON.stringify(value); 53 | if (/^[\{\[]/.test(result)) { 54 | value = result; 55 | } 56 | } catch (e) {} 57 | 58 | value = encodeURIComponent(String(value)); 59 | value = value.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); 60 | 61 | key = encodeURIComponent(String(key)); 62 | key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); 63 | key = key.replace(/[\(\)]/g, escape); 64 | 65 | return (document.cookie = [ 66 | key, '=', value, 67 | attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE 68 | attributes.path && '; path=' + attributes.path, 69 | attributes.domain && '; domain=' + attributes.domain, 70 | attributes.secure && '; secure' 71 | ].join('')); 72 | } 73 | 74 | // Read 75 | 76 | if (!key) { 77 | result = {}; 78 | } 79 | 80 | // To prevent the for loop in the first place assign an empty array 81 | // in case there are no cookies at all. Also prevents odd result when 82 | // calling "get()" 83 | var cookies = document.cookie ? document.cookie.split('; ') : []; 84 | var rdecode = /(%[0-9A-Z]{2})+/g; 85 | var i = 0; 86 | 87 | for (; i < cookies.length; i++) { 88 | var parts = cookies[i].split('='); 89 | var name = parts[0].replace(rdecode, decodeURIComponent); 90 | var cookie = parts.slice(1).join('='); 91 | 92 | if (cookie.charAt(0) === '"') { 93 | cookie = cookie.slice(1, -1); 94 | } 95 | 96 | cookie = converter && converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent); 97 | 98 | if (this.json) { 99 | try { 100 | cookie = JSON.parse(cookie); 101 | } catch (e) {} 102 | } 103 | 104 | if (key === name) { 105 | result = cookie; 106 | break; 107 | } 108 | 109 | if (!key) { 110 | result[name] = cookie; 111 | } 112 | } 113 | 114 | return result; 115 | } 116 | 117 | api.get = api.set = api; 118 | api.getJSON = function () { 119 | return api.apply({ 120 | json: true 121 | }, [].slice.call(arguments)); 122 | }; 123 | api.defaults = {}; 124 | 125 | api.remove = function (key, attributes) { 126 | api(key, '', extend(attributes, { 127 | expires: -1 128 | })); 129 | }; 130 | 131 | api.withConverter = init; 132 | 133 | return api; 134 | } 135 | 136 | return init(); 137 | })); 138 | -------------------------------------------------------------------------------- /vendor/jsonfn.min.js: -------------------------------------------------------------------------------- 1 | "use strict";(function(exports){exports.stringify=function(e){return JSON.stringify(e,function(e,t){if(t instanceof Function||typeof t=="function"){return t.toString()}if(t instanceof RegExp){return"_PxEgEr_"+t}return t})};exports.parse=function(str,date2obj){var iso8061=date2obj?/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/:false;return JSON.parse(str,function(key,value){var prefix;if(typeof value!="string"){return value}if(value.length<8){return value}prefix=value.substring(0,8);if(iso8061&&value.match(iso8061)){return new Date(value)}if(prefix==="function"){return eval("("+value+")")}if(prefix==="_PxEgEr_"){return eval(value.slice(8))}return value})};exports.clone=function(e,t){return exports.parse(exports.stringify(e),t)}})(typeof exports==="undefined"?window.JSONfn={}:exports) -------------------------------------------------------------------------------- /vendor/keypress.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Keypress version 1.0.8 (c) 2013 David Mauro. 3 | Licensed under the Apache License, Version 2.0 4 | http://www.apache.org/licenses/LICENSE-2.0 5 | */ 6 | (function(){var w,x,j,R,S,T,U,y,z,A,V,H,I,B,m,W,X,Y,Z,J,$,aa,ba,ca,da,K,ea,r,s,g,L,t,fa,M,u,N,C,v,O,D,h,P,E,p,F,Q,G,ga,i=[].indexOf||function(a){for(var c=0,b=this.length;ce;b=0<=e?++d:--d)if(a[b]!==c[b])return!1;return!0};ba=function(a,c){var b,d,e;d=0;for(e=a.length;di.call(c,b))return!1;return!0};ca=function(a,c){var b,d,e,f;e=d=0;for(f=a.length;e=d)d=b;else return!1;return!0};v=function(a, 8 | c){if((c||keypress.suppress_event_defaults)&&!keypress.force_event_defaults)if(a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation)return a.stopPropagation()};T=function(a){if(a.prevent_repeat)return!1;if("function"===typeof a.on_keydown)return!0};L=function(a){var c,b,d,e;e=a.keys;b=0;for(d=e.length;bi.call(a,"cmd")?!1:!0};X=function(a){var c,b;c=[];b=B(g,function(b){return b!==a});b.push(a);fa(b,function(a){if(y(a.keys))return c.push(a)});W(b,function(a){if(!(0<=i.call(c,a))&&!a.is_solitary&& 10 | y(a.keys))return c.push(a)});return c};Z=function(a){var c,b,d,e;b=[];d=0;for(e=h.length;dk;e=0<=k?++g:--g)if((c=j[e])&&c.is_exclusive&&a.is_exclusive){c=c.keys;if(!q){h=0;for(l=c.length;hi.call(a.keys,b)){q=!1;break}}if(f&&!q){o=a.keys;h=0;for(l=o.length;hi.call(c,b)){f=!0;break}}q&&(d?E(j.splice(e,1)):(E(j.splice(e,1,a)),d=!0),f=!1)}}f&&j.unshift(a);return q||f};P=function(a){var c,b,d,e;b=d=0;for(e=j.length;0<=e?de;b=0<=e?++d:--d)if(c=j[b],c===a){E(j.splice(b,1));break}};E=function(a){if(a)return a.count=null,a.keyup_fired=null};R=function(a,c){var b,d,e,f;p.push(a);d=Y();if(d.length){e=0;for(f=d.length;e=l;c=1<=l?++g:--g)if(e=p.slice(-c),a.is_sequence){if(0>i.call(a.keys,"shift")&&(e=B(e,function(a){return"shift"!==a}),!e.length))continue;c=n=0;for(k=e.length;0<=k?nk;c=0<=k?++n:--n)if(a.keys[c]===e[c])b=!0;else{b=!1;break}b&&d.push(a)}}return d};J=function(a){var c,b,d,e,f,g,j,m,l,k,o;g=0;for(l=h.length;g=k;b=1<= 13 | k?++j:--j)if(f=B(p,function(a){return 0<=i.call(c.keys,"shift")?!0:"shift"!==a}).slice(-b),c.keys.length===f.length){b=m=0;for(o=f.length;0<=o?mo;b=0<=o?++m:--m)if(e=f[b],!(0>i.call(c.keys,"shift")&&"shift"===e)&&!("shift"===a&&0>i.call(c.keys,"shift")))if(c.keys[b]===e)d=!0;else{d=!1;break}}if(d)return c}return!1};I=function(a,c){var b;if(!c.shiftKey)return!1;b=s[a];return null!=b?b:!1};$=function(a,c,b){if(0>i.call(a.keys,c))return!1;v(b,a&&a.prevent_default);if(0<=i.call(g,c)&&!T(a))return!1; 14 | c=S(a,c);a.keyup_fired=!1;a.is_counting&&"function"===typeof a.on_keydown&&(a.count+=1);if(c)return m("keydown",a,b)};da=function(a,c){var b,d,e,f;(d=I(a,c))&&(a=d);R(a,c);(d=J(a))&&m("keydown",d,c);for(b in u)d=u[b],c[d]&&(b===a||0<=i.call(g,b)||g.push(b));for(b in u)if(d=u[b],b!==a&&0<=i.call(g,b)&&!c[d]){d=e=0;for(f=g.length;0<=f?ef;d=0<=f?++e:--e)g[d]===b&&g.splice(d,1)}d=X(a);e=0;for(f=d.length;e 15 | i.call(g,a)&&g.push(a)};aa=function(a,c,b){var d,e;e=L(a);if(!a.keyup_fired&&(d=g.slice(),d.push(b),!a.is_solitary||A(d,a.keys)))m("keyup",a,c),a.is_counting&&("function"===typeof a.on_keyup&&"function"!==typeof a.on_keydown)&&(a.count+=1);e||(m("release",a,c),P(a))};K=function(a,c){var b,d,e,f,h,n;d=a;(e=I(a,c))&&(a=e);e=s[d];c.shiftKey?e&&0<=i.call(g,e)||(a=d):d&&0<=i.call(g,d)||(a=e);(f=J(a))&&m("keyup",f,c);if(0>i.call(g,a))return!1;f=h=0;for(n=g.length;0<=n?hn;f=0<=n?++h:--h)if((b=g[f])=== 16 | a||b===e||b===d){g.splice(f,1);break}d=j.length;e=[];f=0;for(h=j.length;fd;c=0<=d?++b:--b)if(a===h[c]){h.splice(c,1);break}else e.push(void 0);return e};ga=function(a){var c, 17 | b,d,e,f;a.keys.length||t("You're trying to bind a combo with no keys.");b=e=0;for(f=a.keys.length;0<=f?ef;b=0<=f?++e:--e)d=a.keys[b],(c=ea[d])&&(d=a.keys[b]=c),"meta"===d&&a.keys.splice(b,1,M),"cmd"===d&&t('Warning: use the "meta" key rather than "cmd" for Windows compatibility');f=a.keys;c=0;for(e=f.length;ci.call(G,d))return t('Do not recognize the key "'+d+'"'),!1;if(0<=i.call(a.keys,"meta")||0<=i.call(a.keys,"cmd")){c=a.keys.slice();e=0;for(f=N.length;e",",":"<","'":'"',";":":","[":"{","]":"}","\\":"|","`":"~","=":"+","-":"_",1:"!",2:"@",3:"#",4:"$",5:"%",6:"^",7:"&", 22 | 8:"*",9:"(","0":")"};r={"0":"\\",8:"backspace",9:"tab",12:"num",13:"enter",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"caps",27:"escape",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",44:"print",45:"insert",46:"delete",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x", 23 | 89:"y",90:"z",91:"cmd",92:"cmd",93:"cmd",96:"num_0",97:"num_1",98:"num_2",99:"num_3",100:"num_4",101:"num_5",102:"num_6",103:"num_7",104:"num_8",105:"num_9",106:"num_multiply",107:"num_add",108:"num_enter",109:"num_subtract",110:"num_decimal",111:"num_divide",124:"print",144:"num",145:"scroll",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",223:"`",224:"cmd",57392:"ctrl",63289:"num"};for(x in r)w=r[x],G.push(w);for(x in s)w=s[x],G.push(w);-1!==navigator.userAgent.indexOf("Mac OS X")&& 24 | (M="cmd");-1!==navigator.userAgent.indexOf("Opera")&&(r["17"]="cmd");O=function(a){return(document.attachEvent?"complete"===document.readyState:"loading"!==document.readyState)?a():setTimeout(function(){return O(a)},9)};O(function(){var a;a=function(a,b,d){if(a.addEventListener)return a.addEventListener(b,d);if(a.attachEvent)return a.attachEvent("on"+b,d)};a(document.body,"keydown",function(a){a=a||window.event;D(a,!0);return U(a)});a(document.body,"keyup",function(a){a=a||window.event;return D(a, 25 | !1)});return a(window,"blur",function(){var a,b,d;b=0;for(d=g.length;b"),r=["calc","-webkit-calc","-moz-calc"];e("body").append(t);for(var i=0;i170&&e("li.small",r).length<1?r.addClass("large-format"):r.removeClass("large-format"),200>s?r.removeClass("small-format").addClass("tiny-format"):r.removeClass("tiny-format")})},o=function(){e(".rrssb-buttons").each(function(t){var r=e(this),s=e("li",r),i=s.filter(".small"),a=0,n=0,l=i.first(),o=parseFloat(l.attr("data-size"))+55,c=i.length;if(c===s.length){var d=42*c,m=r.width();m>d+o&&(r.removeClass("small-format"),i.first().removeClass("small"),h())}else{s.not(".small").each(function(t){var r=e(this),s=parseFloat(r.attr("data-size"))+55,i=parseFloat(r.width());a+=i,n+=s});var u=a-n;u>o&&(l.removeClass("small"),h())}})},c=function(t){e(".rrssb-buttons").each(function(t){var r=e(this),s=e("li",r);e(s.get().reverse()).each(function(t,r){var i=e(this);if(i.hasClass("small")===!1){var a=parseFloat(i.attr("data-size"))+55,n=parseFloat(i.width());if(a>n){var l=s.not(".small").last();e(l).addClass("small"),h()}}--r||o()})}),t===!0&&m(h)},h=function(){e(".rrssb-buttons").each(function(t){var r,i,a,l,o,c=e(this),h=e("li",c),d=h.filter(".small"),m=d.length;m>0&&m!==h.length?(c.removeClass("small-format"),d.css("width","42px"),a=42*m,r=h.not(".small").length,i=100/r,o=a/r,s.calc===!1?(l=(c.innerWidth()-1)/r-o,l=Math.floor(1e3*l)/1e3,l+="px"):l=s.calc+"("+i+"% - "+o+"px)",h.not(".small").css("width",l)):m===h.length?(c.addClass("small-format"),n()):(c.removeClass("small-format"),n())}),l()},d=function(){e(".rrssb-buttons").each(function(t){e(this).addClass("rrssb-"+(t+1))}),i(),n(),e(".rrssb-buttons li .rrssb-text").each(function(t){var r=e(this),s=r.width();r.closest("li").attr("data-size",s)}),c(!0)},m=function(t){e(".rrssb-buttons li.small").removeClass("small"),c(),t()},u=function(e,s,i,a){var n=t.screenLeft!==r?t.screenLeft:screen.left,l=t.screenTop!==r?t.screenTop:screen.top,o=t.innerWidth?t.innerWidth:document.documentElement.clientWidth?document.documentElement.clientWidth:screen.width,c=t.innerHeight?t.innerHeight:document.documentElement.clientHeight?document.documentElement.clientHeight:screen.height,h=o/2-i/2+n,d=c/3-a/3+l,m=t.open(e,s,"scrollbars=yes, width="+i+", height="+a+", top="+d+", left="+h);t.focus&&m.focus()},f=function(){var t={};return function(e,r,s){s||(s="Don't call this twice without a uniqueId"),t[s]&&clearTimeout(t[s]),t[s]=setTimeout(e,r)}}();e(document).ready(function(){e(".rrssb-buttons a.popup").on("click",function(t){var r=e(this);u(r.attr("href"),r.find(".rrssb-text").html(),580,470),t.preventDefault()}),e(t).resize(function(){m(h),f(function(){m(h)},200,"finished resizing")}),d()}),t.rrssbInit=d}(window,$); -------------------------------------------------------------------------------- /vendor/sweet-alert.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t,n){function o(e){var t=x(),n=t.querySelector("h2"),o=t.querySelector("p"),a=t.querySelector("button.cancel"),r=t.querySelector("button.confirm");if(n.innerHTML=e.html?e.title:E(e.title).split("\n").join("
"),o.innerHTML=e.html?e.text:E(e.text||"").split("\n").join("
"),e.text&&A(o),e.customClass)T(t,e.customClass),t.setAttribute("data-custom-class",e.customClass);else{var s=t.getAttribute("data-custom-class");B(t,s),t.setAttribute("data-custom-class","")}if(O(t.querySelectorAll(".sa-icon")),e.type&&!u()){for(var c=!1,l=0;lo;o++)n=parseInt(e.substr(2*o,2),16),n=Math.round(Math.min(Math.max(0,n+n*t),255)).toString(16),a+=("00"+n).substr(n.length);return a}function r(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function s(e){var t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?parseInt(t[1],16)+", "+parseInt(t[2],16)+", "+parseInt(t[3],16):null}function i(e,t){var n=s(t);e.style.boxShadow="0 0 2px rgba("+n+", 0.8), inset 0 0 0 1px rgba(0, 0, 0, 0.05)"}function c(){var e=x();H(k(),10),A(e),T(e,"showSweetAlert"),B(e,"hideSweetAlert"),d=t.activeElement;var n=e.querySelector("button.confirm");n.focus(),setTimeout(function(){T(e,"visible")},500);var o=e.getAttribute("data-timer");"null"!==o&&""!==o&&(e.timeout=setTimeout(function(){v.close()},o))}function l(){var e=x();e.style.marginTop=D(x())}function u(){return e.attachEvent&&!e.addEventListener?!0:!1}function f(t){e.console&&e.console.log("SweetAlert: "+t)}var d,m,p,y,v,b,g=".sweet-alert",w=".sweet-overlay",h=["error","warning","info","success"],S={title:"",text:"",type:null,allowOutsideClick:!1,showConfirmButton:!0,showCancelButton:!1,closeOnConfirm:!0,closeOnCancel:!0,confirmButtonText:"OK",confirmButtonColor:"#AEDEF4",cancelButtonText:"Cancel",imageUrl:null,imageSize:null,timer:null,customClass:"",html:!1,animation:!0,allowEscapeKey:!0},x=function(){var e=t.querySelector(g);return e||(j(),e=x()),e},k=function(){return t.querySelector(w)},C=function(e,t){return new RegExp(" "+t+" ").test(" "+e.className+" ")},T=function(e,t){C(e,t)||(e.className+=" "+t)},B=function(e,t){var n=" "+e.className.replace(/[\t\r\n]/g," ")+" ";if(C(e,t)){for(;n.indexOf(" "+t+" ")>=0;)n=n.replace(" "+t+" "," ");e.className=n.replace(/^\s+|\s+$/g,"")}},E=function(e){var n=t.createElement("div");return n.appendChild(t.createTextNode(e)),n.innerHTML},q=function(e){e.style.opacity="",e.style.display="block"},A=function(e){if(e&&!e.length)return q(e);for(var t=0;t0?setTimeout(o,t):e.style.display="none"};o()},N=function(n){if("function"==typeof MouseEvent){var o=new MouseEvent("click",{view:e,bubbles:!1,cancelable:!0});n.dispatchEvent(o)}else if(t.createEvent){var a=t.createEvent("MouseEvents");a.initEvent("click",!1,!1),n.dispatchEvent(a)}else t.createEventObject?n.fireEvent("onclick"):"function"==typeof n.onclick&&n.onclick()},P=function(t){"function"==typeof t.stopPropagation?(t.stopPropagation(),t.preventDefault()):e.event&&e.event.hasOwnProperty("cancelBubble")&&(e.event.cancelBubble=!0)},j=function(){var e='

Title

Text

',n=t.createElement("div");for(n.innerHTML=e;n.firstChild;)t.body.appendChild(n.firstChild)};v=b=function(){function s(e){var t=b;return"undefined"!=typeof t[e]?t[e]:S[e]}function u(t){var o=t||e.event,a=o.keyCode||o.which;if(-1!==[9,13,32,27].indexOf(a)){for(var r=o.target||o.srcElement,s=-1,c=0;ck;k++){var T=w[k];g[T]=s(T)}g.confirmButtonText=g.showCancelButton?"Confirm":S.confirmButtonText,g.confirmButtonText=s("confirmButtonText"),g.doneFunction=arguments[1]||null;break;default:return f('Unexpected type of argument! Expected "string" or "object", got '+typeof arguments[0]),!1}o(g),l(),c();for(var B=x(),E=function(t){var n=t||e.event,o=n.target||n.srcElement,r=-1!==o.className.indexOf("confirm"),s=C(B,"visible"),i=g.doneFunction&&"true"===B.getAttribute("data-has-done-function");switch(n.type){case"mouseover":r&&(o.style.backgroundColor=a(g.confirmButtonColor,-.04));break;case"mouseout":r&&(o.style.backgroundColor=g.confirmButtonColor);break;case"mousedown":r&&(o.style.backgroundColor=a(g.confirmButtonColor,-.14));break;case"mouseup":r&&(o.style.backgroundColor=a(g.confirmButtonColor,-.04));break;case"focus":var c=B.querySelector("button.confirm"),l=B.querySelector("button.cancel");r?l.style.boxShadow="none":c.style.boxShadow="none";break;case"click":if(r&&i&&s)g.doneFunction(!0),g.closeOnConfirm&&v.close();else if(i&&s){var u=String(g.doneFunction).replace(/\s/g,""),f="function("===u.substring(0,9)&&")"!==u.substring(9,10);f&&g.doneFunction(!1),g.closeOnCancel&&v.close()}else v.close()}},q=B.querySelectorAll("button"),A=0;A