From 4fafed3b769845072924889029c7d02fa7c75210 Mon Sep 17 00:00:00 2001 From: Greg French Date: Fri, 8 May 2015 15:01:01 -0400 Subject: [PATCH 001/160] Added missing semicolons --- js/snake.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/snake.js b/js/snake.js index aa0be7a5..e2f114f1 100644 --- a/js/snake.js +++ b/js/snake.js @@ -287,7 +287,7 @@ SNAKE.Snake = SNAKE.Snake || (function() { index = "b" + me.snakeLength++; me.snakeBody[index] = blocks[ii]; me.snakeBody[index].prev = prevNode; - me.snakeBody[index].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') + me.snakeBody[index].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,''); me.snakeBody[index].elm.className += " snake-snakebody-alive"; prevNode.next = me.snakeBody[index]; prevNode = me.snakeBody[index]; @@ -305,7 +305,7 @@ SNAKE.Snake = SNAKE.Snake || (function() { */ me.handleDeath = function() { me.snakeHead.elm.style.zIndex = getNextHighestZIndex(me.snakeBody); - me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/,'') + me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/,''); me.snakeHead.elm.className += " snake-snakebody-dead"; isDead = true; @@ -346,12 +346,12 @@ SNAKE.Snake = SNAKE.Snake || (function() { for (var ii = 0; ii < blocks.length; ii++) { blocks[ii].elm.style.left = "-1000px"; blocks[ii].elm.style.top = "-1000px"; - blocks[ii].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') + blocks[ii].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,''); blocks[ii].elm.className += " snake-snakebody-alive"; } blockPool.concat(blocks); - me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') + me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,''); me.snakeHead.elm.className += " snake-snakebody-alive"; me.snakeHead.row = config.startRow || 1; me.snakeHead.col = config.startCol || 1; @@ -922,4 +922,4 @@ SNAKE.Board = SNAKE.Board || (function() { } }; // end return function -})(); \ No newline at end of file +})(); From 3f883340061fa7428b457813eb5412e74143be8d Mon Sep 17 00:00:00 2001 From: Greg French Date: Fri, 8 May 2015 15:24:09 -0400 Subject: [PATCH 002/160] Declared 'cTop' and 'cLeft' variables Variables were previously undeclared. --- js/snake.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/snake.js b/js/snake.js index e2f114f1..49cff031 100644 --- a/js/snake.js +++ b/js/snake.js @@ -771,7 +771,7 @@ SNAKE.Board = SNAKE.Board || (function() { if (!elmPlayingField) {createBoardElements();} // create playing field // calculate width of our game container - var cWidth, cHeight; + var cWidth, cHeight, cTop, cLeft; if (config.fullScreen === true) { cTop = 0; cLeft = 0; From 2c405e0355bad0e195fad9888b7f6025655a43a2 Mon Sep 17 00:00:00 2001 From: Patrick Gillespie Date: Wed, 10 Jun 2015 21:09:31 -0400 Subject: [PATCH 003/160] Added pause feature and wasd keys --- README.md | 0 css/images/Thumbs.db | Bin css/images/deadblock.png | Bin css/images/snakeblock.png | Bin css/snake.css | 17 +++++++++- index.htm | 22 +++++++++---- js/snake.js | 67 +++++++++++++++++++++++++++++++------- 7 files changed, 88 insertions(+), 18 deletions(-) mode change 100644 => 100755 README.md mode change 100644 => 100755 css/images/Thumbs.db mode change 100644 => 100755 css/images/deadblock.png mode change 100644 => 100755 css/images/snakeblock.png mode change 100644 => 100755 css/snake.css mode change 100644 => 100755 index.htm diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/css/images/Thumbs.db b/css/images/Thumbs.db old mode 100644 new mode 100755 diff --git a/css/images/deadblock.png b/css/images/deadblock.png old mode 100644 new mode 100755 diff --git a/css/images/snakeblock.png b/css/images/snakeblock.png old mode 100644 new mode 100755 diff --git a/css/snake.css b/css/snake.css old mode 100644 new mode 100755 index dc80d4bb..ad76c145 --- a/css/snake.css +++ b/css/snake.css @@ -23,6 +23,21 @@ a.snake-link:hover { color: #FfFf54; } +.snake-pause-screen { + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position:absolute; + width:300px; + height:80px; + text-align:center; + top:50%; + left:50%; + margin-top:-40px; + margin-left:-150px; + display:none; + background-color:black; + color:white; +} .snake-panel-component { position: absolute; @@ -88,7 +103,7 @@ a.snake-link:hover { top: 50%; left: 50%; width: 300px; - height: 150px; + /*height: 150px;*/ margin-top: -100px; margin-left: -158px; text-align: center; diff --git a/index.htm b/index.htm old mode 100644 new mode 100755 index 39921570..26b1e25b --- a/index.htm +++ b/index.htm @@ -1,5 +1,5 @@ - + JavaScript Snake + +
diff --git a/js/snake.js b/js/snake.js index 49cff031..1f00b597 100644 --- a/js/snake.js +++ b/js/snake.js @@ -123,7 +123,8 @@ SNAKE.Snake = SNAKE.Snake || (function() { xPosShift = [], yPosShift = [], snakeSpeed = 75, - isDead = false; + isDead = false, + isPaused = false; // ----- public variables ----- @@ -179,6 +180,13 @@ SNAKE.Snake = SNAKE.Snake || (function() { // ----- public methods ----- + me.setPaused = function(val) { + isPaused = val; + }; + me.getPaused = function() { + return isPaused; + }; + /** * This method is called when a user presses a key. It logs arrow key presses in "moveQueue", which is used when the snake needs to make its next move. * @method handleArrowKeys @@ -192,28 +200,35 @@ SNAKE.Snake = SNAKE.Snake || (function() { 2 */ me.handleArrowKeys = function(keyNum) { - if (isDead) {return;} + if (isDead || isPaused) {return;} var snakeLength = me.snakeLength; var lastMove = moveQueue[0] || currentDirection; + //console.log("lastmove="+lastMove); + //console.log("dir="+keyNum); + switch (keyNum) { case 37: + case 65: if ( lastMove !== 1 || snakeLength === 1 ) { moveQueue.unshift(3); //SnakeDirection = 3; } break; case 38: + case 87: if ( lastMove !== 2 || snakeLength === 1 ) { moveQueue.unshift(0);//SnakeDirection = 0; } break; case 39: + case 68: if ( lastMove !== 3 || snakeLength === 1 ) { moveQueue.unshift(1); //SnakeDirection = 1; } break; case 40: + case 83: if ( lastMove !== 0 || snakeLength === 1 ) { moveQueue.unshift(2);//SnakeDirection = 2; } @@ -232,6 +247,11 @@ SNAKE.Snake = SNAKE.Snake || (function() { myDirection = currentDirection, grid = playingBoard.grid; // cache grid for quicker lookup + if (isPaused === true) { + setTimeout(function(){me.go();}, snakeSpeed); + return; + } + me.snakeTail = newHead.prev; me.snakeHead = newHead; @@ -260,7 +280,7 @@ SNAKE.Snake = SNAKE.Snake || (function() { if (grid[newHead.row][newHead.col] === 0) { grid[newHead.row][newHead.col] = 1; - setTimeout(function(){me.go();}, snakeSpeed); + setTimeout(function(){me.go();}, snakeSpeed); } else if (grid[newHead.row][newHead.col] > 0) { me.handleDeath(); } else if (grid[newHead.row][newHead.col] === playingBoard.getGridFoodValue()) { @@ -287,7 +307,7 @@ SNAKE.Snake = SNAKE.Snake || (function() { index = "b" + me.snakeLength++; me.snakeBody[index] = blocks[ii]; me.snakeBody[index].prev = prevNode; - me.snakeBody[index].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,''); + me.snakeBody[index].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') me.snakeBody[index].elm.className += " snake-snakebody-alive"; prevNode.next = me.snakeBody[index]; prevNode = me.snakeBody[index]; @@ -305,7 +325,7 @@ SNAKE.Snake = SNAKE.Snake || (function() { */ me.handleDeath = function() { me.snakeHead.elm.style.zIndex = getNextHighestZIndex(me.snakeBody); - me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/,''); + me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/,'') me.snakeHead.elm.className += " snake-snakebody-dead"; isDead = true; @@ -346,12 +366,12 @@ SNAKE.Snake = SNAKE.Snake || (function() { for (var ii = 0; ii < blocks.length; ii++) { blocks[ii].elm.style.left = "-1000px"; blocks[ii].elm.style.top = "-1000px"; - blocks[ii].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,''); + blocks[ii].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') blocks[ii].elm.className += " snake-snakebody-alive"; } blockPool.concat(blocks); - me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,''); + me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') me.snakeHead.elm.className += " snake-snakebody-alive"; me.snakeHead.row = config.startRow || 1; me.snakeHead.col = config.startCol || 1; @@ -556,8 +576,9 @@ SNAKE.Board = SNAKE.Board || (function() { mySnake, boardState = 1, // 0: in active; 1: awaiting game start; 2: playing game myKeyListener, + isPaused = false,//note: both the board and the snake can be paused // Board components - elmContainer, elmPlayingField, elmAboutPanel, elmLengthPanel, elmWelcome, elmTryAgain; + elmContainer, elmPlayingField, elmAboutPanel, elmLengthPanel, elmWelcome, elmTryAgain, elmPauseScreen; // --- public variables --- me.grid = []; @@ -575,6 +596,10 @@ SNAKE.Board = SNAKE.Board || (function() { elmContainer.focus(); }, false); + elmPauseScreen = document.createElement("div"); + elmPauseScreen.className = "snake-pause-screen"; + elmPauseScreen.innerHTML = "
[Paused]

Press [space] to unpause.

"; + elmAboutPanel = document.createElement("div"); elmAboutPanel.className = "snake-panel-component"; elmAboutPanel.innerHTML = "more patorjk.com apps - source code"; @@ -596,6 +621,8 @@ SNAKE.Board = SNAKE.Board || (function() { elmContainer.className = "snake-game-container"; + elmPauseScreen.style.zIndex = 10000; + elmContainer.appendChild(elmPauseScreen); elmContainer.appendChild(elmPlayingField); elmContainer.appendChild(elmAboutPanel); elmContainer.appendChild(elmLengthPanel); @@ -687,6 +714,19 @@ SNAKE.Board = SNAKE.Board || (function() { // public functions // --------------------------------------------------------------------- + me.setPaused = function(val) { + isPaused = val; + mySnake.setPaused(val); + if (isPaused) { + elmPauseScreen.style.display = "block"; + } else { + elmPauseScreen.style.display = "none"; + } + }; + me.getPaused = function() { + return isPaused; + }; + /** * Resets the playing board for a new game. * @method resetBoard @@ -771,7 +811,7 @@ SNAKE.Board = SNAKE.Board || (function() { if (!elmPlayingField) {createBoardElements();} // create playing field // calculate width of our game container - var cWidth, cHeight, cTop, cLeft; + var cWidth, cHeight; if (config.fullScreen === true) { cTop = 0; cLeft = 0; @@ -843,7 +883,7 @@ SNAKE.Board = SNAKE.Board || (function() { var keyNum = (evt.which) ? evt.which : evt.keyCode; if (me.getBoardState() === 1) { - if ( !(keyNum >= 37 && keyNum <= 40) ) {return;} // if not an arrow key, leave + if ( !(keyNum >= 37 && keyNum <= 40) && !(keyNum === 87 || keyNum === 65 || keyNum === 83 || keyNum === 68)) {return;} // if not an arrow key, leave // This removes the listener added at the #listenerX line SNAKE.removeEventListener(elmContainer, "keydown", myKeyListener, false); @@ -852,6 +892,11 @@ SNAKE.Board = SNAKE.Board || (function() { if (!evt) var evt = window.event; var keyNum = (evt.which) ? evt.which : evt.keyCode; + //console.log(keyNum); + if (keyNum === 32) { + me.setPaused(!me.getPaused()); + } + mySnake.handleArrowKeys(keyNum); evt.cancelBubble = true; @@ -922,4 +967,4 @@ SNAKE.Board = SNAKE.Board || (function() { } }; // end return function -})(); +})(); \ No newline at end of file From f2f5691725eba8bb3b13897478874cb19a05286c Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sat, 21 Nov 2015 14:52:05 -0500 Subject: [PATCH 004/160] Create dark-snake.css --- css/dark-snake.css | 148 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 css/dark-snake.css diff --git a/css/dark-snake.css b/css/dark-snake.css new file mode 100644 index 00000000..fd552724 --- /dev/null +++ b/css/dark-snake.css @@ -0,0 +1,148 @@ +/* +JavaScript Snake +By Patrick Gillespie +http://patorjk.com/games/snake +*/ +#high-score-dialog { + background: black; + color: #3E2E44; + position: relative; + bottom: 200px; +} + +select { + border: black; + color: #3E2E44; + background: black; +} + +button { + border: black; + color: #3E2E44; + background: black; +} + +body { + margin:0px; + padding:0px; +} + +#game-area { + margin:0px; + padding:0px; +} + +#game-area:focus { outline: none; } + +a.snake-link, a.snake-link:link, a.snake-link:visited { + color: black; +} + +a.snake-link:hover { + color: #3E2E44; +} + +.snake-pause-screen { + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position:absolute; + width:300px; + height:80px; + text-align:center; + top:50%; + left:50%; + margin-top:-40px; + margin-left:-150px; + display:none; + background-color:#3E2E44; + color:black; +} + +.snake-panel-component { + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: black; + text-align: center; + background-color: #3E2E44; + padding: 8px; + margin: 0px; +} + +.snake-snakebody-block { + margin: 0px; + padding: 0px; + background-color: #3E2E44; + position: absolute; + border: 0px solid black; + background-repeat: no-repeat; +} + +.snake-snakebody-alive { + background-image: url('./images/dark-snakeblock.png'); +} +.snake-snakebody-dead { + background-image: url('./images/dead-dark-snakeblock.png'); +} + +.snake-food-block { + margin: 0px; + padding: 0px; + background-color: black; + border: 2px solid #3E2E44; + position: absolute; +} + +.snake-playing-field { + margin: 0px; + padding: 0px; + position: absolute; + background-color: #312E44; + border: 3px solid black; +} + +.snake-game-container { + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + background-color: #3E2E44; + position: relative; +} + +.snake-welcome-dialog { + padding: 8px; + margin: 0px; + background-color: black; + color: #3E2E44; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; +} + +.snake-try-again-dialog { + padding: 8px; + margin: 0px; + background-color: black; + color: #312E44; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; +} From 8a0bd9512c683cd368ed5c67d7bd655eaf42fcfe Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sat, 21 Nov 2015 14:52:36 -0500 Subject: [PATCH 005/160] Update and rename snake.css to main-snake.css --- css/{snake.css => main-snake.css} | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) rename css/{snake.css => main-snake.css} (97%) diff --git a/css/snake.css b/css/main-snake.css similarity index 97% rename from css/snake.css rename to css/main-snake.css index ad76c145..be360a8f 100755 --- a/css/snake.css +++ b/css/main-snake.css @@ -3,6 +3,11 @@ JavaScript Snake By Patrick Gillespie http://patorjk.com/games/snake */ +#high-score-dialog { + background: red; + color: #FCFC54; +} + body { margin:0px; padding:0px; @@ -126,4 +131,4 @@ a.snake-link:hover { margin-left: -158px; text-align: center; display: none; -} \ No newline at end of file +} From 04c9abdf9a54812d6484c8248c476b378ca839dc Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sat, 21 Nov 2015 14:53:48 -0500 Subject: [PATCH 006/160] Update snake.js --- js/snake.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/js/snake.js b/js/snake.js index 1f00b597..f3ff5c1b 100644 --- a/js/snake.js +++ b/js/snake.js @@ -127,7 +127,7 @@ SNAKE.Snake = SNAKE.Snake || (function() { isPaused = false; // ----- public variables ----- - + me.sessionHighScore = 1; me.snakeBody = {}; me.snakeBody["b0"] = new SnakeBlock(); // create snake head me.snakeBody["b0"].row = config.startRow || 1; @@ -324,6 +324,13 @@ SNAKE.Snake = SNAKE.Snake || (function() { * @method handleDeath */ me.handleDeath = function() { + if (me.snakeLength > me.sessionHighScore) me.sessionHighScore = me.snakeLength; + function highScoreAlert() { + document.getElementById('high-score-dialog').innerHTML = 'Your current high score for this session is ' + me.sessionHighScore + '.'; + $(function() { + $( "#high-score-dialog" ).dialog(); + })} + highScoreAlert(); me.snakeHead.elm.style.zIndex = getNextHighestZIndex(me.snakeBody); me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/,'') me.snakeHead.elm.className += " snake-snakebody-dead"; @@ -709,7 +716,6 @@ SNAKE.Board = SNAKE.Board || (function() { tmpElm.appendChild(tryAgainStart); return tmpElm; } - // --------------------------------------------------------------------- // public functions // --------------------------------------------------------------------- @@ -967,4 +973,4 @@ SNAKE.Board = SNAKE.Board || (function() { } }; // end return function -})(); \ No newline at end of file +})(); From c14eb1ba556c0aaad8f44152795d6392bf01ce2a Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sat, 21 Nov 2015 14:54:50 -0500 Subject: [PATCH 007/160] Update index.htm --- index.htm | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/index.htm b/index.htm index 26b1e25b..3f2bdcc0 100755 --- a/index.htm +++ b/index.htm @@ -1,5 +1,5 @@ - + JavaScript Snake - - - + + +
- \ No newline at end of file + From 1f7860360474484cb296163990d38e3448e0daba Mon Sep 17 00:00:00 2001 From: ultra17 Date: Sat, 21 Nov 2015 20:10:19 +0000 Subject: [PATCH 008/160] Add dark-snakeblock.png --- css/images/dark-snakeblock.png | Bin 0 -> 1030 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 css/images/dark-snakeblock.png diff --git a/css/images/dark-snakeblock.png b/css/images/dark-snakeblock.png new file mode 100644 index 0000000000000000000000000000000000000000..66c4f1c2779f4bc29d51e16878bb60124560afd4 GIT binary patch literal 1030 zcmex=_1P|rX?qqI0P zFI~aY%U!`Mz|~!$%*;qrN1?DZF(6Oj-S5fuR$!pIEN!@|nR z%E~Fi%grl7GWdUhL6C#Nh{1@NQHg;`kdaxC@&6G9d7vj*8Nq-73K*GyZe(NU;N;>4 zD%dK(z{JSR%*4VBay3wOEl{3;MUYiU(a@1iI53f2sZhkIapFP_Wv7h?MT0JWP%%y_ zYU1P)6PJ*bQdLve(9|+9H8Z!cv~qTFb#wRd^a>6M4GWKmj7m;PO-s+n%qlJ^Ei136 ztZHs)ZENr7?3y%r%G7DoXUv?nXz`Mz%a*TLxoXqqEnBy3-?4Mop~FXx9y@;G&P778mFHFAhJORD6FcQrO=y<3Ga=wYmQpPJEgF;gkF= z)v7^X<=zuL_FyJ-@X4AD82A*Rmh&*Z(b;RsNqr`O@}3BK6-o zng4mo{|hvE|IdB>%x_}n>b;l*Pgt%}pBH<6>G?k*?cX{j{xfv9{%4rtYyF>L;>-Gn zkN-1l@w0!j@IS*-VZZ+jPpW<{c;O?G$hU@E@W^mwoRsT1d`lAg|CzBKEiB!i?(+MLx}J(n9WT;}}gE1PF1@L*Ok zkEZfkQ!DuSe=CG{?iASC&=(!>7Vm_#o~gPvgLJ$HY^R1YwL Date: Sat, 21 Nov 2015 20:12:52 +0000 Subject: [PATCH 009/160] Add dead-dark-snakeblock.png --- css/images/dead-dark-snakeblock.png | Bin 0 -> 1249 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 css/images/dead-dark-snakeblock.png diff --git a/css/images/dead-dark-snakeblock.png b/css/images/dead-dark-snakeblock.png new file mode 100644 index 0000000000000000000000000000000000000000..63302e51bed87fd0901f23d1cdf0a79f32945824 GIT binary patch literal 1249 zcmV<71Rnc|P)=BiM0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUyBv4FLMF0Q*0s;a90|N#I1_=oX3JMAh z4GjRZOg*)>&^Y$>c#z+3 z;{A;v`3OLsN@t46@ZC_%*_Ui>OynC$LX1XMK|egt55D z%E_;OT66R$p;wCt)z)tVFv`SY_>PmpybIB7{T?AEx?c_0IjFdc{+zWIu~l}v4rb?n z;=8=CF&qG4W!KLBz7{zF*U+=GtUtbMSzhddu(fj8c;lo8%12gUj(KsO;cjhb0j%$hJd;iW)i z;6`mh^yg;lJZw=|JVx$F-4#Pp`;{yMX|Lp*2<aY{XWw9CE z=2IQw>+wk516gJFlA#>gZ#}nWzy1i>)n>iBke|WJgjrmfi8yyi<^s--Gnavu#Ipfcr|vV2;}i>x4MIi)T)SG z=zdXJu3y9Li~to^cP&HxL%FZ7DwcjLl&p?wQvwGf$-g_dhsONMZTIHo#xJ6j?DqiW z0IWI-NRI7hA0LUWr?}xytaaZ0M+2N;UW6^Qyx{d+Oo_98$_gW#P%$|6KUB3A4lN@m zOK5+AI05C!#~uURugEjaJA%4sR})?Avv6V!82kaoIwW*3b@}T4*X}95-lU||pD1Gr zpo`8hmCv+UWasNm%PZKNV-K3VbcQRHfl~*wjs${NBW72#gjDfR9aGL%Sv&45I!+nj znm^-(Q^cw8&{z;sCR1~NnCKX^RakZ;Y*vys&Mx{}f@!%G!&3S`9L@2t1C0&r00000 LNkvXXu0mjfRFY0v literal 0 HcmV?d00001 From cb8a9cbc6e9ea05b1730fef2ce01f37851d68e13 Mon Sep 17 00:00:00 2001 From: ultra17 Date: Sat, 21 Nov 2015 22:44:25 +0000 Subject: [PATCH 010/160] Change positioning of high score dialog box. --- css/main-snake.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/css/main-snake.css b/css/main-snake.css index be360a8f..633acae5 100755 --- a/css/main-snake.css +++ b/css/main-snake.css @@ -6,6 +6,8 @@ http://patorjk.com/games/snake #high-score-dialog { background: red; color: #FCFC54; + position: relative; + bottom: 200px; } body { From 9bda519d1a9aca80cd9c78112da2de6ac00475ec Mon Sep 17 00:00:00 2001 From: ultra17 Date: Sun, 22 Nov 2015 01:59:50 +0000 Subject: [PATCH 011/160] Edit high-score system --- index.html | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ js/snake.js | 14 ++++++------- 2 files changed, 66 insertions(+), 7 deletions(-) create mode 100755 index.html diff --git a/index.html b/index.html new file mode 100755 index 00000000..6881c22c --- /dev/null +++ b/index.html @@ -0,0 +1,59 @@ + + + + + JavaScript Snake + + + + + + +
+
+ + +

High Score:

+
+ + diff --git a/js/snake.js b/js/snake.js index f3ff5c1b..c519d590 100644 --- a/js/snake.js +++ b/js/snake.js @@ -324,13 +324,13 @@ SNAKE.Snake = SNAKE.Snake || (function() { * @method handleDeath */ me.handleDeath = function() { - if (me.snakeLength > me.sessionHighScore) me.sessionHighScore = me.snakeLength; - function highScoreAlert() { - document.getElementById('high-score-dialog').innerHTML = 'Your current high score for this session is ' + me.sessionHighScore + '.'; - $(function() { - $( "#high-score-dialog" ).dialog(); - })} - highScoreAlert(); + function writeHighScore () { + if (me.snakeLength > me.sessionHighScore) + me.sessionHighScore = me.snakeLength; + document.getElementById('score').innerHTML = me.sessionHighScore; + + } + writeHighScore(); me.snakeHead.elm.style.zIndex = getNextHighestZIndex(me.snakeBody); me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/,'') me.snakeHead.elm.className += " snake-snakebody-dead"; From 9571405e5fc720678bcf577af7efc427dffb3245 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sat, 21 Nov 2015 21:03:44 -0500 Subject: [PATCH 012/160] Delete index.htm --- index.htm | 57 ------------------------------------------------------- 1 file changed, 57 deletions(-) delete mode 100755 index.htm diff --git a/index.htm b/index.htm deleted file mode 100755 index 3f2bdcc0..00000000 --- a/index.htm +++ /dev/null @@ -1,57 +0,0 @@ - - - - - JavaScript Snake - - - - - - - - -
-
- - -
- - From 95d0205b5114f04d1ea558ef4fd2ee006bfbb146 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sat, 21 Nov 2015 21:04:35 -0500 Subject: [PATCH 013/160] Update main-snake.css --- css/main-snake.css | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/css/main-snake.css b/css/main-snake.css index 633acae5..be9b2591 100755 --- a/css/main-snake.css +++ b/css/main-snake.css @@ -3,11 +3,22 @@ JavaScript Snake By Patrick Gillespie http://patorjk.com/games/snake */ -#high-score-dialog { - background: red; - color: #FCFC54; +.high-score { position: relative; - bottom: 200px; + left: 1163px; + bottom: 0px; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; +} + +#score { + position: relative; + left: 1250px; + bottom: 31px; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; } body { From f793e03a6efe8726bb7aa7eec1873b73f6753cc2 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sat, 21 Nov 2015 21:05:12 -0500 Subject: [PATCH 014/160] Update dark-snake.css --- css/dark-snake.css | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/css/dark-snake.css b/css/dark-snake.css index fd552724..bba4276e 100644 --- a/css/dark-snake.css +++ b/css/dark-snake.css @@ -3,11 +3,22 @@ JavaScript Snake By Patrick Gillespie http://patorjk.com/games/snake */ -#high-score-dialog { - background: black; - color: #3E2E44; +.high-score { + position: relative; + left: 1163px; + bottom: 0px; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; +} + +#score { position: relative; - bottom: 200px; + left: 1250px; + bottom: 31px; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; } select { From b83f0f899bbbb011f17677ad4a77522612ac37a1 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 09:20:07 -0500 Subject: [PATCH 015/160] Remove high-score feature --- index.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.html b/index.html index 6881c22c..01b03f1e 100755 --- a/index.html +++ b/index.html @@ -53,7 +53,5 @@ fullScreen: true }); -

High Score:

-
From d12d1c2f4530129bf86eee809ce5f5b4367a09d9 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 09:20:49 -0500 Subject: [PATCH 016/160] Remove high-score feature --- js/snake.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/js/snake.js b/js/snake.js index c519d590..049b07d6 100644 --- a/js/snake.js +++ b/js/snake.js @@ -324,13 +324,6 @@ SNAKE.Snake = SNAKE.Snake || (function() { * @method handleDeath */ me.handleDeath = function() { - function writeHighScore () { - if (me.snakeLength > me.sessionHighScore) - me.sessionHighScore = me.snakeLength; - document.getElementById('score').innerHTML = me.sessionHighScore; - - } - writeHighScore(); me.snakeHead.elm.style.zIndex = getNextHighestZIndex(me.snakeBody); me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/,'') me.snakeHead.elm.className += " snake-snakebody-dead"; From 6a217247956c8f13ba6350aab894b5a54d8b86ff Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 09:21:47 -0500 Subject: [PATCH 017/160] Remove high-score styles --- css/main-snake.css | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/css/main-snake.css b/css/main-snake.css index be9b2591..d264e35e 100755 --- a/css/main-snake.css +++ b/css/main-snake.css @@ -3,24 +3,6 @@ JavaScript Snake By Patrick Gillespie http://patorjk.com/games/snake */ -.high-score { - position: relative; - left: 1163px; - bottom: 0px; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; -} - -#score { - position: relative; - left: 1250px; - bottom: 31px; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; -} - body { margin:0px; padding:0px; @@ -144,4 +126,4 @@ a.snake-link:hover { margin-left: -158px; text-align: center; display: none; -} + } From 49f23179cee0edc483438bda0ef27f5b56254944 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 09:22:35 -0500 Subject: [PATCH 018/160] Remove high-score styles --- css/dark-snake.css | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/css/dark-snake.css b/css/dark-snake.css index bba4276e..281e2889 100644 --- a/css/dark-snake.css +++ b/css/dark-snake.css @@ -3,24 +3,6 @@ JavaScript Snake By Patrick Gillespie http://patorjk.com/games/snake */ -.high-score { - position: relative; - left: 1163px; - bottom: 0px; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; -} - -#score { - position: relative; - left: 1250px; - bottom: 31px; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; -} - select { border: black; color: #3E2E44; @@ -156,4 +138,4 @@ a.snake-link:hover { margin-left: -158px; text-align: center; display: none; -} + } From f8207d70789de4ce9c5b6682612c5702c76988c9 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 10:29:43 -0500 Subject: [PATCH 019/160] Remove variable sessionHighScore --- js/snake.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/js/snake.js b/js/snake.js index 049b07d6..f6963207 100644 --- a/js/snake.js +++ b/js/snake.js @@ -127,7 +127,6 @@ SNAKE.Snake = SNAKE.Snake || (function() { isPaused = false; // ----- public variables ----- - me.sessionHighScore = 1; me.snakeBody = {}; me.snakeBody["b0"] = new SnakeBlock(); // create snake head me.snakeBody["b0"].row = config.startRow || 1; @@ -384,7 +383,6 @@ SNAKE.Snake = SNAKE.Snake || (function() { // --------------------------------------------------------------------- // Initialize // --------------------------------------------------------------------- - createBlocks(growthIncr*2); xPosShift[0] = 0; xPosShift[1] = playingBoard.getBlockWidth(); @@ -642,7 +640,9 @@ SNAKE.Board = SNAKE.Board || (function() { } function createWelcomeElement() { - var tmpElm = document.createElement("div"); + //document.getElementById('mode-dialog').innerHTML = 'Select which mode you would like to play in.


'; + + var tmpElm = document.createElement("div"); tmpElm.id = "sbWelcome" + myId; tmpElm.className = "snake-welcome-dialog"; @@ -653,8 +653,7 @@ SNAKE.Board = SNAKE.Board || (function() { } welcomeTxt.innerHTML = "JavaScript Snake

Use the arrow keys on your keyboard to play the game. " + fullScreenText + "

"; var welcomeStart = document.createElement("button"); - welcomeStart.appendChild( document.createTextNode("Play Game")); - + welcomeStart.appendChild(document.createTextNode("Play Game")); var loadGame = function() { SNAKE.removeEventListener(window, "keyup", kbShortcut, false); tmpElm.style.display = "none"; From e4f1ffa0626f42a782cf4b59dec0e12ed25c9d30 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 11:06:23 -0500 Subject: [PATCH 020/160] Update dark-snake.css --- css/dark-snake.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/css/dark-snake.css b/css/dark-snake.css index 281e2889..2b7d74a0 100644 --- a/css/dark-snake.css +++ b/css/dark-snake.css @@ -27,6 +27,12 @@ body { #game-area:focus { outline: none; } +#mode-wrapper { + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: black; +} + a.snake-link, a.snake-link:link, a.snake-link:visited { color: black; } From 8077949355cbb5a597d99398676116c80de5dcb8 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 11:06:49 -0500 Subject: [PATCH 021/160] Update main-snake.css --- css/main-snake.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/css/main-snake.css b/css/main-snake.css index d264e35e..23bea2ee 100755 --- a/css/main-snake.css +++ b/css/main-snake.css @@ -13,6 +13,13 @@ body { padding:0px; } +#mode-wrapper { + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + +} + #game-area:focus { outline: none; } a.snake-link, a.snake-link:link, a.snake-link:visited { From 25129189f7f50a89962f6244693617994e35c149 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 11:07:17 -0500 Subject: [PATCH 022/160] Update snake.js --- js/snake.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/js/snake.js b/js/snake.js index f6963207..ab43072a 100644 --- a/js/snake.js +++ b/js/snake.js @@ -18,7 +18,6 @@ var SNAKE = SNAKE || {}; * @param {Function} funct The function to execute when the event is triggered. * @param {Boolean} evtCapturing True to do event capturing, false to do event bubbling. */ - SNAKE.addEventListener = (function() { if (window.addEventListener) { return function(obj, event, funct, evtCapturing) { @@ -125,7 +124,12 @@ SNAKE.Snake = SNAKE.Snake || (function() { snakeSpeed = 75, isDead = false, isPaused = false; - + function getMode (mode, speed) { + document.getElementById(mode).addEventListener('click', function () { snakeSpeed = speed; }); +} + getMode('Easy', 100); + getMode('Medium', 75); + getMode('Difficult', 50); // ----- public variables ----- me.snakeBody = {}; me.snakeBody["b0"] = new SnakeBlock(); // create snake head @@ -640,8 +644,6 @@ SNAKE.Board = SNAKE.Board || (function() { } function createWelcomeElement() { - //document.getElementById('mode-dialog').innerHTML = 'Select which mode you would like to play in.


'; - var tmpElm = document.createElement("div"); tmpElm.id = "sbWelcome" + myId; tmpElm.className = "snake-welcome-dialog"; @@ -875,7 +877,12 @@ SNAKE.Board = SNAKE.Board || (function() { myFood.randomlyPlaceFood(); // setup event listeners - + function getMode (mode, speed) { + document.getElementById(mode).addEventListener('click', function () { snakeSpeed = speed; }); +} + getMode('Easy', 100); + getMode('Medium', 75); + getMode('Difficult', 50); myKeyListener = function(evt) { if (!evt) var evt = window.event; var keyNum = (evt.which) ? evt.which : evt.keyCode; From b4345ee68a01a7f413722b471cd50fbc99bb1267 Mon Sep 17 00:00:00 2001 From: Ultra17 Date: Sun, 22 Nov 2015 11:07:55 -0500 Subject: [PATCH 023/160] Update index.html --- index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 01b03f1e..8cefc49d 100755 --- a/index.html +++ b/index.html @@ -15,8 +15,9 @@ +
Select which mode you would like to play in.


diff --git a/js/snake.js b/js/snake.js index 3c9dabe0..c73f4c7b 100644 --- a/js/snake.js +++ b/js/snake.js @@ -826,7 +826,7 @@ SNAKE.Board = SNAKE.Board || (function() { cLeft = 0; cWidth = getClientWidth()-5; cHeight = getClientHeight()-5; - document.body.style.backgroundColor = "#FC5454"; + document.body.style.backgroundColor = "#f73378"; } else { cTop = config.top; cLeft = config.left; From a58bef5f58be0861264809b6ff08cb47670506e3 Mon Sep 17 00:00:00 2001 From: Pim Kennedy Date: Wed, 31 Oct 2018 22:53:29 +0100 Subject: [PATCH 034/160] Update index.html --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 04762927..59a5042c 100755 --- a/index.html +++ b/index.html @@ -10,6 +10,7 @@ Source code is available here: https://github.com/patorjk/JavaScript-Snake --> + JavaScript Snake From 44e7ca80a30d73cca7ec5c31728a10dd9220601d Mon Sep 17 00:00:00 2001 From: legoman8304 Date: Wed, 10 Apr 2019 10:07:35 -0400 Subject: [PATCH 035/160] added a minified version of snake.js to use for speed rendering --- index.html | 10 +++++----- js/min-snake.js | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 js/min-snake.js diff --git a/index.html b/index.html index 59a5042c..e939ce95 100755 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + +--> JavaScript Snake @@ -27,7 +27,7 @@ } var index = document.getElementById("select").selectedIndex; switch (index) { - case 0: + case 0: changeTheme('css/dark-snake.css'); break; case 1: changeTheme('css/main-snake.css'); @@ -49,12 +49,12 @@
- + diff --git a/js/min-snake.js b/js/min-snake.js new file mode 100644 index 00000000..339037bc --- /dev/null +++ b/js/min-snake.js @@ -0,0 +1 @@ +var SNAKE=SNAKE||{};function getHighScore(){document.getElementById("high-score").addEventListener("click",function(){null==localStorage.jsSnakeHighScore?alert("You have not played this game yet!"):alert("Your current high score is "+localStorage.jsSnakeHighScore+".")})}SNAKE.addEventListener=window.addEventListener?function(e,t,n,a){e.addEventListener(t,n,a)}:window.attachEvent?function(e,t,n){e.attachEvent("on"+t,n)}:void 0,SNAKE.removeEventListener=window.removeEventListener?function(e,t,n,a){e.removeEventListener(t,n,a)}:window.detachEvent?function(e,t,n){e.detachEvent("on"+t,n)}:void 0,SNAKE.Snake=SNAKE.Snake||function(){var f=[],v=function(){this.elm=null,this.elmStyle=null,this.row=-1,this.col=-1,this.xPos=-1e3,this.yPos=-1e3,this.next=null,this.prev=null};return function(o){if(o&&o.playingBoard){var d=this,l=o.playingBoard,i=(0,[]),s=1,r=[0,1,0,-1],c=[-1,0,1,0],u=[],h=[],k=75,p=!1,m=!1;e("Easy",100),e("Medium",75),e("Difficult",50),d.snakeBody={},d.snakeBody.b0=new v,d.snakeBody.b0.row=o.startRow||1,d.snakeBody.b0.col=o.startCol||1,d.snakeBody.b0.xPos=d.snakeBody.b0.row*l.getBlockWidth(),d.snakeBody.b0.yPos=d.snakeBody.b0.col*l.getBlockHeight(),d.snakeBody.b0.elm=g(),d.snakeBody.b0.elmStyle=d.snakeBody.b0.elm.style,l.getBoardContainer().appendChild(d.snakeBody.b0.elm),d.snakeBody.b0.elm.style.left=d.snakeBody.b0.xPos+"px",d.snakeBody.b0.elm.style.top=d.snakeBody.b0.yPos+"px",d.snakeBody.b0.next=d.snakeBody.b0,d.snakeBody.b0.prev=d.snakeBody.b0,d.snakeLength=1,d.snakeHead=d.snakeBody.b0,d.snakeTail=d.snakeBody.b0,d.snakeHead.elm.className=d.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,""),d.snakeHead.elm.className+=" snake-snakebody-alive",d.setPaused=function(e){m=e},d.getPaused=function(){return m},d.handleArrowKeys=function(e){if(!p&&!m){var t=d.snakeLength,n=i[0]||s;switch(e){case 37:case 65:1===n&&1!==t||i.unshift(3);break;case 38:case 87:2===n&&1!==t||i.unshift(0);break;case 39:case 68:3===n&&1!==t||i.unshift(1);break;case 40:case 83:0===n&&1!==t||i.unshift(2)}}},d.go=function(){var e=d.snakeHead,t=d.snakeTail,n=s,a=l.grid;!0!==m?(d.snakeTail=t.prev,a[(d.snakeHead=t).row]&&a[t.row][t.col]&&(a[t.row][t.col]=0),i.length&&(n=s=i.pop()),t.col=e.col+r[n],t.row=e.row+c[n],t.xPos=e.xPos+u[n],t.yPos=e.yPos+h[n],t.elmStyle||(t.elmStyle=t.elm.style),t.elmStyle.left=t.xPos+"px",t.elmStyle.top=t.yPos+"px",0===a[t.row][t.col]?(a[t.row][t.col]=1,setTimeout(function(){d.go()},k)):0e&&(alert("Congratulations! You have beaten your previous high score, which was "+e+"."),localStorage.setItem("jsSnakeHighScore",d.snakeLength)),d.snakeHead.elm.style.zIndex=function(e){var t,n=0,a=0;for(t in e)e[t].elm.currentStyle?a=parseFloat(e[t].elm.style["z-index"],10):window.getComputedStyle&&(a=parseFloat(document.defaultView.getComputedStyle(e[t].elm,null).getPropertyValue("z-index"),10)),!isNaN(a)&&n[Paused]

Press [space] to unpause.

",(w=document.createElement("div")).className="snake-panel-component",w.innerHTML="more patorjk.com apps - source code",(B=document.createElement("div")).className="snake-panel-component",B.innerHTML="Length: 1",t=function(){var e=document.createElement("div");e.id="sbWelcome"+l,e.className="snake-welcome-dialog";var t=document.createElement("div"),n="";E.fullScreen&&(n="On Windows, press F11 to play in Full Screen mode.");t.innerHTML="JavaScript Snake

Use the arrow keys on your keyboard to play the game. "+n+"

";var a=document.createElement("button");a.appendChild(document.createTextNode("Play Game"));var o=function(){SNAKE.removeEventListener(window,"keyup",d,!1),e.style.display="none",b.setBoardState(1),b.getBoardContainer().focus()},d=function(e){if(!e)var e=window.event;var t=e.which?e.which:e.keyCode;32!==t&&13!==t||o()};return SNAKE.addEventListener(window,"keyup",d,!1),SNAKE.addEventListener(a,"click",o,!1),e.appendChild(t),e.appendChild(a),e}(),n=function(){var n=document.createElement("div");n.id="sbTryAgain"+l,n.className="snake-try-again-dialog";var e=document.createElement("div");e.innerHTML="JavaScript Snake

You died :(.

";var t=document.createElement("button");t.appendChild(document.createTextNode("Play Again?"));var a=function(){n.style.display="none",b.resetBoard(),b.setBoardState(1),b.getBoardContainer().focus()};return SNAKE.addEventListener(window,"keyup",function(e){if(0===o&&"block"===n.style.display){if(!e)var e=window.event;var t=e.which?e.which:e.keyCode;32!==t&&13!==t||a()}},!0),SNAKE.addEventListener(t,"click",a,!1),n.appendChild(e),n.appendChild(t),n}(),SNAKE.addEventListener(f,"keyup",function(e){if(!e)e=window.event;return e.cancelBubble=!0,e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault(),!1},!1),f.className="snake-game-container",a.style.zIndex=1e4,f.appendChild(a),f.appendChild(v),f.appendChild(w),f.appendChild(B),f.appendChild(t),f.appendChild(n),g=new SNAKE.Snake({playingBoard:b,startRow:2,startCol:2}),m=new SNAKE.Food({playingBoard:b}),t.style.zIndex=1e3}b.grid=[],b.setPaused=function(e){d=e,g.setPaused(e),a.style.display=d?"block":"none"},b.getPaused=function(){return d},b.resetBoard=function(){SNAKE.removeEventListener(f,"keydown",y,!1),g.reset(),B.innerHTML="Length: 1",b.setupPlayingField()},b.getBoardState=function(){return o},b.setBoardState=function(e){o=e},b.getGridFoodValue=function(){return-1},b.getPlayingFieldElement=function(){return v},b.setBoardContainer=function(e){"string"==typeof e&&(e=document.getElementById(e)),e!==f&&(f=e,v=null,b.setupPlayingField())},b.getBoardContainer=function(){return f},b.getBlockWidth=function(){return 20},b.getBlockHeight=function(){return 20},b.setupPlayingField=function(){var e,t,n,a;v||S(),!0===E.fullScreen?(cTop=0,cLeft=0,a=0,"number"==typeof window.innerWidth?a=window.innerWidth:document.documentElement&&(document.documentElement.clientWidth||document.documentElement.clientHeight)?a=document.documentElement.clientWidth:document.body&&(document.body.clientWidth||document.body.clientHeight)&&(a=document.body.clientWidth),e=a-5,n=0,"number"==typeof window.innerHeight?n=window.innerHeight:document.documentElement&&(document.documentElement.clientWidth||document.documentElement.clientHeight)?n=document.documentElement.clientHeight:document.body&&(document.body.clientWidth||document.body.clientHeight)&&(n=document.body.clientHeight),t=n-5,document.body.style.backgroundColor="#FC5454"):(cTop=E.top,cLeft=E.left,e=E.width,t=E.height);var o=2*b.getBlockWidth()+e%b.getBlockWidth(),d=Math.min(250*b.getBlockWidth()-o,e-o),l=3*b.getBlockHeight()+t%b.getBlockHeight(),i=Math.min(250*b.getBlockHeight()-l,t-l);f.style.left=cLeft+"px",f.style.top=cTop+"px",f.style.width=e+"px",f.style.height=t+"px",v.style.left=b.getBlockWidth()+"px",v.style.top=b.getBlockHeight()+"px",v.style.width=d+"px",v.style.height=i+"px";var s=l-b.getBlockHeight(),r=b.getBlockHeight()+i+Math.round((s-30)/2)+"px";w.style.top=r,w.style.width="450px",w.style.left=Math.round(e/2)-Math.round(225)+"px",B.style.top=r,B.style.left=e-120+"px",w.style.display=e<700?"none":"block",b.grid=[];for(var c=d/b.getBlockWidth()+2,u=i/b.getBlockHeight()+2,h=0;h Date: Fri, 12 Apr 2019 08:39:09 -0400 Subject: [PATCH 036/160] added a toggle button for light/dark theme for easier switching --- index.html | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/index.html b/index.html index e939ce95..54c6428a 100755 --- a/index.html +++ b/index.html @@ -13,25 +13,21 @@ JavaScript Snake - - +
Select which mode you would like to play in.


+
+
+ Theme: + +
+
+ Mode: + +
+
+ +
+
+ + +
+
+
- + + From e5f1f4241153e19b2d5ce4cc0a4bae76b2f94254 Mon Sep 17 00:00:00 2001 From: Bugs Bunny <57536929+mamamia5x@users.noreply.github.com> Date: Tue, 17 Dec 2019 09:21:11 -0600 Subject: [PATCH 062/160] Shows the snake favicon on the tab --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index f768bb23..24330506 100755 --- a/index.html +++ b/index.html @@ -13,7 +13,7 @@ JavaScript Snake - + + + + + +
+
+ Theme: + +
+
+ Mode: + +
+ +
+
+ +
+ +
+ + + + + diff --git a/src/css/Senura-snake.css b/src/css/Senura-snake.css index 15ac9b61..2102a783 100644 --- a/src/css/Senura-snake.css +++ b/src/css/Senura-snake.css @@ -5,29 +5,33 @@ http://patorjk.com/games/snake */ body { - margin:0px; - padding:0px; - background-color:#000000; + margin: 0px; + padding: 0px; + background-color: #000000; } .snake-toolbar { - color: #847a87; + color: #847a87; } #game-area { - margin:10px; - padding:0px; + margin: 10px; + padding: 0px; } -#game-area:focus { outline: none; } +#game-area:focus { + outline: none; +} #mode-wrapper { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #f6f0f7; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #f6f0f7; } -a.snake-link, a.snake-link:link, a.snake-link:visited { +a.snake-link, +a.snake-link:link, +a.snake-link:visited { color: #605d61; } @@ -36,106 +40,107 @@ a.snake-link:hover { } .snake-pause-screen { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position:absolute; - width:300px; - height:80px; - text-align:center; - top:50%; - left:50%; - margin-top:-40px; - margin-left:-150px; - display:none; - background-color:#ffffff; - color: #938996; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: #ffffff; + color: #938996; } .snake-panel-component { - position: absolute; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #cf6d6d; - text-align: center; - background-color: #550b70; - padding: 8px; - margin: 0px; + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #cf6d6d; + text-align: center; + background-color: #550b70; + padding: 8px; + margin: 0px; } .snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: #eddff2; - position: absolute; - border: 0px solid black; - background-repeat: no-repeat; + margin: 0px; + padding: 0px; + background-color: #eddff2; + position: absolute; + border: 0px solid black; + background-repeat: no-repeat; } .snake-snakebody-alive { - background-image: url('src/css/images/dark-snakeblock.png'); + background-image: url("src/css/images/dark-snakeblock.png"); } .snake-snakebody-dead { - background-image: url('src/css/images/dead-dark-snakeblock.png'); + background-image: url("src/css/images/dead-dark-snakeblock.png"); } .snake-food-block { - margin: 0px; - padding: 0px; - background-color: black; - border: 2px solid #000000; - position: absolute; + margin: 0px; + padding: 0px; + background-color: black; + border: 2px solid #000000; + position: absolute; } .snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: #fcfcfc; - border: 3px solid black; + margin: 0px; + padding: 0px; + position: absolute; + background-color: #fcfcfc; + border: 3px solid black; } .snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - background-color: #3E2E44; - position: relative; + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + background-color: #3e2e44; + position: relative; } .snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: black; - color: #ab00de; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; -} - -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: black; - color: #ab00de; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; + padding: 8px; + margin: 0px; + background-color: black; + color: #ab00de; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; +} + +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: black; + color: #ab00de; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; } diff --git a/src/css/black-snake.css b/src/css/black-snake.css index 90d22abf..a92710b5 100644 --- a/src/css/black-snake.css +++ b/src/css/black-snake.css @@ -4,133 +4,139 @@ By Patrick Gillespie http://patorjk.com/games/snake */ body { - margin:0px; - padding:0px; - background-color: black; - color: white; + margin: 0px; + padding: 0px; + background-color: black; + color: white; } #game-area { - margin:10px; - padding:0px; + margin: 10px; + padding: 0px; } #mode-wrapper { - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; } -#game-area:focus { outline: none; } +#game-area:focus { + outline: none; +} -a.snake-link, a.snake-link:link, a.snake-link:visited { - color: #FCFC54; +a.snake-link, +a.snake-link:link, +a.snake-link:visited { + color: #fcfc54; } a.snake-link:hover { - color: #FfFf54; + color: #ffff54; } .snake-pause-screen { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position:absolute; - width:300px; - height:80px; - text-align:center; - top:50%; - left:50%; - margin-top:-40px; - margin-left:-150px; - display:none; - background-color:black; - color:white; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: black; + color: white; } .snake-panel-component { - position: absolute; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; - text-align: center; - padding: 8px; - margin: 0px; + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; + text-align: center; + padding: 8px; + margin: 0px; } .snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: #FF0000; - position: absolute; - border: 0px solid #000080; - background-repeat: no-repeat; + margin: 0px; + padding: 0px; + background-color: #ff0000; + position: absolute; + border: 0px solid #000080; + background-repeat: no-repeat; } .snake-snakebody-alive { - background-image: url('src/cssss/images/snakeblock.png'), url('src/css/images/snakeblock.png'); + background-image: url("src/cssss/images/snakeblock.png"), + url("src/css/images/snakeblock.png"); } .snake-snakebody-dead { - background-image: url('src/cssss/images/deadblock.png'), url('src/css/images/deadblock.png'); + background-image: url("src/cssss/images/deadblock.png"), + url("src/css/images/deadblock.png"); } .snake-food-block { - margin: 0px; - padding: 0px; - background-color: aqua; - border: 0px solid #000080; - position: absolute; + margin: 0px; + padding: 0px; + background-color: aqua; + border: 0px solid #000080; + position: absolute; } .snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: purple; - border: 0px solid purple; + margin: 0px; + padding: 0px; + position: absolute; + background-color: purple; + border: 0px solid purple; } .snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - position: relative; + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + position: relative; } .snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; } -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; } diff --git a/src/css/dark-snake.css b/src/css/dark-snake.css index 8603a1cb..16388e41 100644 --- a/src/css/dark-snake.css +++ b/src/css/dark-snake.css @@ -5,29 +5,33 @@ http://patorjk.com/games/snake */ body { - margin:0px; - padding:0px; - background-color:#3E2E44; + margin: 0px; + padding: 0px; + background-color: #3e2e44; } .snake-toolbar { - color: #938996; + color: #938996; } #game-area { - margin:10px; - padding:0px; + margin: 10px; + padding: 0px; } -#game-area:focus { outline: none; } +#game-area:focus { + outline: none; +} #mode-wrapper { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #938996; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #938996; } -a.snake-link, a.snake-link:link, a.snake-link:visited { +a.snake-link, +a.snake-link:link, +a.snake-link:visited { color: #938996; } @@ -36,106 +40,107 @@ a.snake-link:hover { } .snake-pause-screen { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position:absolute; - width:300px; - height:80px; - text-align:center; - top:50%; - left:50%; - margin-top:-40px; - margin-left:-150px; - display:none; - background-color:#3E2E44; - color: #938996; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: #3e2e44; + color: #938996; } .snake-panel-component { - position: absolute; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #938996; - text-align: center; - background-color: #3E2E44; - padding: 8px; - margin: 0px; + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #938996; + text-align: center; + background-color: #3e2e44; + padding: 8px; + margin: 0px; } .snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: #3E2E44; - position: absolute; - border: 0px solid black; - background-repeat: no-repeat; + margin: 0px; + padding: 0px; + background-color: #3e2e44; + position: absolute; + border: 0px solid black; + background-repeat: no-repeat; } .snake-snakebody-alive { - background-image: url('src/css/images/dark-snakeblock.png'); + background-image: url("src/css/images/dark-snakeblock.png"); } .snake-snakebody-dead { - background-image: url('src/css/images/dead-dark-snakeblock.png'); + background-image: url("src/css/images/dead-dark-snakeblock.png"); } .snake-food-block { - margin: 0px; - padding: 0px; - background-color: black; - border: 2px solid #3E2E44; - position: absolute; + margin: 0px; + padding: 0px; + background-color: black; + border: 2px solid #3e2e44; + position: absolute; } .snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: #312E44; - border: 3px solid black; + margin: 0px; + padding: 0px; + position: absolute; + background-color: #312e44; + border: 3px solid black; } .snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - background-color: #3E2E44; - position: relative; + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + background-color: #3e2e44; + position: relative; } .snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: black; - color: #938996; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; -} - -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: black; - color: #938996; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; + padding: 8px; + margin: 0px; + background-color: black; + color: #938996; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; +} + +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: black; + color: #938996; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; } diff --git a/src/css/green-snake.css b/src/css/green-snake.css index 64cf1564..9cd114c5 100644 --- a/src/css/green-snake.css +++ b/src/css/green-snake.css @@ -4,140 +4,144 @@ By Patrick Gillespie http://patorjk.com/games/snake */ body { - margin:0px; - padding:0px; - background-color: darkgreen; + margin: 0px; + padding: 0px; + background-color: darkgreen; } .snake-toolbar { - background-color: rgba(255,255,255,0.4); - border-radius: 10px; + background-color: rgba(255, 255, 255, 0.4); + border-radius: 10px; } #game-area { - margin:10px; - padding:0px; - background-color: lightgreen; + margin: 10px; + padding: 0px; + background-color: lightgreen; } #mode-wrapper { - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; } -#game-area:focus { outline: none; } +#game-area:focus { + outline: none; +} -a.snake-link, a.snake-link:link, a.snake-link:visited { +a.snake-link, +a.snake-link:link, +a.snake-link:visited { color: black; } a.snake-link:hover { - color: #FfFf54; + color: #ffff54; } .snake-pause-screen { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position:absolute; - width:300px; - height:80px; - text-align:center; - top:50%; - left:50%; - margin-top:-40px; - margin-left:-150px; - display:none; - background-color:black; - color:white; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: black; + color: white; } .snake-panel-component { - position: absolute; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: black; - text-align: center; - background-color: white; - padding: 8px; - margin: 0px; + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: black; + text-align: center; + background-color: white; + padding: 8px; + margin: 0px; } .snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: #FF0000; - position: absolute; - border: 0px solid #000080; - background-repeat: no-repeat; + margin: 0px; + padding: 0px; + background-color: #ff0000; + position: absolute; + border: 0px solid #000080; + background-repeat: no-repeat; } .snake-snakebody-alive { - background-image: url('src/css/images/snakeblock.png'); + background-image: url("src/css/images/snakeblock.png"); } .snake-snakebody-dead { - background-image: url('src/css/images/deadblock.png'); + background-image: url("src/css/images/deadblock.png"); } .snake-food-block { - margin: 0px; - padding: 0px; - background-color: black; - border: 0px solid #000080; - position: absolute; + margin: 0px; + padding: 0px; + background-color: black; + border: 0px solid #000080; + position: absolute; } .snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: white; - border: 0px solid #0000A8; + margin: 0px; + padding: 0px; + position: absolute; + background-color: white; + border: 0px solid #0000a8; } .snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - background-color: #FC5454; - position: relative; + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + background-color: #fc5454; + position: relative; } .snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; -} - -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; +} + +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; } diff --git a/src/css/head-snake.css b/src/css/head-snake.css index e077a44a..0e7daf95 100644 --- a/src/css/head-snake.css +++ b/src/css/head-snake.css @@ -1,142 +1,148 @@ body { - margin:0px; - padding:0px; - background-color: rgb(0, 0, 0); + margin: 0px; + padding: 0px; + background-color: rgb(0, 0, 0); } #game-area { - margin:10px; - padding:0px; + margin: 10px; + padding: 0px; } #mode-wrapper { - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; } -#game-area:focus { outline: none; } +#game-area:focus { + outline: none; +} -a.snake-link, a.snake-link:link, a.snake-link:visited { - color: #FCFC54; +a.snake-link, +a.snake-link:link, +a.snake-link:visited { + color: #fcfc54; } a.snake-link:hover { - color: #FfFf54; + color: #ffff54; } .snake-pause-screen { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position:absolute; - width:300px; - height:80px; - text-align:center; - top:50%; - left:50%; - margin-top:-40px; - margin-left:-150px; - display:none; - background-color:black; - color:white; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: black; + color: white; } .snake-panel-component { - position: absolute; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; - text-align: center; - padding: 8px; - margin: 0px; + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; + text-align: center; + padding: 8px; + margin: 0px; } #snake-snakehead-alive { - background-image: url('src/css/images/green-head-snakeblock.png'); - margin: 0px; - padding: 0px; - background-color: rgb(10, 173, 10); - position: absolute; - border: 0px solid #000080; - background-repeat: no-repeat; - border-radius: 4px; + background-image: url("src/css/images/green-head-snakeblock.png"); + margin: 0px; + padding: 0px; + background-color: rgb(10, 173, 10); + position: absolute; + border: 0px solid #000080; + background-repeat: no-repeat; + border-radius: 4px; } .snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: #FF0000; - position: absolute; - border: 0px solid #000080; - background-repeat: no-repeat; + margin: 0px; + padding: 0px; + background-color: #ff0000; + position: absolute; + border: 0px solid #000080; + background-repeat: no-repeat; } .snake-snakebody-alive { - background-image: url('src/css/images/green-body-snakeblock.png'), url('src/css/images/green-body-snakeblock.png'); + background-image: url("src/css/images/green-body-snakeblock.png"), + url("src/css/images/green-body-snakeblock.png"); } .snake-snakebody-dead { - background-image: url('src/css/images/deadblock.png'), url('src/css/images/deadblock.png'); + background-image: url("src/css/images/deadblock.png"), + url("src/css/images/deadblock.png"); } .snake-food-block { - margin: 0px; - padding: 0px; - background-color: rgb(182, 11, 11); - border: 0px solid #000080; - position: absolute; - border-radius: 6px; + margin: 0px; + padding: 0px; + background-color: rgb(182, 11, 11); + border: 0px solid #000080; + position: absolute; + border-radius: 6px; } .snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: rgb(245, 245, 220); - border: 0px solid #0000A8; + margin: 0px; + padding: 0px; + position: absolute; + background-color: rgb(245, 245, 220); + border: 0px solid #0000a8; } .snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - position: relative; + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + position: relative; } .snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; -} - -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; +} + +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; } diff --git a/src/css/light-snake.css b/src/css/light-snake.css index 3829ee4e..db0be890 100644 --- a/src/css/light-snake.css +++ b/src/css/light-snake.css @@ -5,120 +5,123 @@ http://patorjk.com/games/snake */ body { - margin: 0px; - padding: 0px; - background-color: #f73378; + margin: 0px; + padding: 0px; + background-color: #f73378; } #game-area { - margin: 10px; - padding: 0px; + margin: 10px; + padding: 0px; } #mode-wrapper { - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; } #game-area:focus { - outline: none; + outline: none; } -a.snake-link, a.snake-link:link, a.snake-link:visited { - color: #FCFC54; +a.snake-link, +a.snake-link:link, +a.snake-link:visited { + color: #fcfc54; } a.snake-link:hover { - color: #FfFf54; + color: #ffff54; } .snake-pause-screen { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - width: 300px; - height: 80px; - text-align: center; - top: 50%; - left: 50%; - margin-top: -40px; - margin-left: -150px; - display: none; - background-color: black; - color: white; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: black; + color: white; } .snake-panel-component { - position: absolute; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; - text-align: center; - padding: 8px; - margin: 0px; + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; + text-align: center; + padding: 8px; + margin: 0px; } .snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: #FF0000; - position: absolute; - border: 0px solid #000080; - background-repeat: no-repeat; + margin: 0px; + padding: 0px; + background-color: #ff0000; + position: absolute; + border: 0px solid #000080; + background-repeat: no-repeat; } .snake-snakebody-alive { - background-image: url('src/css/images/snakeblock.png'); + background-image: url("src/css/images/snakeblock.png"); } .snake-snakebody-dead { - background-image: url('src/css/images/deadblock.png'); + background-image: url("src/css/images/deadblock.png"); } .snake-food-block { - margin: 0px; - padding: 0px; - background-color: #6cfd6a; - border: 0px solid #000080; - position: absolute; + margin: 0px; + padding: 0px; + background-color: #6cfd6a; + border: 0px solid #000080; + position: absolute; } .snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: #ab003c; - border: 0px solid #ab003c; + margin: 0px; + padding: 0px; + position: absolute; + background-color: #ab003c; + border: 0px solid #ab003c; } .snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - position: relative; + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + position: relative; } .snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; -} -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; +} +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; } diff --git a/src/css/main-snake.css b/src/css/main-snake.css index 5623c07e..7938bf34 100755 --- a/src/css/main-snake.css +++ b/src/css/main-snake.css @@ -4,132 +4,137 @@ By Patrick Gillespie http://patorjk.com/games/snake */ body { - margin:0px; - padding:0px; - background-color: #FC5454; + margin: 0px; + padding: 0px; + background-color: #fc5454; } #game-area { - margin:10px; - padding:0px; + margin: 10px; + padding: 0px; } #mode-wrapper { - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; } -#game-area:focus { outline: none; } +#game-area:focus { + outline: none; +} -a.snake-link, a.snake-link:link, a.snake-link:visited { - color: #FCFC54; +a.snake-link, +a.snake-link:link, +a.snake-link:visited { + color: #fcfc54; } a.snake-link:hover { - color: #FfFf54; + color: #ffff54; } .snake-pause-screen { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position:absolute; - width:300px; - height:80px; - text-align:center; - top:50%; - left:50%; - margin-top:-40px; - margin-left:-150px; - display:none; - background-color:black; - color:white; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: black; + color: white; } .snake-panel-component { - position: absolute; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; - text-align: center; - padding: 8px; - margin: 0px; + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; + text-align: center; + padding: 8px; + margin: 0px; } .snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: #FF0000; - position: absolute; - border: 0px solid #000080; - background-repeat: no-repeat; + margin: 0px; + padding: 0px; + background-color: #ff0000; + position: absolute; + border: 0px solid #000080; + background-repeat: no-repeat; } .snake-snakebody-alive { - background-image: url('./images/snakeblock.png'), url('./images/snakeblock.png'); + background-image: url("./images/snakeblock.png"), + url("./images/snakeblock.png"); } .snake-snakebody-dead { - background-image: url('./images/deadblock.png'), url('./images/deadblock.png'); + background-image: url("./images/deadblock.png"), url("./images/deadblock.png"); } .snake-food-block { - margin: 0px; - padding: 0px; - background-color: #FF0000; - border: 0px solid #000080; - position: absolute; + margin: 0px; + padding: 0px; + background-color: #ff0000; + border: 0px solid #000080; + position: absolute; } .snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: #0000A8; - border: 0px solid #0000A8; + margin: 0px; + padding: 0px; + position: absolute; + background-color: #0000a8; + border: 0px solid #0000a8; } .snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - position: relative; + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + position: relative; } .snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; } -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: #000000; - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: #000000; + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; } diff --git a/src/css/neon-snake.css b/src/css/neon-snake.css index 31b3291f..49591510 100644 --- a/src/css/neon-snake.css +++ b/src/css/neon-snake.css @@ -1,139 +1,145 @@ -/* -JavaScript Snake -By Patrick Gillespie -http://patorjk.com/games/snake -*/ -body { - margin:0px; - padding:0px; - background-color: #000000; -} - -.snake-toolbar { - color: #ffffff; -} - -#game-area { - margin:10px; - padding:0px; -} - -#mode-wrapper { - color: #ffffff; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - -} - -#game-area:focus { outline: none; } - -a.snake-link, a.snake-link:link, a.snake-link:visited { - color: #00FFE0; -} - -a.snake-link:hover { - color: #0FFF00; -} - -.snake-pause-screen { - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position:absolute; - width:300px; - height:80px; - text-align:center; - top:50%; - left:50%; - margin-top:-40px; - margin-left:-150px; - display:none; - background-color:#0FFF00; - color:#000000; -} - -.snake-panel-component { - position: absolute; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - color: #ffffff; - text-align: center; - padding: 8px; - margin: 0px; -} - -.snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: #FF0000; - position: absolute; - border: 0px solid #000080; - background-repeat: no-repeat; -} - -.snake-snakebody-alive { - background-image: url('src/css/images/neon-body-snakeblock.png'), url('src/cssss/images/neon-body-snakeblock.png'); -} -.snake-snakebody-dead { - background-image: url('src/css/images/neon-dead-snakeblock.png'), url('src/cssss/images/neon-dead-snakeblock.png'); -} - -.snake-food-block { - margin: 0px; - padding: 0px; - background-color: #FF0000; - border: 0px solid #000080; - position: absolute; -} - -.snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: #00FFD4; - border: 0px solid #0000A8; -} - -.snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - position: relative; -} - -.snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: #0FFF00; - color: #000000; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; -} - -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: #0FFF00; - color: #000000; - font-family: Verdana, arial, helvetica, sans-serif; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; -} +/* +JavaScript Snake +By Patrick Gillespie +http://patorjk.com/games/snake +*/ +body { + margin: 0px; + padding: 0px; + background-color: #000000; +} + +.snake-toolbar { + color: #ffffff; +} + +#game-area { + margin: 10px; + padding: 0px; +} + +#mode-wrapper { + color: #ffffff; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; +} + +#game-area:focus { + outline: none; +} + +a.snake-link, +a.snake-link:link, +a.snake-link:visited { + color: #00ffe0; +} + +a.snake-link:hover { + color: #0fff00; +} + +.snake-pause-screen { + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: #0fff00; + color: #000000; +} + +.snake-panel-component { + position: absolute; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + color: #ffffff; + text-align: center; + padding: 8px; + margin: 0px; +} + +.snake-snakebody-block { + margin: 0px; + padding: 0px; + background-color: #ff0000; + position: absolute; + border: 0px solid #000080; + background-repeat: no-repeat; +} + +.snake-snakebody-alive { + background-image: url("src/css/images/neon-body-snakeblock.png"), + url("src/cssss/images/neon-body-snakeblock.png"); +} +.snake-snakebody-dead { + background-image: url("src/css/images/neon-dead-snakeblock.png"), + url("src/cssss/images/neon-dead-snakeblock.png"); +} + +.snake-food-block { + margin: 0px; + padding: 0px; + background-color: #ff0000; + border: 0px solid #000080; + position: absolute; +} + +.snake-playing-field { + margin: 0px; + padding: 0px; + position: absolute; + background-color: #00ffd4; + border: 0px solid #0000a8; +} + +.snake-game-container { + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + position: relative; +} + +.snake-welcome-dialog { + padding: 8px; + margin: 0px; + background-color: #0fff00; + color: #000000; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; +} + +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: #0fff00; + color: #000000; + font-family: Verdana, arial, helvetica, sans-serif; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; +} diff --git a/src/css/teal-snake.css b/src/css/teal-snake.css index 8fbe6ffa..ac06471a 100644 --- a/src/css/teal-snake.css +++ b/src/css/teal-snake.css @@ -3,34 +3,37 @@ JavaScript Snake By Patrick Gillespie http://patorjk.com/games/snake */ -@import url('https://fonts.googleapis.com/css2?family=Electrolize&display=swap'); - +@import url("https://fonts.googleapis.com/css2?family=Electrolize&display=swap"); body { - margin:0px; - padding:0px; - background-color:teal; + margin: 0px; + padding: 0px; + background-color: teal; } .snake-toolbar { - font-family: Electrolize; - color: white; + font-family: Electrolize; + color: white; } #game-area { - margin:10px; - padding:0px; + margin: 10px; + padding: 0px; } -#game-area:focus { outline: none; } +#game-area:focus { + outline: none; +} #mode-wrapper { - font-family: Electrolize; - font-size: 14px; - color: whitesmoke; + font-family: Electrolize; + font-size: 14px; + color: whitesmoke; } -a.snake-link, a.snake-link:link, a.snake-link:visited { +a.snake-link, +a.snake-link:link, +a.snake-link:visited { color: white; } @@ -39,106 +42,107 @@ a.snake-link:hover { } .snake-pause-screen { - font-family: Electrolize; - font-size: 16px; - position:absolute; - width:300px; - height:80px; - text-align:center; - top:50%; - left:50%; - margin-top:-40px; - margin-left:-150px; - display:none; - background-color:#3E2E44; - color: whitesmoke; + font-family: Electrolize; + font-size: 16px; + position: absolute; + width: 300px; + height: 80px; + text-align: center; + top: 50%; + left: 50%; + margin-top: -40px; + margin-left: -150px; + display: none; + background-color: #3e2e44; + color: whitesmoke; } .snake-panel-component { - position: absolute; - font-family: Electrolize; - font-size: 16px; - color: #938996; - text-align: center; - background-color: #3E2E44; - padding: 8px; - margin: 0px; + position: absolute; + font-family: Electrolize; + font-size: 16px; + color: #938996; + text-align: center; + background-color: #3e2e44; + padding: 8px; + margin: 0px; } .snake-snakebody-block { - margin: 0px; - padding: 0px; - background-color: orange; - position: absolute; - border: 0px solid black; - background-repeat: no-repeat; + margin: 0px; + padding: 0px; + background-color: orange; + position: absolute; + border: 0px solid black; + background-repeat: no-repeat; } .snake-snakebody-alive { - background-image: url('src/css/images/snakeblock.png'); + background-image: url("src/css/images/snakeblock.png"); } .snake-snakebody-dead { - background-image: url('src/css/images/dead-dark-snakeblock.png'); + background-image: url("src/css/images/dead-dark-snakeblock.png"); } .snake-food-block { - margin: 0px; - padding: 0px; - background-color: red; - border: 2px solid black; - position: absolute; + margin: 0px; + padding: 0px; + background-color: red; + border: 2px solid black; + position: absolute; } .snake-playing-field { - margin: 0px; - padding: 0px; - position: absolute; - background-color: rgb(0, 180, 180); - border: 3px solid black; + margin: 0px; + padding: 0px; + position: absolute; + background-color: rgb(0, 180, 180); + border: 3px solid black; } .snake-game-container { - margin: 0px; - padding: 0px; - border-width: 0px; - border-style: none; - zoom: 1; - background-color: #3E2E44; - position: relative; + margin: 0px; + padding: 0px; + border-width: 0px; + border-style: none; + zoom: 1; + background-color: #3e2e44; + position: relative; } .snake-welcome-dialog { - padding: 8px; - margin: 0px; - background-color: black; - color: whitesmoke; - font-family: Electrolize; - font-size: 14px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - /*height: 150px;*/ - margin-top: -100px; - margin-left: -158px; - text-align: center; - display: block; -} - -.snake-try-again-dialog, .snake-win-dialog { - padding: 8px; - margin: 0px; - background-color: black; - color: whitesmoke; - font-family: Electrolize; - font-size: 16px; - position: absolute; - top: 50%; - left: 50%; - width: 300px; - height: 100px; - margin-top: -75px; - margin-left: -158px; - text-align: center; - display: none; + padding: 8px; + margin: 0px; + background-color: black; + color: whitesmoke; + font-family: Electrolize; + font-size: 14px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + /*height: 150px;*/ + margin-top: -100px; + margin-left: -158px; + text-align: center; + display: block; +} + +.snake-try-again-dialog, +.snake-win-dialog { + padding: 8px; + margin: 0px; + background-color: black; + color: whitesmoke; + font-family: Electrolize; + font-size: 16px; + position: absolute; + top: 50%; + left: 50%; + width: 300px; + height: 100px; + margin-top: -75px; + margin-left: -158px; + text-align: center; + display: none; } diff --git a/src/index.html b/src/index.html index 360fe818..d29237b0 100755 --- a/src/index.html +++ b/src/index.html @@ -1,154 +1,147 @@ - + - - - + --> + JavaScript Snake - + - + +
-
+
Theme:
-
+
Mode:
-
+ +
- -
-
+
-
-
+
- + + diff --git a/src/js/ai-init.js b/src/js/ai-init.js new file mode 100644 index 00000000..daddd8b8 --- /dev/null +++ b/src/js/ai-init.js @@ -0,0 +1,21 @@ +const mySnakeBoard = new SNAKE.Board({ + boardContainer: "game-area", + fullScreen: true, + premoveOnPause: false, + onLengthUpdate: (length) => { + console.log(`Length: ${length}`); + }, + onPauseToggle: (isPaused) => { + console.log(`Is paused: ${isPaused}`); + }, + onInit: (params) => { + console.log("init!"); + console.log(params); + }, + onWin: () => { + console.log("wn!"); + }, + onDeath: () => { + console.log("dead!"); + }, +}); diff --git a/src/js/init.js b/src/js/init.js index 045d093f..daddd8b8 100644 --- a/src/js/init.js +++ b/src/js/init.js @@ -1,5 +1,21 @@ const mySnakeBoard = new SNAKE.Board({ boardContainer: "game-area", fullScreen: true, - premoveOnPause: false -}); \ No newline at end of file + premoveOnPause: false, + onLengthUpdate: (length) => { + console.log(`Length: ${length}`); + }, + onPauseToggle: (isPaused) => { + console.log(`Is paused: ${isPaused}`); + }, + onInit: (params) => { + console.log("init!"); + console.log(params); + }, + onWin: () => { + console.log("wn!"); + }, + onDeath: () => { + console.log("dead!"); + }, +}); diff --git a/src/js/snake.js b/src/js/snake.js index 103a5bdb..2bfe6a79 100644 --- a/src/js/snake.js +++ b/src/js/snake.js @@ -29,6 +29,14 @@ const MOVE_RIGHT = 1; const MIN_SNAKE_SPEED = 25; const RUSH_INCR = 5; +const DEFAULT_SNAKE_SPEED = 80; + +const BOARD_NOT_READY = 0; +const BOARD_READY = 1; +const BOARD_IN_PLAY = 2; + +const HIGH_SCORE_KEY = "jsSnakeHighScore"; + /** * @method addEventListener * @param {Object} obj The object to add an event listener to. @@ -75,426 +83,468 @@ SNAKE.removeEventListener = (function () { * @namespace SNAKE * @param {Object} config The configuration object for the class. Contains playingBoard (the SNAKE.Board that this snake resides in), startRow and startCol. */ -SNAKE.Snake = SNAKE.Snake || (function () { - - // ------------------------------------------------------------------------- - // Private static variables and methods - // ------------------------------------------------------------------------- - - const blockPool = []; - - const SnakeBlock = function () { - this.elm = null; - this.elmStyle = null; - this.row = -1; - this.col = -1; - this.next = null; - this.prev = null; - }; - - // this function is adapted from the example at http://greengeckodesign.com/blog/2007/07/get-highest-z-index-in-javascript.html - function getNextHighestZIndex(myObj) { - let highestIndex = 0, - currentIndex = 0, - ii; - for (ii in myObj) { - if (myObj[ii].elm.currentStyle) { - currentIndex = parseFloat(myObj[ii].elm.style["z-index"], 10); - } else if (window.getComputedStyle) { - currentIndex = parseFloat(document.defaultView.getComputedStyle(myObj[ii].elm, null).getPropertyValue("z-index"), 10); - } - if (!isNaN(currentIndex) && currentIndex > highestIndex) { - highestIndex = currentIndex; +SNAKE.Snake = + SNAKE.Snake || + (function () { + // ------------------------------------------------------------------------- + // Private static variables and methods + // ------------------------------------------------------------------------- + + const blockPool = []; + + const SnakeBlock = function () { + this.elm = null; + this.elmStyle = null; + this.row = -1; + this.col = -1; + this.next = null; + this.prev = null; + }; + + // this function is adapted from the example at http://greengeckodesign.com/blog/2007/07/get-highest-z-index-in-javascript.html + function getNextHighestZIndex(myObj) { + let highestIndex = 0, + currentIndex = 0, + ii; + for (ii in myObj) { + if (myObj[ii].elm.currentStyle) { + currentIndex = parseFloat(myObj[ii].elm.style["z-index"], 10); + } else if (window.getComputedStyle) { + currentIndex = parseFloat( + document.defaultView + .getComputedStyle(myObj[ii].elm, null) + .getPropertyValue("z-index"), + 10, + ); + } + if (!isNaN(currentIndex) && currentIndex > highestIndex) { + highestIndex = currentIndex; + } } + return highestIndex + 1; } - return (highestIndex + 1); - } - // ------------------------------------------------------------------------- - // Contructor + public and private definitions - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- + // Contructor + public and private definitions + // ------------------------------------------------------------------------- - /* + /* config options: playingBoard - the SnakeBoard that this snake belongs too. startRow - The row the snake should start on. startCol - The column the snake should start on. + moveSnakeWithAI - function to move the snake with AI */ - return function (config) { + return function (config) { + if (!config || !config.playingBoard) { + return; + } + if (localStorage[HIGH_SCORE_KEY] === undefined) + localStorage.setItem(HIGH_SCORE_KEY, 0); + + // ----- private variables ----- + + const me = this; + const playingBoard = config.playingBoard; + const growthIncr = 5; + const columnShift = [0, 1, 0, -1]; + const rowShift = [-1, 0, 1, 0]; + + let lastMove = 1, + preMove = MOVE_NONE, + isFirstGameMove = true, + currentDirection = MOVE_NONE, // 0: up, 1: left, 2: down, 3: right + snakeSpeed = DEFAULT_SNAKE_SPEED, + isDead = false, + isPaused = false; + + const modeDropdown = document.getElementById("selectMode"); + if (modeDropdown) { + modeDropdown.addEventListener("change", function (evt) { + evt = evt || {}; + let val = evt.target + ? parseInt(evt.target.value) + : DEFAULT_SNAKE_SPEED; + + if (isNaN(val)) { + val = DEFAULT_SNAKE_SPEED; + } else if (val < MIN_SNAKE_SPEED) { + val = DEFAULT_SNAKE_SPEED; + } - if (!config || !config.playingBoard) { - return; - } - if (localStorage.jsSnakeHighScore === undefined) localStorage.setItem('jsSnakeHighScore', 0); - - // ----- private variables ----- - - const me = this; - const playingBoard = config.playingBoard; - const growthIncr = 5; - const columnShift = [0, 1, 0, -1]; - const rowShift = [-1, 0, 1, 0]; - - let lastMove = 1, - preMove = MOVE_NONE, - isFirstMove = true, - isFirstGameMove = true, - currentDirection = MOVE_NONE, // 0: up, 1: left, 2: down, 3: right - snakeSpeed = 80, - isDead = false, - isPaused = false; - - const modeDropdown = document.getElementById('selectMode'); - if (modeDropdown) { - modeDropdown.addEventListener('change', function (evt) { - evt = evt || {}; - let val = evt.target ? parseInt(evt.target.value) : 75; - - if (isNaN(val)) { - val = 75; - } else if (val < MIN_SNAKE_SPEED) { - val = 75 - } + snakeSpeed = val; - snakeSpeed = val; + setTimeout(function () { + document.getElementById("game-area").focus(); + }, 10); + }); + } - setTimeout(function () { - document.getElementById('game-area').focus(); - }, 10); - }); - } + // ----- public variables ----- + me.snakeBody = {}; + me.snakeBody["b0"] = new SnakeBlock(); // create snake head + me.snakeBody["b0"].row = config.startRow || 1; + me.snakeBody["b0"].col = config.startCol || 1; + me.snakeBody["b0"].elm = createSnakeElement(); + me.snakeBody["b0"].elmStyle = me.snakeBody["b0"].elm.style; + playingBoard.getBoardContainer().appendChild(me.snakeBody["b0"].elm); + me.snakeBody["b0"].elm.style.left = getLeftPosition(me.snakeBody["b0"]); + me.snakeBody["b0"].elm.style.top = getTopPosition(me.snakeBody["b0"]); + me.snakeBody["b0"].next = me.snakeBody["b0"]; + me.snakeBody["b0"].prev = me.snakeBody["b0"]; - // ----- public variables ----- - me.snakeBody = {}; - me.snakeBody["b0"] = new SnakeBlock(); // create snake head - me.snakeBody["b0"].row = config.startRow || 1; - me.snakeBody["b0"].col = config.startCol || 1; - me.snakeBody["b0"].elm = createSnakeElement(); - me.snakeBody["b0"].elmStyle = me.snakeBody["b0"].elm.style; - playingBoard.getBoardContainer().appendChild(me.snakeBody["b0"].elm); - me.snakeBody["b0"].elm.style.left = getLeftPosition(me.snakeBody["b0"]); - me.snakeBody["b0"].elm.style.top = getTopPosition(me.snakeBody["b0"]); - me.snakeBody["b0"].next = me.snakeBody["b0"]; - me.snakeBody["b0"].prev = me.snakeBody["b0"]; - - me.snakeLength = 1; - me.snakeHead = me.snakeBody["b0"]; - me.snakeTail = me.snakeBody["b0"]; - me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/, ''); - me.snakeHead.elm.id = "snake-snakehead-alive"; - me.snakeHead.elm.className += " snake-snakebody-alive"; - - // ----- private methods ----- - - function getTopPosition(block) { - const num = block.row * playingBoard.getBlockHeight() - return `${num}px`; - } - function getLeftPosition(block) { - const num = block.col * playingBoard.getBlockWidth() - return `${num}px`; - } + me.snakeLength = 1; + me.snakeHead = me.snakeBody["b0"]; + me.snakeTail = me.snakeBody["b0"]; + me.snakeHead.elm.className = me.snakeHead.elm.className.replace( + /\bsnake-snakebody-dead\b/, + "", + ); + me.snakeHead.elm.id = "snake-snakehead-alive"; + me.snakeHead.elm.className += " snake-snakebody-alive"; - function createSnakeElement() { - const tempNode = document.createElement("div"); - tempNode.className = "snake-snakebody-block"; - tempNode.style.left = "-1000px"; - tempNode.style.top = "-1000px"; - tempNode.style.width = playingBoard.getBlockWidth() + "px"; - tempNode.style.height = playingBoard.getBlockHeight() + "px"; - return tempNode; - } + // ----- private methods ----- - function createBlocks(num) { - let tempBlock; - const tempNode = createSnakeElement(); + function getTopPosition(block) { + const num = block.row * playingBoard.getBlockHeight(); + return `${num}px`; + } + + function getLeftPosition(block) { + const num = block.col * playingBoard.getBlockWidth(); + return `${num}px`; + } + + function createSnakeElement() { + const tempNode = document.createElement("div"); + tempNode.className = "snake-snakebody-block"; + tempNode.style.left = "-1000px"; + tempNode.style.top = "-1000px"; + tempNode.style.width = playingBoard.getBlockWidth() + "px"; + tempNode.style.height = playingBoard.getBlockHeight() + "px"; + return tempNode; + } + + function createBlocks(num) { + let tempBlock; + const tempNode = createSnakeElement(); + + for (let ii = 1; ii < num; ii++) { + tempBlock = new SnakeBlock(); + tempBlock.elm = tempNode.cloneNode(true); + tempBlock.elmStyle = tempBlock.elm.style; + playingBoard.getBoardContainer().appendChild(tempBlock.elm); + blockPool[blockPool.length] = tempBlock; + } - for (let ii = 1; ii < num; ii++) { tempBlock = new SnakeBlock(); - tempBlock.elm = tempNode.cloneNode(true); - tempBlock.elmStyle = tempBlock.elm.style; + tempBlock.elm = tempNode; playingBoard.getBoardContainer().appendChild(tempBlock.elm); blockPool[blockPool.length] = tempBlock; } - tempBlock = new SnakeBlock(); - tempBlock.elm = tempNode; - playingBoard.getBoardContainer().appendChild(tempBlock.elm); - blockPool[blockPool.length] = tempBlock; - } - - function recordScore() { - const highScore = localStorage.jsSnakeHighScore; - if (me.snakeLength > highScore) { - alert('Congratulations! You have beaten your previous high score, which was ' + highScore + '.'); - localStorage.setItem('jsSnakeHighScore', me.snakeLength); + function recordScore() { + const highScore = localStorage[HIGH_SCORE_KEY]; + if (me.snakeLength > highScore) { + alert( + "Congratulations! You have beaten your previous high score, which was " + + highScore + + ".", + ); + localStorage.setItem(HIGH_SCORE_KEY, me.snakeLength); + } } - } - function handleEndCondition(handleFunc) { - recordScore(); - me.snakeHead.elm.style.zIndex = getNextHighestZIndex(me.snakeBody); - me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/, '') - me.snakeHead.elm.className += " snake-snakebody-dead"; - - isDead = true; - handleFunc(); - } + function handleEndCondition(handleFunc) { + recordScore(); + me.snakeHead.elm.style.zIndex = getNextHighestZIndex(me.snakeBody); + me.snakeHead.elm.className = me.snakeHead.elm.className.replace( + /\bsnake-snakebody-alive\b/, + "", + ); + me.snakeHead.elm.className += " snake-snakebody-dead"; + + isDead = true; + handleFunc(); + } - // ----- public methods ----- + // ----- public methods ----- - me.setPaused = function (val) { - isPaused = val; - }; - me.getPaused = function () { - return isPaused; - }; + me.setPaused = function (val) { + isPaused = val; + }; + me.getPaused = function () { + return isPaused; + }; - /** - * This method is called when a user presses a key. It logs arrow key presses in "currentDirection", which is used when the snake needs to make its next move. - * @method handleArrowKeys - * @param {Number} keyNum A number representing the key that was pressed. - */ - /* + /** + * This method is called when a user presses a key. It logs arrow key presses in "currentDirection", which is used when the snake needs to make its next move. + * @method handleArrowKeys + * @param {Number} keyNum A number representing the key that was pressed. + */ + /* Handles what happens when an arrow key is pressed. Direction explained (0 = up, etc etc) 0 3 1 2 */ - me.handleArrowKeys = function (keyNum) { - if (isDead || (isPaused && !config.premoveOnPause)) { - return; - } - - let directionFound = MOVE_NONE; - - switch (keyNum) { - case 37: - case 65: - directionFound = MOVE_LEFT; - break; - case 38: - case 87: - directionFound = MOVE_UP; - break; - case 39: - case 68: - directionFound = MOVE_RIGHT; - break; - case 40: - case 83: - directionFound = MOVE_DOWN; - break; - } - if (currentDirection !== lastMove) // Allow a queue of 1 premove so you can turn again before the first turn registers - { - preMove = directionFound; - } - if (Math.abs(directionFound - lastMove) !== 2 && (isFirstMove || isPaused) || isFirstGameMove) // Prevent snake from turning 180 degrees - { - currentDirection = directionFound; - isFirstMove = false; - isFirstGameMove = false; - } - }; - - /** - * This method is executed for each move of the snake. It determines where the snake will go and what will happen to it. This method needs to run quickly. - * @method go - */ - me.go = function () { + me.handleArrowKeys = function (keyNum) { + if (isDead || (isPaused && !config.premoveOnPause)) { + return; + } - const oldHead = me.snakeHead, - newHead = me.snakeTail, - grid = playingBoard.grid; // cache grid for quicker lookup + let directionFound = MOVE_NONE; + + switch (keyNum) { + case 37: + case 65: + directionFound = MOVE_LEFT; + break; + case 38: + case 87: + directionFound = MOVE_UP; + break; + case 39: + case 68: + directionFound = MOVE_RIGHT; + break; + case 40: + case 83: + directionFound = MOVE_DOWN; + break; + } + if (currentDirection !== lastMove) { + // Allow a queue of 1 premove so you can turn again before the first turn registers + preMove = directionFound; + } + if (Math.abs(directionFound - lastMove) !== 2 || isFirstGameMove) { + // Prevent snake from turning 180 degrees + currentDirection = directionFound; + isFirstGameMove = false; + } + }; - if (isPaused === true) { - setTimeout(function () { - me.go(); - }, snakeSpeed); - return; - } + /** + * This method is executed for each move of the snake. It determines where the snake will go and what will happen to it. This method needs to run quickly. + * @method go + */ + me.go = function () { + const oldHead = me.snakeHead, + newHead = me.snakeTail, + grid = playingBoard.grid; // cache grid for quicker lookup + + if (isPaused === true) { + setTimeout(function () { + me.go(); + }, snakeSpeed); + return; + } - me.snakeTail = newHead.prev; - me.snakeHead = newHead; + // code to execute if snake is being moved by AI + if (config.moveSnakeWithAI) { + config.moveSnakeWithAI({ + grid, + snakeHead: me.snakeHead, + currentDirection, + isFirstGameMove, + setDirection: me.setDirection, + }); + } - // clear the old board position - if (grid[newHead.row] && grid[newHead.row][newHead.col]) { - grid[newHead.row][newHead.col] = 0; - } + me.snakeTail = newHead.prev; + me.snakeHead = newHead; - if (currentDirection !== MOVE_NONE) { - lastMove = currentDirection; - if (preMove !== MOVE_NONE) // If the user queued up another move after the current one - { - currentDirection = preMove; // Execute that move next time (unless overwritten) - preMove = MOVE_NONE; + // clear the old board position + if (grid[newHead.row] && grid[newHead.row][newHead.col]) { + grid[newHead.row][newHead.col] = 0; } - } - isFirstMove = true; - newHead.col = oldHead.col + columnShift[lastMove]; - newHead.row = oldHead.row + rowShift[lastMove]; - - if (!newHead.elmStyle) { - newHead.elmStyle = newHead.elm.style; - } + if (currentDirection !== MOVE_NONE) { + lastMove = currentDirection; + if (preMove !== MOVE_NONE) { + // If the user queued up another move after the current one + currentDirection = preMove; // Execute that move next time (unless overwritten) + preMove = MOVE_NONE; + } + } - newHead.elmStyle.left = getLeftPosition(newHead); - newHead.elmStyle.top = getTopPosition(newHead); - if (me.snakeLength > 1) { - newHead.elm.id = "snake-snakehead-alive"; - oldHead.elm.id = ""; - } + newHead.col = oldHead.col + columnShift[lastMove]; + newHead.row = oldHead.row + rowShift[lastMove]; + if (!newHead.elmStyle) { + newHead.elmStyle = newHead.elm.style; + } - // check the new spot the snake moved into + newHead.elmStyle.left = getLeftPosition(newHead); + newHead.elmStyle.top = getTopPosition(newHead); + if (me.snakeLength > 1) { + newHead.elm.id = "snake-snakehead-alive"; + oldHead.elm.id = ""; + } - if (grid[newHead.row][newHead.col] === 0) { - grid[newHead.row][newHead.col] = 1; - setTimeout(function () { - me.go(); - }, snakeSpeed); - } else if (grid[newHead.row][newHead.col] > 0) { - me.handleDeath(); - } else if (grid[newHead.row][newHead.col] === playingBoard.getGridFoodValue()) { - grid[newHead.row][newHead.col] = 1; - if (!me.eatFood()) { - me.handleWin(); - return; + // check the new spot the snake moved into + + if (grid[newHead.row][newHead.col] === 0) { + grid[newHead.row][newHead.col] = 1; + setTimeout(function () { + me.go(); + }, snakeSpeed); + } else if (grid[newHead.row][newHead.col] > 0) { + me.handleDeath(); + } else if ( + grid[newHead.row][newHead.col] === playingBoard.getGridFoodValue() + ) { + grid[newHead.row][newHead.col] = 1; + if (!me.eatFood()) { + me.handleWin(); + return; + } + setTimeout(function () { + me.go(); + }, snakeSpeed); } - setTimeout(function () { - me.go(); - }, snakeSpeed); - } - }; + }; - /** - * This method is called when it is determined that the snake has eaten some food. - * @method eatFood - * @return {bool} Whether a new food was able to spawn (true) - * or not (false) after the snake eats food. - */ - me.eatFood = function () { - if (blockPool.length <= growthIncr) { - createBlocks(growthIncr * 2); - } - const blocks = blockPool.splice(0, growthIncr); - - let ii = blocks.length, - index; - prevNode = me.snakeTail; - while (ii--) { - index = "b" + me.snakeLength++; - me.snakeBody[index] = blocks[ii]; - me.snakeBody[index].prev = prevNode; - me.snakeBody[index].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/, '') - me.snakeBody[index].elm.className += " snake-snakebody-alive"; - prevNode.next = me.snakeBody[index]; - prevNode = me.snakeBody[index]; - } - me.snakeTail = me.snakeBody[index]; - me.snakeTail.next = me.snakeHead; - me.snakeHead.prev = me.snakeTail; + /** + * This method is called when it is determined that the snake has eaten some food. + * @method eatFood + * @return {bool} Whether a new food was able to spawn (true) + * or not (false) after the snake eats food. + */ + me.eatFood = function () { + if (blockPool.length <= growthIncr) { + createBlocks(growthIncr * 2); + } + const blocks = blockPool.splice(0, growthIncr); + + let ii = blocks.length, + index; + prevNode = me.snakeTail; + while (ii--) { + index = "b" + me.snakeLength++; + me.snakeBody[index] = blocks[ii]; + me.snakeBody[index].prev = prevNode; + me.snakeBody[index].elm.className = + me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/, ""); + me.snakeBody[index].elm.className += " snake-snakebody-alive"; + prevNode.next = me.snakeBody[index]; + prevNode = me.snakeBody[index]; + } + me.snakeTail = me.snakeBody[index]; + me.snakeTail.next = me.snakeHead; + me.snakeHead.prev = me.snakeTail; - if (!playingBoard.foodEaten()) { - return false; - } + if (!playingBoard.foodEaten()) { + return false; + } - //Checks if the current selected option is that of "Rush" - //If so, "increase" the snake speed - const selectDropDown = document.getElementById("selectMode"); - const selectedOption = selectDropDown.options[selectDropDown.selectedIndex]; + //Checks if the current selected option is that of "Rush" + //If so, "increase" the snake speed + const selectDropDown = document.getElementById("selectMode"); + const selectedOption = + selectDropDown.options[selectDropDown.selectedIndex]; - if (selectedOption.text.localeCompare("Rush") == 0) { - if (snakeSpeed > (MIN_SNAKE_SPEED + RUSH_INCR)) { - snakeSpeed -= RUSH_INCR; + if (selectedOption.text.localeCompare("Rush") == 0) { + if (snakeSpeed > MIN_SNAKE_SPEED + RUSH_INCR) { + snakeSpeed -= RUSH_INCR; + } } - } - return true; - }; + return true; + }; - /** - * This method handles what happens when the snake dies. - * @method handleDeath - */ - me.handleDeath = function () { - //Reset speed - const selectedSpeed = document.getElementById("selectMode").value; - snakeSpeed = parseInt(selectedSpeed); + /** + * This method handles what happens when the snake dies. + * @method handleDeath + */ + me.handleDeath = function () { + //Reset speed + const selectedSpeed = document.getElementById("selectMode").value; + snakeSpeed = parseInt(selectedSpeed); - handleEndCondition(playingBoard.handleDeath); - }; + handleEndCondition(playingBoard.handleDeath); + }; - /** - * This method handles what happens when the snake wins. - * @method handleDeath - */ - me.handleWin = function () { - handleEndCondition(playingBoard.handleWin); - }; + /** + * This method handles what happens when the snake wins. + * @method handleDeath + */ + me.handleWin = function () { + handleEndCondition(playingBoard.handleWin); + }; - /** - * This method sets a flag that lets the snake be alive again. - * @method rebirth - */ - me.rebirth = function () { - isDead = false; - isFirstMove = true; - isFirstGameMove = true; - preMove = MOVE_NONE; - }; + /** + * This method sets a flag that lets the snake be alive again. + * @method rebirth + */ + me.rebirth = function () { + isDead = false; + isFirstGameMove = true; + preMove = MOVE_NONE; + }; - /** - * This method reset the snake so it is ready for a new game. - * @method reset - */ - me.reset = function () { - if (isDead === false) { - return; - } + /** + * This method reset the snake so it is ready for a new game. + * @method reset + */ + me.reset = function () { + if (isDead === false) { + return; + } - const blocks = []; - let curNode = me.snakeHead.next; - let nextNode; + const blocks = []; + let curNode = me.snakeHead.next; + let nextNode; - while (curNode !== me.snakeHead) { - nextNode = curNode.next; - curNode.prev = null; - curNode.next = null; - blocks.push(curNode); - curNode = nextNode; - } - me.snakeHead.next = me.snakeHead; - me.snakeHead.prev = me.snakeHead; - me.snakeTail = me.snakeHead; - me.snakeLength = 1; + while (curNode !== me.snakeHead) { + nextNode = curNode.next; + curNode.prev = null; + curNode.next = null; + blocks.push(curNode); + curNode = nextNode; + } + me.snakeHead.next = me.snakeHead; + me.snakeHead.prev = me.snakeHead; + me.snakeTail = me.snakeHead; + me.snakeLength = 1; + + for (let ii = 0; ii < blocks.length; ii++) { + blocks[ii].elm.style.left = "-1000px"; + blocks[ii].elm.style.top = "-1000px"; + blocks[ii].elm.className = me.snakeHead.elm.className.replace( + /\bsnake-snakebody-dead\b/, + "", + ); + blocks[ii].elm.className += " snake-snakebody-alive"; + } - for (let ii = 0; ii < blocks.length; ii++) { - blocks[ii].elm.style.left = "-1000px"; - blocks[ii].elm.style.top = "-1000px"; - blocks[ii].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/, '') - blocks[ii].elm.className += " snake-snakebody-alive"; - } + blockPool.concat(blocks); + me.snakeHead.elm.className = me.snakeHead.elm.className.replace( + /\bsnake-snakebody-dead\b/, + "", + ); + me.snakeHead.elm.className += " snake-snakebody-alive"; + me.snakeHead.elm.id = "snake-snakehead-alive"; + me.snakeHead.row = config.startRow || 1; + me.snakeHead.col = config.startCol || 1; + me.snakeHead.elm.style.left = getLeftPosition(me.snakeHead); + me.snakeHead.elm.style.top = getTopPosition(me.snakeHead); + }; - blockPool.concat(blocks); - me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/, '') - me.snakeHead.elm.className += " snake-snakebody-alive"; - me.snakeHead.elm.id = "snake-snakehead-alive"; - me.snakeHead.row = config.startRow || 1; - me.snakeHead.col = config.startCol || 1; - me.snakeHead.elm.style.left = getLeftPosition(me.snakeHead); - me.snakeHead.elm.style.top = getTopPosition(me.snakeHead); - }; + me.getSpeed = () => { + return snakeSpeed; + }; + me.setSpeed = (speed) => { + snakeSpeed = speed; + }; - // --------------------------------------------------------------------- - // Initialize - // --------------------------------------------------------------------- - createBlocks(growthIncr * 2); - }; -})(); + // --------------------------------------------------------------------- + // Initialize + // --------------------------------------------------------------------- + createBlocks(growthIncr * 2); + }; + })(); /** * This class manages the food which the snake will eat. @@ -504,96 +554,101 @@ SNAKE.Snake = SNAKE.Snake || (function () { * @param {Object} config The configuration object for the class. Contains playingBoard (the SNAKE.Board that this food resides in). */ -SNAKE.Food = SNAKE.Food || (function () { - - // ------------------------------------------------------------------------- - // Private static variables and methods - // ------------------------------------------------------------------------- +SNAKE.Food = + SNAKE.Food || + (function () { + // ------------------------------------------------------------------------- + // Private static variables and methods + // ------------------------------------------------------------------------- - let instanceNumber = 0; + let instanceNumber = 0; - function getRandomPosition(x, y) { - return Math.floor(Math.random() * (y + 1 - x)) + x; - } + function getRandomPosition(x, y) { + return Math.floor(Math.random() * (y + 1 - x)) + x; + } - // ------------------------------------------------------------------------- - // Contructor + public and private definitions - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- + // Contructor + public and private definitions + // ------------------------------------------------------------------------- - /* + /* config options: playingBoard - the SnakeBoard that this object belongs too. */ - return function (config) { - - if (!config || !config.playingBoard) { - return; - } + return function (config) { + if (!config || !config.playingBoard) { + return; + } - // ----- private variables ----- - - const me = this; - const playingBoard = config.playingBoard; - let fRow, fColumn; - const myId = instanceNumber++; - - const elmFood = document.createElement("div"); - elmFood.setAttribute("id", "snake-food-" + myId); - elmFood.className = "snake-food-block"; - elmFood.style.width = playingBoard.getBlockWidth() + "px"; - elmFood.style.height = playingBoard.getBlockHeight() + "px"; - elmFood.style.left = "-1000px"; - elmFood.style.top = "-1000px"; - playingBoard.getBoardContainer().appendChild(elmFood); - - // ----- public methods ----- - - /** - * @method getFoodElement - * @return {DOM Element} The div the represents the food. - */ - me.getFoodElement = function () { - return elmFood; - }; + // ----- private variables ----- + + const me = this; + const playingBoard = config.playingBoard; + let fRow, fColumn; + const myId = instanceNumber++; + + const elmFood = document.createElement("div"); + elmFood.setAttribute("id", "snake-food-" + myId); + elmFood.className = "snake-food-block"; + elmFood.style.width = playingBoard.getBlockWidth() + "px"; + elmFood.style.height = playingBoard.getBlockHeight() + "px"; + elmFood.style.left = "-1000px"; + elmFood.style.top = "-1000px"; + playingBoard.getBoardContainer().appendChild(elmFood); + + // ----- public methods ----- + + /** + * @method getFoodElement + * @return {DOM Element} The div the represents the food. + */ + me.getFoodElement = function () { + return elmFood; + }; - /** - * Randomly places the food onto an available location on the playing board. - * @method randomlyPlaceFood - * @return {bool} Whether a food was able to spawn (true) or not (false). - */ - me.randomlyPlaceFood = function () { - // if there exist some food, clear its presence from the board - if (playingBoard.grid[fRow] && playingBoard.grid[fRow][fColumn] === playingBoard.getGridFoodValue()) { - playingBoard.grid[fRow][fColumn] = 0; - } + /** + * Randomly places the food onto an available location on the playing board. + * @method randomlyPlaceFood + * @return {bool} Whether a food was able to spawn (true) or not (false). + */ + me.randomlyPlaceFood = function () { + // if there exist some food, clear its presence from the board + if ( + playingBoard.grid[fRow] && + playingBoard.grid[fRow][fColumn] === playingBoard.getGridFoodValue() + ) { + playingBoard.grid[fRow][fColumn] = 0; + } - let row = 0, col = 0, numTries = 0; + let row = 0, + col = 0, + numTries = 0; - const maxRows = playingBoard.grid.length - 1; - const maxCols = playingBoard.grid[0].length - 1; + const maxRows = playingBoard.grid.length - 1; + const maxCols = playingBoard.grid[0].length - 1; - while (playingBoard.grid[row][col] !== 0) { - row = getRandomPosition(1, maxRows); - col = getRandomPosition(1, maxCols); + while (playingBoard.grid[row][col] !== 0) { + row = getRandomPosition(1, maxRows); + col = getRandomPosition(1, maxCols); - // in some cases there may not be any room to put food anywhere - // instead of freezing, exit out (and return false to indicate - // that the player beat the game) - numTries++; - if (numTries > 20000) { - return false; + // in some cases there may not be any room to put food anywhere + // instead of freezing, exit out (and return false to indicate + // that the player beat the game) + numTries++; + if (numTries > 20000) { + return false; + } } - } - playingBoard.grid[row][col] = playingBoard.getGridFoodValue(); - fRow = row; - fColumn = col; - elmFood.style.top = row * playingBoard.getBlockHeight() + "px"; - elmFood.style.left = col * playingBoard.getBlockWidth() + "px"; - return true; + playingBoard.grid[row][col] = playingBoard.getGridFoodValue(); + fRow = row; + fColumn = col; + elmFood.style.top = row * playingBoard.getBlockHeight() + "px"; + elmFood.style.left = col * playingBoard.getBlockWidth() + "px"; + return true; + }; }; - }; -})(); + })(); /** * This class manages playing board for the game. @@ -603,557 +658,733 @@ SNAKE.Food = SNAKE.Food || (function () { * @param {Object} config The configuration object for the class. Set fullScreen equal to true if you want the game to take up the full screen, otherwise, set the top, left, width and height parameters. */ -SNAKE.Board = SNAKE.Board || (function () { - - // ------------------------------------------------------------------------- - // Private static variables and methods - // ------------------------------------------------------------------------- - - let instanceNumber = 0; - - // this function is adapted from the example at http://greengeckodesign.com/blog/2007/07/get-highest-z-index-in-javascript.html - function getNextHighestZIndex(myObj) { - let highestIndex = 0, - currentIndex = 0, - ii; - for (ii in myObj) { - if (myObj[ii].elm.currentStyle) { - currentIndex = parseFloat(myObj[ii].elm.style["z-index"], 10); - } else if (window.getComputedStyle) { - currentIndex = parseFloat(document.defaultView.getComputedStyle(myObj[ii].elm, null).getPropertyValue("z-index"), 10); - } - if (!isNaN(currentIndex) && currentIndex > highestIndex) { - highestIndex = currentIndex; +SNAKE.Board = + SNAKE.Board || + (function () { + // ------------------------------------------------------------------------- + // Private static variables and methods + // ------------------------------------------------------------------------- + + let instanceNumber = 0; + + // this function is adapted from the example at http://greengeckodesign.com/blog/2007/07/get-highest-z-index-in-javascript.html + function getNextHighestZIndex(myObj) { + let highestIndex = 0, + currentIndex = 0, + ii; + for (ii in myObj) { + if (myObj[ii].elm.currentStyle) { + currentIndex = parseFloat(myObj[ii].elm.style["z-index"], 10); + } else if (window.getComputedStyle) { + currentIndex = parseFloat( + document.defaultView + .getComputedStyle(myObj[ii].elm, null) + .getPropertyValue("z-index"), + 10, + ); + } + if (!isNaN(currentIndex) && currentIndex > highestIndex) { + highestIndex = currentIndex; + } } + return highestIndex + 1; } - return (highestIndex + 1); - } - /* + /* This function returns the width of the available screen real estate that we have */ - function getClientWidth() { - let myWidth = 0; - if (typeof window.innerWidth === "number") { - myWidth = window.innerWidth;//Non-IE - } else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) { - myWidth = document.documentElement.clientWidth;//IE 6+ in 'standards compliant mode' - } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) { - myWidth = document.body.clientWidth;//IE 4 compatible + function getClientWidth() { + let myWidth = 0; + if (typeof window.innerWidth === "number") { + myWidth = window.innerWidth; //Non-IE + } else if ( + document.documentElement && + (document.documentElement.clientWidth || + document.documentElement.clientHeight) + ) { + myWidth = document.documentElement.clientWidth; //IE 6+ in 'standards compliant mode' + } else if ( + document.body && + (document.body.clientWidth || document.body.clientHeight) + ) { + myWidth = document.body.clientWidth; //IE 4 compatible + } + return myWidth; } - return myWidth; - } - /* + /* This function returns the height of the available screen real estate that we have */ - function getClientHeight() { - let myHeight = 0; - if (typeof window.innerHeight === "number") { - myHeight = window.innerHeight;//Non-IE - } else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) { - myHeight = document.documentElement.clientHeight;//IE 6+ in 'standards compliant mode' - } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) { - myHeight = document.body.clientHeight;//IE 4 compatible + function getClientHeight() { + let myHeight = 0; + if (typeof window.innerHeight === "number") { + myHeight = window.innerHeight; //Non-IE + } else if ( + document.documentElement && + (document.documentElement.clientWidth || + document.documentElement.clientHeight) + ) { + myHeight = document.documentElement.clientHeight; //IE 6+ in 'standards compliant mode' + } else if ( + document.body && + (document.body.clientWidth || document.body.clientHeight) + ) { + myHeight = document.body.clientHeight; //IE 4 compatible + } + return myHeight; } - return myHeight; - } - - // ------------------------------------------------------------------------- - // Contructor + public and private definitions - // ------------------------------------------------------------------------- - - return function (inputConfig) { - - // --- private variables --- - const me = this; - const myId = instanceNumber++; - const config = inputConfig || {}; - const MAX_BOARD_COLS = 250; - const MAX_BOARD_ROWS = 250; - const blockWidth = 20; - const blockHeight = 20; - const GRID_FOOD_VALUE = -1; // the value of a spot on the board that represents snake food; MUST BE NEGATIVE - - let myFood, - mySnake, - boardState = 1, // 0: in active, 1: awaiting game start, 2: playing game - myKeyListener, - myWindowListener, - isPaused = false;//note: both the board and the snake can be paused - - // Board components - let elmContainer, - elmPlayingField, - elmAboutPanel, - elmLengthPanel, - elmHighscorePanel, - elmWelcome, - elmTryAgain, - elmWin, - elmPauseScreen; - - // --- public variables --- - me.grid = []; - - // --------------------------------------------------------------------- - // private functions - // --------------------------------------------------------------------- - - function createBoardElements() { - elmPlayingField = document.createElement("div"); - elmPlayingField.setAttribute("id", "playingField"); - elmPlayingField.className = "snake-playing-field"; - - SNAKE.addEventListener(elmPlayingField, "click", function () { - elmContainer.focus(); - }, false); - - elmPauseScreen = document.createElement("div"); - elmPauseScreen.className = "snake-pause-screen"; - elmPauseScreen.innerHTML = "
[Paused]

Press [space] to unpause.

"; - - elmAboutPanel = document.createElement("div"); - elmAboutPanel.className = "snake-panel-component"; - elmAboutPanel.innerHTML = "more patorjk.com apps - source code - pat's youtube"; - - elmLengthPanel = document.createElement("div"); - elmLengthPanel.className = "snake-panel-component"; - elmLengthPanel.innerHTML = "Length: 1"; - - elmHighscorePanel = document.createElement("div"); - elmHighscorePanel.className = "snake-panel-component"; - elmHighscorePanel.innerHTML = "Highscore: " + (localStorage.jsSnakeHighScore || 0); - - elmWelcome = createWelcomeElement(); - elmTryAgain = createTryAgainElement(); - elmWin = createWinElement(); - - SNAKE.addEventListener(elmContainer, "keyup", function (evt) { - if (!evt) evt = window.event; - evt.cancelBubble = true; - if (evt.stopPropagation) { - evt.stopPropagation(); - } - if (evt.preventDefault) { - evt.preventDefault(); - } - return false; - }, false); - - elmContainer.className = "snake-game-container"; - elmPauseScreen.style.zIndex = 10000; - elmContainer.appendChild(elmPauseScreen); - elmContainer.appendChild(elmPlayingField); - elmContainer.appendChild(elmAboutPanel); - elmContainer.appendChild(elmLengthPanel); - elmContainer.appendChild(elmHighscorePanel); - elmContainer.appendChild(elmWelcome); - elmContainer.appendChild(elmTryAgain); - elmContainer.appendChild(elmWin); - - mySnake = new SNAKE.Snake({playingBoard: me, startRow: 2, startCol: 2, premoveOnPause: config.premoveOnPause}); - myFood = new SNAKE.Food({playingBoard: me}); - - elmWelcome.style.zIndex = 1000; - } + // ------------------------------------------------------------------------- + // Contructor + public and private definitions + // ------------------------------------------------------------------------- + + return function (inputConfig) { + // --- private variables --- + const me = this; + const myId = instanceNumber++; + const config = inputConfig || {}; + const MAX_BOARD_COLS = 250; + const MAX_BOARD_ROWS = 250; + const blockWidth = 20; + const blockHeight = 20; + const GRID_FOOD_VALUE = -1; // the value of a spot on the board that represents snake food; MUST BE NEGATIVE + + // defaults + if (!config.onLengthUpdate) { + config.onLengthUpdate = () => {}; + } - function maxBoardWidth() { - return MAX_BOARD_COLS * me.getBlockWidth(); - } + if (!config.onPauseToggle) { + config.onPauseToggle = () => {}; + } + if (!config.onWin) { + config.onWin = () => {}; + } + if (!config.onDeath) { + config.onDeath = () => {}; + } - function maxBoardHeight() { - return MAX_BOARD_ROWS * me.getBlockHeight(); - } + let myFood, + mySnake, + boardState = 1, // 0: in active, 1: awaiting game start, 2: playing game + myKeyListener, + myWindowListener, + isPaused = false; //note: both the board and the snake can be paused + + // Board components + let elmContainer, + elmPlayingField, + elmAboutPanel, + elmLengthPanel, + elmHighscorePanel, + elmWelcome, + elmTryAgain, + elmWin, + elmPauseScreen; + + // --- public variables --- + me.grid = []; - function createWelcomeElement() { - const tmpElm = document.createElement("div"); - tmpElm.id = "sbWelcome" + myId; - tmpElm.className = "snake-welcome-dialog"; + // --------------------------------------------------------------------- + // private functions + // --------------------------------------------------------------------- - const welcomeTxt = document.createElement("div"); - let fullScreenText = ""; - if (config.fullScreen) { - fullScreenText = "On Windows, press F11 to play in Full Screen mode."; + function getStartRow() { + return config.startRow || 2; } - welcomeTxt.innerHTML = "JavaScript Snake

Use the arrow keys on your keyboard to play the game. " + fullScreenText + "

"; - const welcomeStart = document.createElement("button"); - welcomeStart.appendChild(document.createTextNode("Play Game")); - - const loadGame = function () { - SNAKE.removeEventListener(window, "keyup", kbShortcut, false); - tmpElm.style.display = "none"; - me.setBoardState(1); - me.getBoardContainer().focus(); - }; - const kbShortcut = function (evt) { - if (!evt) evt = window.event; - const keyNum = (evt.which) ? evt.which : evt.keyCode; - if (keyNum === 32 || keyNum === 13) { - loadGame(); - } - }; - - SNAKE.addEventListener(window, "keyup", kbShortcut, false); - SNAKE.addEventListener(welcomeStart, "click", loadGame, false); + function getStartCol() { + return config.startCol || 2; + } - tmpElm.appendChild(welcomeTxt); - tmpElm.appendChild(welcomeStart); - return tmpElm; - } + function createBoardElements() { + elmPlayingField = document.createElement("div"); + elmPlayingField.setAttribute("id", "playingField"); + elmPlayingField.className = "snake-playing-field"; + + SNAKE.addEventListener( + elmPlayingField, + "click", + function () { + elmContainer.focus(); + }, + false, + ); + + elmPauseScreen = document.createElement("div"); + elmPauseScreen.className = "snake-pause-screen"; + elmPauseScreen.innerHTML = + "
[Paused]

Press [space] to unpause.

"; + + elmAboutPanel = document.createElement("div"); + elmAboutPanel.className = "snake-panel-component"; + elmAboutPanel.innerHTML = + "more patorjk.com apps - source code - pat's youtube"; + + elmLengthPanel = document.createElement("div"); + elmLengthPanel.className = "snake-panel-component"; + elmLengthPanel.innerHTML = "Length: 1"; + + elmHighscorePanel = document.createElement("div"); + elmHighscorePanel.className = "snake-panel-component"; + elmHighscorePanel.innerHTML = + "Highscore: " + (localStorage[HIGH_SCORE_KEY] || 0); + + elmWelcome = createWelcomeElement(); + elmTryAgain = createTryAgainElement(); + elmWin = createWinElement(); + + SNAKE.addEventListener( + elmContainer, + "keyup", + function (evt) { + if (!evt) evt = window.event; + evt.cancelBubble = true; + if (evt.stopPropagation) { + evt.stopPropagation(); + } + if (evt.preventDefault) { + evt.preventDefault(); + } + return false; + }, + false, + ); + + elmContainer.className = "snake-game-container"; + + elmPauseScreen.style.zIndex = 10000; + elmContainer.appendChild(elmPauseScreen); + elmContainer.appendChild(elmPlayingField); + elmContainer.appendChild(elmAboutPanel); + elmContainer.appendChild(elmLengthPanel); + elmContainer.appendChild(elmHighscorePanel); + elmContainer.appendChild(elmWelcome); + elmContainer.appendChild(elmTryAgain); + elmContainer.appendChild(elmWin); + + mySnake = new SNAKE.Snake({ + playingBoard: me, + startRow: getStartRow(), + startCol: getStartCol(), + premoveOnPause: config.premoveOnPause, + moveSnakeWithAI: config.moveSnakeWithAI, + }); + myFood = new SNAKE.Food({ playingBoard: me }); + + elmWelcome.style.zIndex = 1000; + } - function createGameEndElement(message, elmId, elmClassName) { - const tmpElm = document.createElement("div"); - tmpElm.id = elmId + myId; - tmpElm.className = elmClassName; + function maxBoardWidth() { + return MAX_BOARD_COLS * me.getBlockWidth(); + } - const gameEndTxt = document.createElement("div"); - gameEndTxt.innerHTML = "JavaScript Snake

" + message + "

"; - const gameEndStart = document.createElement("button"); - gameEndStart.appendChild(document.createTextNode("Play Again?")); + function maxBoardHeight() { + return MAX_BOARD_ROWS * me.getBlockHeight(); + } - const reloadGame = function () { - tmpElm.style.display = "none"; - me.resetBoard(); - me.setBoardState(1); - me.getBoardContainer().focus(); - }; + function createWelcomeElement() { + const tmpElm = document.createElement("div"); + tmpElm.id = "sbWelcome" + myId; + tmpElm.className = "snake-welcome-dialog"; - const kbGameEndShortcut = function (evt) { - if (boardState !== 0 || tmpElm.style.display !== "block") { - return; + const welcomeTxt = document.createElement("div"); + let fullScreenText = ""; + if (config.fullScreen) { + fullScreenText = "On Windows, press F11 to play in Full Screen mode."; } - if (!evt) evt = window.event; - const keyNum = (evt.which) ? evt.which : evt.keyCode; - if (keyNum === 32 || keyNum === 13) { - reloadGame(); - } - }; - SNAKE.addEventListener(window, "keyup", kbGameEndShortcut, true); - - SNAKE.addEventListener(gameEndStart, "click", reloadGame, false); - tmpElm.appendChild(gameEndTxt); - tmpElm.appendChild(gameEndStart); - return tmpElm; - } + welcomeTxt.innerHTML = + "JavaScript Snake

Use the arrow keys on your keyboard to play the game. " + + fullScreenText + + "

"; + const welcomeStart = document.createElement("button"); + welcomeStart.appendChild(document.createTextNode("Play Game")); + + const loadGame = function () { + SNAKE.removeEventListener(window, "keyup", kbShortcut, false); + tmpElm.style.display = "none"; + me.setBoardState(BOARD_READY); + me.getBoardContainer().focus(); + }; + + const kbShortcut = function (evt) { + if (!evt) evt = window.event; + const keyNum = evt.which ? evt.which : evt.keyCode; + if (keyNum === 32 || keyNum === 13) { + loadGame(); + } + }; - function createTryAgainElement() { - return createGameEndElement("You died :(", "sbTryAgain", "snake-try-again-dialog"); - } + SNAKE.addEventListener(window, "keyup", kbShortcut, false); + SNAKE.addEventListener(welcomeStart, "click", loadGame, false); - function createWinElement() { - return createGameEndElement("You win! :D", "sbWin", "snake-win-dialog"); - } + tmpElm.appendChild(welcomeTxt); + tmpElm.appendChild(welcomeStart); + return tmpElm; + } - function handleEndCondition(elmDialog) { - const index = Math.max(getNextHighestZIndex(mySnake.snakeBody), getNextHighestZIndex({tmp: {elm: myFood.getFoodElement()}})); - elmContainer.removeChild(elmDialog); - elmContainer.appendChild(elmDialog); - elmDialog.style.zIndex = index; - elmDialog.style.display = "block"; - me.setBoardState(0); - } + function createGameEndElement(message, elmId, elmClassName) { + const tmpElm = document.createElement("div"); + tmpElm.id = elmId + myId; + tmpElm.className = elmClassName; + + const gameEndTxt = document.createElement("div"); + gameEndTxt.innerHTML = "JavaScript Snake

" + message + "

"; + const gameEndStart = document.createElement("button"); + gameEndStart.appendChild(document.createTextNode("Play Again?")); + + const reloadGame = function () { + tmpElm.style.display = "none"; + me.resetBoard(); + me.setBoardState(BOARD_READY); + me.getBoardContainer().focus(); + }; + + const kbGameEndShortcut = function (evt) { + if (boardState !== 0 || tmpElm.style.display !== "block") { + return; + } + if (!evt) evt = window.event; + const keyNum = evt.which ? evt.which : evt.keyCode; + if (keyNum === 32 || keyNum === 13) { + reloadGame(); + } + }; + SNAKE.addEventListener(window, "keyup", kbGameEndShortcut, true); - // --------------------------------------------------------------------- - // public functions - // --------------------------------------------------------------------- - - me.setPaused = function (val) { - isPaused = val; - mySnake.setPaused(val); - if (isPaused) { - elmPauseScreen.style.display = "block"; - } else { - elmPauseScreen.style.display = "none"; + SNAKE.addEventListener(gameEndStart, "click", reloadGame, false); + tmpElm.appendChild(gameEndTxt); + tmpElm.appendChild(gameEndStart); + return tmpElm; } - }; - me.getPaused = function () { - return isPaused; - }; - /** - * Resets the playing board for a new game. - * @method resetBoard - */ - me.resetBoard = function () { - SNAKE.removeEventListener(elmContainer, "keydown", myKeyListener, false); - SNAKE.removeEventListener(elmContainer, "visibilitychange", myWindowListener, false); - mySnake.reset(); - elmLengthPanel.innerHTML = "Length: 1"; - me.setupPlayingField(); - }; - /** - * Gets the current state of the playing board. There are 3 states: 0 - Welcome or Try Again dialog is present. 1 - User has pressed "Start Game" on the Welcome or Try Again dialog but has not pressed an arrow key to move the snake. 2 - The game is in progress and the snake is moving. - * @method getBoardState - * @return {Number} The state of the board. - */ - me.getBoardState = function () { - return boardState; - }; - /** - * Sets the current state of the playing board. There are 3 states: 0 - Welcome or Try Again dialog is present. 1 - User has pressed "Start Game" on the Welcome or Try Again dialog but has not pressed an arrow key to move the snake. 2 - The game is in progress and the snake is moving. - * @method setBoardState - * @param {Number} state The state of the board. - */ - me.setBoardState = function (state) { - boardState = state; - }; - /** - * @method getGridFoodValue - * @return {Number} A number that represents food on a number representation of the playing board. - */ - me.getGridFoodValue = function () { - return GRID_FOOD_VALUE; - }; - /** - * @method getPlayingFieldElement - * @return {DOM Element} The div representing the playing field (this is where the snake can move). - */ - me.getPlayingFieldElement = function () { - return elmPlayingField; - }; - /** - * @method setBoardContainer - * @param {DOM Element or String} myContainer Sets the container element for the game. - */ - me.setBoardContainer = function (myContainer) { - if (typeof myContainer === "string") { - myContainer = document.getElementById(myContainer); - } - if (myContainer === elmContainer) { - return; + function createTryAgainElement() { + return createGameEndElement( + "You died :(", + "sbTryAgain", + "snake-try-again-dialog", + ); } - elmContainer = myContainer; - elmPlayingField = null; - me.setupPlayingField(); - }; - /** - * @method getBoardContainer - * @return {DOM Element} - */ - me.getBoardContainer = function () { - return elmContainer; - }; - /** - * @method getBlockWidth - * @return {Number} - */ - me.getBlockWidth = function () { - return blockWidth; - }; - /** - * @method getBlockHeight - * @return {Number} - */ - me.getBlockHeight = function () { - return blockHeight; - }; - /** - * Sets up the playing field. - * @method setupPlayingField - */ - me.setupPlayingField = function () { - - if (!elmPlayingField) { - createBoardElements(); - } // create playing field - - // calculate width of our game container - let cWidth, cHeight; - let cTop, cLeft; - if (config.fullScreen === true) { - cTop = 0; - cLeft = 0; - cWidth = getClientWidth() - 20; - cHeight = getClientHeight() - 20; - - } else { - cTop = config.top; - cLeft = config.left; - cWidth = config.width; - cHeight = config.height; + function createWinElement() { + return createGameEndElement("You win! :D", "sbWin", "snake-win-dialog"); } - // define the dimensions of the board and playing field - const wEdgeSpace = me.getBlockWidth() * 2 + (cWidth % me.getBlockWidth()); - const fWidth = Math.min(maxBoardWidth() - wEdgeSpace, cWidth - wEdgeSpace); - const hEdgeSpace = me.getBlockHeight() * 3 + (cHeight % me.getBlockHeight()); - const fHeight = Math.min(maxBoardHeight() - hEdgeSpace, cHeight - hEdgeSpace); - - elmContainer.style.left = cLeft + "px"; - elmContainer.style.top = cTop + "px"; - elmContainer.style.width = cWidth + "px"; - elmContainer.style.height = cHeight + "px"; - elmPlayingField.style.left = me.getBlockWidth() + "px"; - elmPlayingField.style.top = me.getBlockHeight() + "px"; - elmPlayingField.style.width = fWidth + "px"; - elmPlayingField.style.height = fHeight + "px"; - - // the math for this will need to change depending on font size, padding, etc - // assuming height of 14 (font size) + 8 (padding) - const bottomPanelHeight = hEdgeSpace - me.getBlockHeight(); - const pLabelTop = me.getBlockHeight() + fHeight + Math.round((bottomPanelHeight - 30) / 2) + "px"; - - elmAboutPanel.style.top = pLabelTop; - elmAboutPanel.style.width = "450px"; - elmAboutPanel.style.left = Math.round(cWidth / 2) - Math.round(450 / 2) + "px"; - - elmLengthPanel.style.top = pLabelTop; - elmLengthPanel.style.left = 30 + "px"; - - elmHighscorePanel.style.top = pLabelTop; - elmHighscorePanel.style.left = cWidth - 140 + "px"; - - // if width is too narrow, hide the about panel - if (cWidth < 700) { - elmAboutPanel.style.display = "none"; - } else { - elmAboutPanel.style.display = "block"; + function handleEndCondition(elmDialog) { + const index = Math.max( + getNextHighestZIndex(mySnake.snakeBody), + getNextHighestZIndex({ tmp: { elm: myFood.getFoodElement() } }), + ); + elmContainer.removeChild(elmDialog); + elmContainer.appendChild(elmDialog); + elmDialog.style.zIndex = index; + elmDialog.style.display = "block"; + me.setBoardState(BOARD_NOT_READY); } - me.grid = []; - const numBoardCols = fWidth / me.getBlockWidth() + 2; - const numBoardRows = fHeight / me.getBlockHeight() + 2; - - for (let row = 0; row < numBoardRows; row++) { - me.grid[row] = []; - for (let col = 0; col < numBoardCols; col++) { - if (col === 0 || row === 0 || col === (numBoardCols - 1) || row === (numBoardRows - 1)) { - me.grid[row][col] = 1; // an edge - } else { - me.grid[row][col] = 0; // empty space - } + // --------------------------------------------------------------------- + // public functions + // --------------------------------------------------------------------- + + me.setPaused = function (val) { + isPaused = val; + mySnake.setPaused(val); + if (isPaused) { + elmPauseScreen.style.display = "block"; + } else { + elmPauseScreen.style.display = "none"; } - } - - myFood.randomlyPlaceFood(); - - myKeyListener = function (evt) { - if (!evt) evt = window.event; - const keyNum = (evt.which) ? evt.which : evt.keyCode; + config.onPauseToggle(isPaused); + }; + me.getPaused = function () { + return isPaused; + }; - if (me.getBoardState() === 1) { - if (!(keyNum >= 37 && keyNum <= 40) && !(keyNum === 87 || keyNum === 65 || keyNum === 83 || keyNum === 68)) { - return; - } // if not an arrow key, leave + /** + * Resets the playing board for a new game. + * @method resetBoard + */ + me.resetBoard = function () { + SNAKE.removeEventListener( + elmContainer, + "keydown", + myKeyListener, + false, + ); + SNAKE.removeEventListener( + elmContainer, + "visibilitychange", + myWindowListener, + false, + ); + mySnake.reset(); + config.onLengthUpdate(1); + elmLengthPanel.innerHTML = "Length: 1"; + me.setupPlayingField(); + }; + /** + * Gets the current state of the playing board. There are 3 states: 0 - Welcome or Try Again dialog is present. 1 - User has pressed "Start Game" on the Welcome or Try Again dialog but has not pressed an arrow key to move the snake. 2 - The game is in progress and the snake is moving. + * @method getBoardState + * @return {Number} The state of the board. + */ + me.getBoardState = function () { + return boardState; + }; + /** + * Sets the current state of the playing board. There are 3 states: 0 - Welcome or Try Again dialog is present. 1 - User has pressed "Start Game" on the Welcome or Try Again dialog but has not pressed an arrow key to move the snake. 2 - The game is in progress and the snake is moving. + * @method setBoardState + * @param {Number} state The state of the board. + */ + me.setBoardState = function (state) { + boardState = state; + }; + /** + * @method getGridFoodValue + * @return {Number} A number that represents food on a number representation of the playing board. + */ + me.getGridFoodValue = function () { + return GRID_FOOD_VALUE; + }; + /** + * @method getPlayingFieldElement + * @return {DOM Element} The div representing the playing field (this is where the snake can move). + */ + me.getPlayingFieldElement = function () { + return elmPlayingField; + }; + /** + * @method setBoardContainer + * @param {DOM Element or String} myContainer Sets the container element for the game. + */ + me.setBoardContainer = function (myContainer) { + if (typeof myContainer === "string") { + myContainer = document.getElementById(myContainer); + } + if (myContainer === elmContainer) { + return; + } + elmContainer = myContainer; + elmPlayingField = null; - // This removes the listener added at the #listenerX line - SNAKE.removeEventListener(elmContainer, "keydown", myKeyListener, false); - SNAKE.removeEventListener(elmContainer, "visibilitychange", myWindowListener, false); + me.setupPlayingField(); + }; + /** + * @method getBoardContainer + * @return {DOM Element} + */ + me.getBoardContainer = function () { + return elmContainer; + }; + /** + * @method getBlockWidth + * @return {Number} + */ + me.getBlockWidth = function () { + return blockWidth; + }; + /** + * @method getBlockHeight + * @return {Number} + */ + me.getBlockHeight = function () { + return blockHeight; + }; + /** + * Sets up the playing field. + * @method setupPlayingField + */ + me.setupPlayingField = function () { + if (!elmPlayingField) { + createBoardElements(); + } // create playing field + + // calculate width of our game container + let cWidth, cHeight; + let cTop, cLeft; + if (config.fullScreen === true) { + cTop = 0; + cLeft = 0; + cWidth = getClientWidth() - 20; + cHeight = getClientHeight() - 20; + } else { + cTop = config.top; + cLeft = config.left; + cWidth = config.width; + cHeight = config.height; + } - myKeyListener = function (evt) { - if (!evt) evt = window.event; - const keyNum = (evt.which) ? evt.which : evt.keyCode; + // define the dimensions of the board and playing field + const wEdgeSpace = + me.getBlockWidth() * 2 + (cWidth % me.getBlockWidth()); + const fWidth = Math.min( + maxBoardWidth() - wEdgeSpace, + cWidth - wEdgeSpace, + ); + const hEdgeSpace = + me.getBlockHeight() * 3 + (cHeight % me.getBlockHeight()); + const fHeight = Math.min( + maxBoardHeight() - hEdgeSpace, + cHeight - hEdgeSpace, + ); + + elmContainer.style.left = cLeft + "px"; + elmContainer.style.top = cTop + "px"; + elmContainer.style.width = cWidth + "px"; + elmContainer.style.height = cHeight + "px"; + elmPlayingField.style.left = me.getBlockWidth() + "px"; + elmPlayingField.style.top = me.getBlockHeight() + "px"; + elmPlayingField.style.width = fWidth + "px"; + elmPlayingField.style.height = fHeight + "px"; + + // the math for this will need to change depending on font size, padding, etc + // assuming height of 14 (font size) + 8 (padding) + const bottomPanelHeight = hEdgeSpace - me.getBlockHeight(); + const pLabelTop = + me.getBlockHeight() + + fHeight + + Math.round((bottomPanelHeight - 30) / 2) + + "px"; + + elmAboutPanel.style.top = pLabelTop; + elmAboutPanel.style.width = "450px"; + elmAboutPanel.style.left = + Math.round(cWidth / 2) - Math.round(450 / 2) + "px"; + + elmLengthPanel.style.top = pLabelTop; + elmLengthPanel.style.left = 30 + "px"; + + elmHighscorePanel.style.top = pLabelTop; + elmHighscorePanel.style.left = cWidth - 140 + "px"; + + // if width is too narrow, hide the about panel + if (cWidth < 700) { + elmAboutPanel.style.display = "none"; + } else { + elmAboutPanel.style.display = "block"; + } - //console.log(keyNum); - if (keyNum === 32) { - if (me.getBoardState() != 0) - me.setPaused(!me.getPaused()); + me.grid = []; + const numBoardCols = fWidth / me.getBlockWidth() + 2; + const numBoardRows = fHeight / me.getBlockHeight() + 2; + + for (let row = 0; row < numBoardRows; row++) { + me.grid[row] = []; + for (let col = 0; col < numBoardCols; col++) { + if ( + col === 0 || + row === 0 || + col === numBoardCols - 1 || + row === numBoardRows - 1 + ) { + me.grid[row][col] = 1; // an edge + } else { + me.grid[row][col] = 0; // empty space } - + } + } + me.grid[getStartRow()][getStartCol()] = 1; // snake head + + myFood.randomlyPlaceFood(); + config.onLengthUpdate(1); + + myKeyListener = function (evt) { + if (!evt) evt = window.event; + const keyNum = evt.which ? evt.which : evt.keyCode; + + if (me.getBoardState() === BOARD_READY) { + if ( + !(keyNum >= 37 && keyNum <= 40) && + !( + keyNum === 87 || + keyNum === 65 || + keyNum === 83 || + keyNum === 68 + ) + ) { + return; + } // if not an arrow key, leave + + // This removes the listener added at the #listenerX line + SNAKE.removeEventListener( + elmContainer, + "keydown", + myKeyListener, + false, + ); + SNAKE.removeEventListener( + elmContainer, + "visibilitychange", + myWindowListener, + false, + ); + + myKeyListener = function (evt) { + if (!evt) evt = window.event; + const keyNum = evt.which ? evt.which : evt.keyCode; + + if (keyNum === 32) { + if (me.getBoardState() != BOARD_NOT_READY) + me.setPaused(!me.getPaused()); + } + + mySnake.handleArrowKeys(keyNum); + + evt.cancelBubble = true; + if (evt.stopPropagation) { + evt.stopPropagation(); + } + if (evt.preventDefault) { + evt.preventDefault(); + } + return false; + }; + + //listener for pausing the game if user change tab or minimize the browser window + document.addEventListener("visibilitychange", () => { + if (document.visibilityState === "hidden") { + if (me.getBoardState() != BOARD_NOT_READY && !me.getPaused()) + me.setPaused(true); + } + }); + + SNAKE.addEventListener( + elmContainer, + "keydown", + myKeyListener, + false, + ); + SNAKE.addEventListener( + elmContainer, + "visibilitychange", + myWindowListener, + false, + ); + + mySnake.rebirth(); mySnake.handleArrowKeys(keyNum); + me.setBoardState(BOARD_IN_PLAY); // start the game! + mySnake.go(); + } - evt.cancelBubble = true; - if (evt.stopPropagation) { - evt.stopPropagation(); - } - if (evt.preventDefault) { - evt.preventDefault(); - } - return false; - }; - - //listener for pausing the game if user change tab or minimize the browser window - document.addEventListener("visibilitychange", () => { - if (document.visibilityState === 'hidden') { - if (me.getBoardState() != 0 && !me.getPaused()) - me.setPaused(true); - } - }); + evt.cancelBubble = true; + if (evt.stopPropagation) { + evt.stopPropagation(); + } + if (evt.preventDefault) { + evt.preventDefault(); + } + return false; + }; + // Search for #listenerX to see where this is removed + if (!config.moveSnakeWithAI) { SNAKE.addEventListener(elmContainer, "keydown", myKeyListener, false); - SNAKE.addEventListener(elmContainer, "visibilitychange", myWindowListener, false); - - mySnake.rebirth(); - mySnake.handleArrowKeys(keyNum); - me.setBoardState(2); // start the game! - mySnake.go(); + SNAKE.addEventListener( + elmContainer, + "visibilitychange", + myWindowListener, + false, + ); } + }; - evt.cancelBubble = true; - if (evt.stopPropagation) { - evt.stopPropagation(); + /** + * This method is called when the snake has eaten some food. + * @method foodEaten + * @return {bool} Whether a new food was able to spawn (true) + * or not (false) after the snake eats food. + */ + me.foodEaten = function () { + config.onLengthUpdate(mySnake.snakeLength); + elmLengthPanel.innerHTML = "Length: " + mySnake.snakeLength; + if (mySnake.snakeLength > localStorage[HIGH_SCORE_KEY]) { + localStorage.setItem(HIGH_SCORE_KEY, mySnake.snakeLength); + elmHighscorePanel.innerHTML = + "Highscore: " + localStorage[HIGH_SCORE_KEY]; } - if (evt.preventDefault) { - evt.preventDefault(); + if (!myFood.randomlyPlaceFood()) { + return false; } - return false; + return true; }; - // Search for #listenerX to see where this is removed - SNAKE.addEventListener(elmContainer, "keydown", myKeyListener, false); - SNAKE.addEventListener(elmContainer, "visibilitychange", myWindowListener, false); - }; + /** + * This method is called when the snake dies. + * @method handleDeath + */ + me.handleDeath = function () { + handleEndCondition(elmTryAgain); + config.onDeath({ startAIGame: me.startAIGame }); + }; - /** - * This method is called when the snake has eaten some food. - * @method foodEaten - * @return {bool} Whether a new food was able to spawn (true) - * or not (false) after the snake eats food. - */ - me.foodEaten = function () { - elmLengthPanel.innerHTML = "Length: " + mySnake.snakeLength; - if (mySnake.snakeLength > localStorage.jsSnakeHighScore) { - localStorage.setItem("jsSnakeHighScore", mySnake.snakeLength); - elmHighscorePanel.innerHTML = "Highscore: " + localStorage.jsSnakeHighScore; - } - if (!myFood.randomlyPlaceFood()) { - return false; - } - return true; - }; + /** + * This method is called when the snake wins. + * @method handleWin + */ + me.handleWin = function () { + handleEndCondition(elmWin); + config.onWin({ startAIGame: me.startAIGame }); + }; - /** - * This method is called when the snake dies. - * @method handleDeath - */ - me.handleDeath = function () { - handleEndCondition(elmTryAgain); - }; + me.setSpeed = (speed) => { + mySnake.setSpeed(speed); + }; + me.getSpeed = () => { + return mySnake.getSpeed(); + }; - /** - * This method is called when the snake wins. - * @method handleWin - */ - me.handleWin = function () { - handleEndCondition(elmWin); - }; + me.startAIGame = () => { + mySnake.rebirth(); + me.setBoardState(2); // start the game! + mySnake.go(); + }; - // --------------------------------------------------------------------- - // Initialize - // --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Initialize + // --------------------------------------------------------------------- + + config.fullScreen = + typeof config.fullScreen === "undefined" ? false : config.fullScreen; + config.top = typeof config.top === "undefined" ? 0 : config.top; + config.left = typeof config.left === "undefined" ? 0 : config.left; + config.width = typeof config.width === "undefined" ? 400 : config.width; + config.height = + typeof config.height === "undefined" ? 400 : config.height; + config.premoveOnPause = + typeof config.premoveOnPause === "undefined" + ? false + : config.premoveOnPause; - config.fullScreen = (typeof config.fullScreen === "undefined") ? false : config.fullScreen; - config.top = (typeof config.top === "undefined") ? 0 : config.top; - config.left = (typeof config.left === "undefined") ? 0 : config.left; - config.width = (typeof config.width === "undefined") ? 400 : config.width; - config.height = (typeof config.height === "undefined") ? 400 : config.height; - config.premoveOnPause = (typeof config.premoveOnPause === "undefined") ? false : config.premoveOnPause; + if (config.fullScreen) { + SNAKE.addEventListener( + window, + "resize", + function () { + me.setupPlayingField(); + }, + false, + ); + } - if (config.fullScreen) { - SNAKE.addEventListener(window, "resize", function () { - me.setupPlayingField(); - }, false); - } + me.setBoardState(BOARD_NOT_READY); - me.setBoardState(0); + if (config.boardContainer) { + me.setBoardContainer(config.boardContainer); + } - if (config.boardContainer) { - me.setBoardContainer(config.boardContainer); - } + const reloadGame = function () { + me.resetBoard(); + me.setBoardState(BOARD_READY); + me.getBoardContainer().focus(); + }; - }; // end return function -})(); + if (config.onInit) { + config.onInit({ + reloadGame, + getSpeed: me.getSpeed, + setSpeed: me.setSpeed, + startAIGame: me.startAIGame, + }); + } + }; // end return function + })(); From df3d88ec11da90aba952b4d26ee911597814d4e7 Mon Sep 17 00:00:00 2001 From: patorjk Date: Thu, 13 Feb 2025 21:49:59 -0500 Subject: [PATCH 155/160] updates --- README.md | 43 ++++++++++++++++++++++++++++ src/ai-example.html | 2 +- src/js/ai-init.js | 43 ++++++++++++++++++++++++++-- src/js/snake.js | 68 +++++++++++++++++++++++++++++---------------- 4 files changed, 128 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 8577b786..641e7803 100755 --- a/README.md +++ b/README.md @@ -37,6 +37,49 @@ npx parcel src/index.html Runs on http://localhost:1234 +## AI Snake + +If you want to control the snake via an AI algorithm see the ai-init.js and ai-example files. + +Essentially all you have to do is run `params.startAIGame();` when initializing and pass in a `moveSnakeWithAI` method +which is run before the snake does each move. + +```js + moveSnakeWithAI: ({ + grid, + snakeHead, + currentDirection, + isFirstGameMove, + setDirection, + }) => { + + /* + Direction: + 0 + 3 1 + 2 + */ + + // This is NOT a real hamiltonian cycle. It misses some values, I'm just including this here as an example of + // a look-up type table that you could do. + const hamiltonianCycleGrid = [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0], + [0, 0, 2, 3, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 0], + [0, 0, 2, 0, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0], + [0, 0, 2, 0, 2, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0], + [0, 0, 3, 0, 3, 3, 3, 3, 0, 3, 0, 3, 0, 3, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ]; + + const newDirection = hamiltonianCycleGrid[snakeHead.row][snakeHead.col]; + setDirection(newDirection); + }, + onInit: (params) => { + params.startAIGame(); // This start an AI game + }, +``` + ## Contributors Thanks goes to these people: ([emoji key](https://allcontributors.org/docs/en/emoji-key)) diff --git a/src/ai-example.html b/src/ai-example.html index e1acb6ad..d3ca29d7 100644 --- a/src/ai-example.html +++ b/src/ai-example.html @@ -124,7 +124,7 @@
- + From 2dd6f1b8d1c95f1d100bf038f75bfaa234723ee8 Mon Sep 17 00:00:00 2001 From: patorjk Date: Thu, 13 Feb 2025 22:16:49 -0500 Subject: [PATCH 159/160] game note --- README.md | 2 ++ src/index.html | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 641e7803..b3a2f430 100755 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ You can now play and edit the game live in codesandbox: https://codesandbox.io/s/github/patorjk/JavaScript-Snake?file=/index.html +**2025: Looks like CSS inside the sandbox isn't working properly, in the game it works fine though** + On first load sometimes the game frame will not load correctly and you'll need to press the refresh icon above its display panel to get the game to show. Original game is located here: diff --git a/src/index.html b/src/index.html index 291c88ce..03dc6b10 100755 --- a/src/index.html +++ b/src/index.html @@ -38,7 +38,6 @@ newCss.rel = "stylesheet"; newCss.type = "text/css"; newCss.href = themeUrl; - console.log(newCss.href); document.head.appendChild(newCss); } From 5702346689d4af03d7b5635005c34fa695d03802 Mon Sep 17 00:00:00 2001 From: patorjk Date: Thu, 13 Feb 2025 22:17:43 -0500 Subject: [PATCH 160/160] clean up --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index b3a2f430..0956f864 100755 --- a/README.md +++ b/README.md @@ -119,8 +119,3 @@ Thanks goes to these people: ([emoji key](https://allcontributors.org/docs/en/em - -TODO: - -- Add in what was added to Subpixel Snake --