/*========================================================================================================= AUTHOR: JÉRÉMIE JACQUES (http://jeremiejacques.be) TITLE: HANGMAN GAME VERSION: 1.0 LAST MODIFIED: Fri 29th May 2015 DESCR: Little game realized with jQuery to learn oriented objects. SOURCES: http://stackoverflow.com/questions/8222447/how-do-i-get-the-value-of-each-key-pressed-and-use-it-in-a-variable-with-jquery http://code.tutsplus.com/tutorials/creating-a-keyboard-with-css-and-jquery--net-5774 https://api.jquery.com/ DATA SOURCES: FR: https://github.com/atebits/Words EN: https://github.com/bevacqua/correcthorse/blob/master/wordlist.json =========================================================================================================*/ $(document).ready(function(){ //------------------------------ // START - LANGUAGE OF WORDS AND LEVEL //------------------------------ /* level - two possibility : - beginner : -> word point : 0-8 -> word length : 2-6 letters -> just decomment lines 71->73 and comment lines 74->76 - medium : -> word point : 9-16 -> word length : 6-12 letters -> just decomment lines 71->73 and comment lines 74->76 - expert : -> word point : 17+ -> word length : 12 and more letters -> just decomment lines 71->73 and comment lines 74->76 word point based on scrabble : http://en.wikipedia.org/wiki/Scrabble_letter_distributions */ var $baseURL = "http://tfa.jeremiejacques.be/lab/hangman-game/assets/ajax/words-en.json?accessType=DOWNLOAD"; var $words = []; // to push the words from the json file $englishPoint = { 1 : ["e", "a", "i", "n", "o", "r", "s", "t", "u", "l"], 2 : ["d", "m", "g"], 3 : ["b", "c", "p"], 4 : ["f", "h", "v"], 5 : [], 8 : ["j", "q"], 10 : ["k", "w", "x", "y", "z"] }; $frenchPoints = { 1 : ["e", "a", "i", "n", "o", "r", "s", "t", "u", "l"], 2 : ["d", "g"], 3 : ["b", "c", "m", "p"], 4 : ["f", "h", "v", "w", "y"], 5 : ["k"], 8 : ["j", "x"], 10 : ["q", "z"] }; $wordsPoints = $englishPoint; // if .lang don't change, english is selected $goodWords = []; $(".lang").change(function(){ // get the language for the word $lang = $(this).val(); if($lang == "fr"){ $baseURL = "http://tfa.jeremiejacques.be/lab/hangman-game/assets/ajax/words-fr.json?accessType=DOWNLOAD"; $wordsPoints = $frenchPoints; }else{ $baseURL = "http://tfa.jeremiejacques.be/lab/hangman-game/assets/ajax/words-en.json?accessType=DOWNLOAD"; $wordsPoints = $englishPoint; }; }); $(".level").click(function(){ $level = $(this).attr("value"); $.getJSON($baseURL, function(data){ for (var i = 0; i < data.words.length; i++) { // each word in json /* get the point of each word */ var $points = 0; for (var j = 0; j < data.words[i].length; j++) { // each letter for this word $.each($wordsPoints, function(point, tabOfLetter){ // each element in the object $frenchPoint if($.inArray(data.words[i][j], tabOfLetter) == true){ // if the letter is in the array $points = parseFloat($points + parseFloat(point)); }; }); }; if($level == "beginner"){ /* if(data.words[i].length > 2 && data.words[i].length < 6){ $words.push(data.words[i]); }; */ if ($points <= 8){ $words.push(data.words[i]); }; }else if($level == "medium"){ /* if(data.words[i].length > 6 && data.words[i].length < 12){ $words.push(data.words[i]); }; */ if ($points > 8 && $points <= 16){ $words.push(data.words[i]); }; }else if($level == "expert"){ /* if(data.words[i].length > 12){ $words.push(data.words[i]); }; */ if ($points > 16){ $words.push(data.words[i]); }; }; }; hanged = new Game({ words : $words }); }); $(".start").fadeOut(); event.preventDefault(); }); //------------------------------ // THE GAME //------------------------------ var Game = function(obj){ var $self = $(this); $self.dom = { keyboardCharacter: $('#keyboard li input'), // characters on the virtual keyboard result: $('#result'), // to display the result win/lost restart: $('.restart'), // button to restart the game close: $('#close'), // button to stop the game gameTime: $('#gameTime span'), // to display the time that the game took parts: $('#parts span'), // to display all parts that the player have played partsWin: $('#partsWin span'), // to display all parts that the player have win clearStats : $('.clearStats') }; $self.init = function(){ $self.word;// the word to have to find $self.error = 0; // count each faults to display the hanged $self.letterPosition = []; // records the position in the word of the letter entered if it matches one of the word $self.letterDifferent = []; // records the position of the letter entered if it doesn't correspond with the letter of the word in the same position $self.letterComplete = 0; // records the numbers of completed letter in the word $self.saveKeyPress = [0]; // records all key that the user press (only : [a-z\.]) $self.result; // records if game is win / lost $self.parts = parseFloat(localStorage.getItem("parts")); // records number of game that the player have played $self.partsWin = parseFloat(localStorage.getItem("partsWin")); // records number of game that the player have win $self.words = obj.words; // get the array with words from the JSON file $(self.getWord = function(){ $self.word = $self.words[getRandomNum($self.words)]; // get a random word in the array from the JSON file //$("h2").html($self.word); // only for dev }); $(self.create = function(){ for (var i = 0; i < $self.word.length; i++) { $("<input/>").attr("maxlength", "1").attr("class", "wordLetter").prop('disabled', true).appendTo("#word"); }; }); $self.timeGame = { sec: 0, min: 0 }; $self.timer = setInterval(function(){ $self.timeGame.sec++; if($self.timeGame.sec < 10){ $(".time").html($self.timeGame.min + " : " + "0" + $self.timeGame.sec); }; if($self.timeGame.sec > 59){ $self.timeGame.min++; $self.timeGame.sec=0; }; if($self.timeGame.min < 10){ $(".time").html("0" + $self.timeGame.min + " : " + $self.timeGame.sec); }; if($self.timeGame.min < 10 && $self.timeGame.sec < 10){ $(".time").html("0" + $self.timeGame.min + " : " + "0" + $self.timeGame.sec); }; if($self.timeGame.min >= 10 && $self.timeGame.sec >= 10){ $(".time").html($self.timeGame.min + " : " + $self.timeGame.sec); }; }, 1000); /* event for user keyboard ----- have to be in the init to allow keypress on game restart */ $(document).keypress(function(e){ var $character = String.fromCharCode(e.which); var $can = true; if($character.match(/[a-z\.]/)){ for(var i = 0; i < $self.saveKeyPress.length; i++) { if($character == $self.saveKeyPress[i]){ $can = false; }; // just to know if key was press before or not }; if($can){ // only if key wasn't press $self.letterPosition = []; $self.letterDifferent = []; var $btnCharacter = $('input[value="' + $character + '"]'); $btnCharacter.prop('disabled', true); $self.saveKeyPress.push($character); $self.checkLetter($character, $btnCharacter); }; }else{return;}; }); } $self.init(); /* event for virtual keyboard */ $self.dom.keyboardCharacter.click(function(){ var $character = $(this).val(); // take the value of the character $(this).prop('disabled', true); // desactivate the character when click on $self.letterPosition = []; // remove everything in the array, each time we click on character $self.letterDifferent = []; // remove everything in the array, each time we click on character $self.saveKeyPress.push($character); $self.checkLetter($character, $(this)); }); $self.dom.clearStats.click(function(){ localStorage.clear(); $self.dom.parts.text(0); $self.dom.partsWin.text(0); }); $self.checkLetter = function($character, $btnCharacter){ for(var i = 0; i < $self.word.length; i++){ if($character == $self.word[i]){ $self.letterPosition.push(i); }else{ $self.letterDifferent.push(i); }; }; if($self.letterDifferent.length == $self.word.length){ $btnCharacter.addClass("error"); $(".hangedEl:nth-child("+ parseInt($self.error+1) +")").attr("class", "hangedEl draw"); //to display element of hanged $self.error++; if($self.error == 11){ // word not find after 11 trials , hanged is dead $self.result = "lost"; $self.endGame(); }; }; for(var i = 0; i < $self.letterPosition.length; i++){ $(".wordLetter:nth-child("+ parseInt($self.letterPosition[i]+1) +")").val($character); }; $self.letterComplete = $self.letterComplete + $self.letterPosition.length; // save the number of letter complete in the word if($self.letterComplete == $self.word.length){ // if we find all letters $self.result = "win"; $self.endGame(); }; }; $self.endGame = function(){ /* stop everything in the game */ $self.dom.keyboardCharacter.prop('disabled', true); // desactivate all key in the keyboard for(var i=0; i<$self.word.length; i++){ // $(".wordLetter:nth-child("+ parseInt(i+1) +")").val($self.word[i]); // to complete the word at the end -> Good idea ? Not sure... }; clearInterval($self.timer); // stop the timer $(document).off("keypress"); // stop the keypress listenner setTimeout(function(){ $(".end").addClass("end--open"); // open the panel for end game }, 1000); /* display the game result */ if($self.result == "win"){ $self.dom.result.text("Congratulations you found the word : " + $self.word); if($self.partsWin){ localStorage.setItem("partsWin", parseFloat($self.partsWin + 1)); $self.partsWin++ ; }else{localStorage.setItem("partsWin",1); $self.partsWin=1;}; }else{ $self.dom.result.text("You lost, the word was : " + $self.word); if(!$self.partsWin){$self.partsWin=0;}; }; if($self.parts){ localStorage.setItem("parts", parseFloat($self.parts + 1)); $self.parts++; }else{localStorage.setItem("parts",1); $self.parts=1;}; $self.dom.gameTime.text($self.timeGame.min + " min " + $self.timeGame.sec + " sec"); $self.dom.parts.text($self.parts); $self.dom.partsWin.text($self.partsWin); $("#restart").focus(); // focus on restart allows to restart on press enter }; /* event listenner on button (restart/close) */ $self.dom.restart.click(function(){ $self.reset(); $(".end").removeClass("end--open"); $(".btnRestart, .btnInfoParts").fadeOut(); $(".letter").focus(); }); $self.dom.close.click(function(){ $(".end").removeClass("end--open"); $(".btnRestart").fadeIn(); $(".btnInfoParts").fadeIn(); $(".btnInfoParts").click(function(){ $(".end").addClass("end--open"); }); }); $self.reset = function(){ $("#word").html(""); $(".letter").prop('disabled', false).removeClass("error"); $(".wordLetter").val(""); $(".hangedEl").attr("class", "hangedEl"); $(".btnInfoParts").removeClass("btnInfoParts--open"); $self.init(); }; }; //end of Game // get a random num to take a random word in the JSON file function getRandomNum($words){ var rndNum = Math.random(); // between 0 - 1 rndNum = parseInt(rndNum * $words.length); // from 0 - to array words.length = quantity of words return rndNum; }; });//end of $(document).ready
<div class="start"> <h1>Hangman Game !</h1> <p>Little game that I realized only jQuery oriented objects.</p> <p>Choose a game mode below to begin :</p> <select class="lang"> <option value="en">English</option> <option value="fr">French</option> </select> <button value="beginner" name="level" class="level" id="beginner">Beginner</button> <button value="medium" name="level" class="level" id="medium">Intermediate</button> <button value="expert" name="level" class="level" id="expert">Expert</button> </div> <h1>Hangman Game !</h1> <div class="time">00 : 00</div> <button class="restart btnRestart">Restart the game</button> <button class="btnInfoParts">Information on the part</button> <svg id="hanged" x="0px" y="0px" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve"> <line class="hangedEl" x1="37" y1="456" x2="458" y2="456"/> <line class="hangedEl" x1="88.5" y1="456" x2="88.5" y2="51.5"/> <line class="hangedEl" x1="85.3" y1="51.5" x2="272.7" y2="51.5" /> <line class="hangedEl" x1="88.5" y1="155.5" x2="192.5" y2="51.5"/> <line class="hangedEl" x1="269.7" y1="51.5" x2="269.7" y2="103.5"/> <circle class="hangedEl" cx="269.7" cy="131.7" r="29.5"/> <line class="hangedEl" x1="269.7" y1="161.2" x2="269.7" y2="309"/> <line class="hangedEl" x1="269.7" y1="309" x2="206.3" y2="402.3"/> <line class="hangedEl" x1="269.7" y1="309" x2="332.3" y2="401.7"/> <line class="hangedEl" x1="269.7" y1="215.7" x2="369" y2="215.7"/> <line class="hangedEl" x1="170.3" y1="215.7" x2="269.7" y2="215.7"/> </svg> <form action="" method="" accept-charset="utf-8" id="game"> <div id="word"></div> </form> <form action="" method="" accept-charset="utf-8"> <ul id="keyboard"> <li><input type="button" name="" value="a" class="letter"></li> <li><input type="button" name="" value="b" class="letter"></li> <li><input type="button" name="" value="c" class="letter"></li> <li><input type="button" name="" value="d" class="letter"></li> <li><input type="button" name="" value="e" class="letter"></li> <li><input type="button" name="" value="f" class="letter"></li> <li><input type="button" name="" value="g" class="letter"></li> <li><input type="button" name="" value="h" class="letter"></li> <li><input type="button" name="" value="i" class="letter"></li> <li><input type="button" name="" value="j" class="letter"></li> <li><input type="button" name="" value="k" class="letter"></li> <li><input type="button" name="" value="l" class="letter"></li> <li><input type="button" name="" value="m" class="letter"></li> <li><input type="button" name="" value="n" class="letter"></li> <li><input type="button" name="" value="o" class="letter"></li> <li><input type="button" name="" value="p" class="letter"></li> <li><input type="button" name="" value="q" class="letter"></li> <li><input type="button" name="" value="r" class="letter"></li> <li><input type="button" name="" value="s" class="letter"></li> <li><input type="button" name="" value="t" class="letter"></li> <li><input type="button" name="" value="u" class="letter"></li> <li><input type="button" name="" value="v" class="letter"></li> <li><input type="button" name="" value="w" class="letter"></li> <li><input type="button" name="" value="x" class="letter"></li> <li><input type="button" name="" value="y" class="letter"></li> <li><input type="button" name="" value="z" class="letter"></li> </ul> </form> <div id="test"></div> <div class="end"> <div id="result">Congratulations you found the word : xxx</div> <div id="gameTime">You have completed this part : <strong><span>0</span></strong></div> <div id="parts">You play <strong><span>0</span> time</strong></div> <div id="partsWin">You won <strong><span>0</span> parts</strong></div> <button id="restart" class="restart">Restart a part</button> <button class="clearStats">Clear Stats</button> <button id="close">Close</button> </div>
@import url(http://fonts.googleapis.com/css?family=Indie+Flower); html, body{ padding: 0; margin: 0; background: url(http://tfa.jeremiejacques.be/lab/hangman-game/assets/_img/chalkboard.jpg) no-repeat center center fixed; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover; background-size: cover; overflow: hidden; } .clearfix:after { content: " "; display: block; clear: both; visibility: hidden; line-height: 0; height: 0; } h1{ text-align: center; font-family: 'Indie Flower', cursive; color: #FFFFFF; font-size: 64px; margin-bottom: 0; } .start h1{ color: #111111; margin-top: 30vh; } h2{ position: absolute; margin: 0; left: 0; top: 10px; color: lightgray; } .time{ position: absolute; right: 30px; top: 81px; border: #fff solid; padding: 2px 15px; border-radius: 5px; font-size: 22px; color: #fff; } button{ cursor: pointer; } #game{ text-align: center; } .wordLetter{ height: 90px; width: 7%; text-align: center; font-size: 64px; background: none; border: none; margin: 0 13px; color: white; border-bottom: 2px solid; font-family: 'Indie Flower', cursive; } #hanged{ width: 24%; display: block; position: relative; left: 50%; -webkit-transform: translateX(-50%); -moz-transform: translateX(-50%); -ms-transform: translateX(-50%); -o-transform: translateX(-50%); transform: translateX(-50%); } .hangedEl{ fill:none; stroke:#FFFFFF; stroke-width:6.5; stroke-miterlimit:10; stroke-dasharray: 800; stroke-dashoffset: 800; } .hangedEl.draw{-webkit-animation: draw 3s forwards;} @-webkit-keyframes draw{ from{ stroke-dashoffset : 800; } to{ stroke-dashoffset : 0; } } #keyboard { margin: 0 auto; padding: 0; list-style: none; width: 650px; margin-top: 50px; } .letter{ float: left; margin: 0 8px 8px 0; width: 40px; height: 40px; line-height: 40px; font-size: 15px; text-align: center; background: #fff; border: none; -moz-border-radius: 5px; -webkit-border-radius: 5px; } .letter:hover, .letter:active, .letter:focus{ position: relative; top: 2px; left: 1px; cursor: pointer; outline: none; } .letter:disabled:hover{ cursor: default; top: 0px; left: 0px; border: none; } .letter:disabled{ background: #898989; color: #646464; } .error{ color: #FFFFFF!important; background: #C05453!important; } .start{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; text-align: center; line-height: 45px; font-size: 25px; font-family: 'Indie Flower', cursive; z-index: 9999; } .start::after { content: ''; position: absolute; top: 0; left: 0; height: 100%; width: 100%; background: #fff; z-index: -1; } select.lang{ display: block; margin: 0 auto; height: 50px; width: 343px; border: none; color: #FFFFFF; background-color: black; font-family: 'Indie Flower' cursive; font-size: 20px; outline: none; } .level{ border: none; padding: 15px; margin-top: 30px; background: black; color: #fff; font-size: 20px; border-radius: 8px; outline: none; font-family: 'Indie Flower', cursive; } .end{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; text-align: center; line-height: 45px; font-size: 25px; font-family: 'Indie Flower', cursive; opacity: 0; transform: translateX(-100%); -webkit-transition: opacity .6s cubic-bezier(0.165, 0.84, 0.44, 1); -moz-transition: opacity .6s cubic-bezier(0.165, 0.84, 0.44, 1); -ms-transition: opacity .6s cubic-bezier(0.165, 0.84, 0.44, 1); -o-transition: opacity .6s cubic-bezier(0.165, 0.84, 0.44, 1); transition: opacity .6s cubic-bezier(0.165, 0.84, 0.44, 1); } .end::after { content: ''; position: absolute; top: 0; left: 0; height: 100%; width: 100%; background: #fff; opacity: .8; z-index: -1; } .end--open{ transform: translateX(0); opacity: 1; } .end button{ border: none; padding: 15px; margin-top: 30px; background: black; color: #fff; font-size: 20px; border-radius: 8px; outline: none; font-family: 'Indie Flower', cursive; } #close, .clearStats{ background: none !important; color: black !important; } .end button:hover, .end button:active, .end button:focus, .start button:hover, .start button:active, .start button:focus{ position: relative; top: 2px; left: 1px; } button#restart { display: block; margin: 0 auto; margin-top: 30px; } .btnInfoParts, .btnRestart{ position: absolute; right: 30px; top: 132px; border: none; outline: none; background: #fff; padding: 3px 15px; border-radius: 5px; font-size: 20px; font-family: 'Indie Flower', cursive; cursor: pointer; display: none; } .btnRestart{ right: 260px; } .btnInfoParts:hover, .btnInfoParts:active, .btnRestart:focus, .btnRestart:hover, .btnRestart:active, .btnRestart:focus{ top: 134px; } #result { margin-top: 35vh; } table.stats{ margin: 0 auto; } #word { max-width: 1200px; width: 90%; margin: 0 auto; }