/*========================================================================================================= AUTHOR: JÉRÉMIE JACQUES (http://jeremiejacques.be) TITLE: MEMORY GAME VERSION: 1.1 LAST MODIFIED: Sun 5th Dec 2015 DESCR: Little game realized in pure Javascript to learn oriented objects. =========================================================================================================*/ /* ================================================ Construct the dom elements ================================================ */ if (!document.getElementById('game')) { obj = document.createElement('div'); obj.setAttribute('class', 'game'); obj.setAttribute('id', 'game'); document.body.appendChild(obj); }; if (!document.getElementById('container')) { obj = document.createElement('div'); obj.setAttribute('class', 'container clearfix'); obj.setAttribute('id', 'container'); document.getElementById("game").appendChild(obj); }; /* ================================================ Memory game ================================================ */ var Game = function(obj) { var self = this; self.dom = { container: document.getElementById("container"), end: document.getElementById("end"), // permet d'afficher les résultat du jeu restart: document.getElementById("restart"), returnToGameMode: document.getElementById("return"), time: document.getElementById("time") } /* **************************** Parameter that can be customized **************************** */ self.cardsCount = obj.cards || 9; // Nombre de cartes différentes dans la partie ( /!\ c'est *2 pour que ce soit des paires) self.level = obj.level || "beginner"; // Choix du level pour le jeu (beginner, medium ou expert) -> change le contenu des cartes /* *************************** Parameter for game **************************** */ self.cards = []; // tableau pour stocker les cartes self.cardsFind = []; // tableau pour stocker les cartes retournée qui sont correct self.nbrError = 0; // compte le nombre de carte retourné qui ne sont pas des paires self.timeToLook = 0.5; // temps pour regarder au début du jeu et temps que les 2 cartes retournée reste affiché en sec //self.turnCard = 1; // sert à connaitre si c'est le première carte retournée sur le jeu ou la deuxième self.firstCard; // enregistre la première carte retournée self.clicks = 0; self.canClick = true; self.ifIsAnimate = false; // si les cartes sont animées /* **************************** INITIALISATION **************************** */ self.init = function() { for (var i = 0; i < self.cardsCount * 2; i++) { var card = new Card(self); card.create(i % self.cardsCount, self.level); self.cards.push(card); } self.cards.sort(function() { return 0.5 - Math.random(); }); // random the array of cards for (var i = 0; i < self.cards.length; i++) { self.dom.container.appendChild(self.cards[i].element); }; setTimeout(function() { // laisse les cartes visibles au début du jeu for (var i = 0; i < self.cards.length; i++) { self.cards[i].element.classList.remove("turn"); self.cards[i].element.children[0].children[0].classList.remove("turn"); } }, self.timeToLook * 1000); self.timeGame = { // pour enregistrer le temps qu'à durer la partie sec: 0, min: 0 }; self.timer = setInterval(function() { self.timeGame.sec++; if (self.timeGame.sec > 59) { self.timeGame.min++; self.timeGame.sec = 0; }; }, 1000); }; self.init(); /* **************************** Reset game **************************** */ self.reset = function() { self.cards = []; self.cardsFind = []; self.clicks = 0; self.nbrError = 0; self.gameTime = 0; self.canClick = true; self.ifIsAnimate = false; self.firstCard; self.init(); } /* **************************** End of game **************************** */ self.end = function() { clearInterval(self.timer); // stop the timer if (self.timeGame.sec < 10) { self.dom.time.innerHTML = self.timeGame.min + " min : 0" + self.timeGame.sec + " sec"; }; if (self.timeGame.min < 10) { self.dom.time.innerHTML = "0" + self.timeGame.min + " min : " + self.timeGame.sec + " sec"; }; if (self.timeGame.min < 10 && self.timeGame.sec < 10) { self.dom.time.innerHTML = "0" + self.timeGame.min + " min : " + "0" + self.timeGame.sec + " sec"; }; if (self.timeGame.min >= 10 && self.timeGame.sec >= 10) { self.dom.time.innerHTML = self.timeGame.min + " min : " + self.timeGame.sec + " sec"; }; self.dom.restart.addEventListener("click", function() { document.getElementById("container").innerHTML = ""; self.dom.end.classList.remove("end--open"); self.reset(); }); self.dom.returnToGameMode.addEventListener("click", function() { document.getElementById("container").innerHTML = ""; self.dom.end.classList.remove("end--open"); document.getElementById("intro").classList.add("intro--open"); }); } } /* **************************** Create the cards **************************** */ var Card = function(game) { var self = this; self.create = function(index, level) { self.element = document.createElement("div"); self.element.setAttribute("id", "containerCard"); self.element.setAttribute("class", "containerCard turn"); self.element.setAttribute("index", index); self.element.addEventListener("click", function() { // regarder si la carte qu'on clique n'est pas déjà trouvé var cardIndex = self.element.getAttribute("index"); for (var i = 0; i < game.cardsFind.length; i++) { if (cardIndex == game.cardsFind[i]) { game.canClick = false; }; }; if (game.canClick && !game.ifIsAnimate) { game.clicks++; if (game.clicks == 1) { game.firstCard = self.element; // enregistre la première carte retournée }; _turnCard(self, game); if (game.clicks == 2) { game.clicks = 0; }; }; game.canClick = true; }, false); // false -> ne prend que l'éléments et pas tout le window containerContent = document.createElement("div"); containerContent.setAttribute("id", "card"); containerContent.setAttribute("class", "card"); self.element.appendChild(containerContent); var content = ['back', 'front']; for (var i = 0; i < content.length; i++) { obj = document.createElement('div'); if (content[i] == 'back') { obj.setAttribute('class', 'face ' + content[i] + ' card__' + level + '--' + index); } else { obj.setAttribute('class', 'face ' + content[i]); }; obj.setAttribute('id', content[i]); containerContent.appendChild(obj); }; return self.element; }; } /* **************************** Append when you click on a card **************************** */ var _turnCard = function(card, game) { var self = card.element; if (game.clicks == 1) { self.classList.add("turn"); }; if (game.clicks == 2 && self == game.firstCard) { self.classList.remove("turn"); game.clicks == 0; }; if (game.clicks == 2 && self != game.firstCard) { self.classList.add("turn"); var firstIndex = game.firstCard.getAttribute("index"); var secondIndex = self.getAttribute("index"); if (firstIndex == secondIndex) { game.cardsFind.push(firstIndex); } else { game.ifIsAnimate = true; setTimeout(function() { self.classList.remove("turn"); game.firstCard.classList.remove("turn"); game.ifIsAnimate = false; }, game.timeToLook * 1000); }; }; if ((game.cardsFind.length == game.cardsCount)) { setTimeout(game.dom.end.classList.add("end--open"), 1500); game.end(); }; }; /* ================================================ THE GAME ================================================ */ var level = document.getElementsByName('level'); for (key in level) { level[key].onclick = function() { var self = this; document.getElementById("container").innerHTML = ""; // remove all in the container memoryGame = new Game({ cards: paramLevel(this)[0], level: paramLevel(this)[1] }); document.getElementById("intro").classList.remove("intro--open"); event.preventDefault(); } } function paramLevel(level) { // get the level choose at the beginning of the game if (level.value == "beginner") { return [9, "beginner"]; }; if (level.value == "medium") { return [9, "medium"]; }; if (level.value == "expert") { return [12, "expert"]; }; }
<section id="intro" class="intro intro--open"> <h1>Memory game</h1> <p>Petit jeu memory réalisé uniquement en javascript orienté objects.</p> <p>Choisissez un mode de jeu ci-dessous pour commencer :</p> <button value="beginner" name="level" id="beginner">Débutant</button> <button value="medium" name="level" id="medium">Intermédiaire</button> <button value="expert" name="level" id="expert">Expert</button> </section> <section id="end" class="end"> <p class="result">Vous avez terminé la partie en <span id="time">0sec</span></p> <button value="restart" id="restart">Recommencer une partie</button> <button value="return" id="return">Retour au mode de jeu</button> </section>
body { margin: 0; background: url(http://tfa.jeremiejacques.be/lab/memory-game/assets/_img/background.png) no-repeat center center fixed; color: #65666A; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover; background-size: cover; font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 400; } /*clearfix from:http://www.positioniseverything.net/easyclearing.html*/ .clearfix:after { content: "0"; display: block; height: 0; clear: both; visibility: hidden; overflow: hidden; } .clearfix { display: inline-table; } /*Hides from IE-mac*/ .clearfix { display: block; } /*End hide from IE-mac*/ .intro { display: none; } .intro--open { display: block; z-index: 999; padding: 35px; top: 0; left: 0; height: 90%; width: 50%; margin: 0 auto; background: #F9F9F9; margin-top: 2vh; border-radius: 8px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.6); } [name="level"], button { border: none; border-radius: none; outline: none; display: block; width: 70%; padding: 10px; margin: 15px auto; background: none; border: 3px solid #ADABA5; color: #65656A; cursor: pointer; font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; text-transform: uppercase; -webkit-transition: all .3s ease-in-out; -moz-transition: all .3s ease-in-out; -ms-transition: all .3s ease-in-out; -o-transition: all .3s ease-in-out; transition: all .3s ease-in-out; } [name="level"]:hover, button:hover { background: #ADABA5; } .container { width: 95%; max-width: 1400px; margin: 0 auto; margin-top: 30px; background: #F9F9F9; border-radius: 8px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.6); } .containerCard { height: 170px; width: 170px; float: left; margin: 2vh 15px; cursor: pointer; position: relative; -webkit-perspective: 1000; -moz-perspective: 1000; -ms-perspective: 1000; -o-perspective: 1000; } .card { width: 100%; height: 100%; border-radius: 8px; position: relative; -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; -ms-transform-style: preserve-3d; -o-transform-style: preserve-3d; -webkit-transition: .4s; -moz-transition: .4s; -ms-transition: .4s; -o-transition: .4s; transition: .4s; } .front { background: url(http://tfa.jeremiejacques.be/lab/memory-game/assets/_img/card.png) center center no-repeat; border-radius: 8px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.6); z-index: 10; } .face { position: absolute; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; -o-backface-visibility: hidden; backface-visibility: hidden; top: 0; left: 0; width: 100%; height: 100%; color: white; line-height: 50px; text-align: center; } .back { -webkit-transform: rotateY(180deg); -moz-transform: rotateY(180deg); -ms-transform: rotateY(180deg); -o-transform: rotateY(180deg); transform: rotateY(180deg); border-radius: 8px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.6); } .face { position: absolute; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; -o-backface-visibility: hidden; backface-visibility: hidden; top: 0; left: 0; width: 100%; height: 100%; } .containerCard.turn .card { -webkit-transform: rotateY(180deg); -moz-transform: rotateY(180deg); -ms-transform: rotateY(180deg); -o-transform: rotateY(180deg); transform: rotateY(180deg); } .containerCard.turn .front { z-index: 0; } .card__beginner--0 { background: #E65100; } .card__beginner--1 { background: #FF4081; } .card__beginner--2 { background: #9C27B0; } .card__beginner--3 { background: #3F51B5; } .card__beginner--4 { background: #03A9F4; } .card__beginner--5 { background: #009688; } .card__beginner--6 { background: #4CAF50; } .card__beginner--7 { background: #CDDC39; } .card__beginner--8 { background: #FFC107; } .card__beginner--9 { background: #795548; } [class*="card__medium--"]::after { color: #373B44; font-size: 58px; line-height: 170px; background: #C4C2B8; height: 100%; width: 100%; position: absolute; left: 0; border-radius: 8px; } .card__medium--0::after { content: 'α'; } .card__medium--1::after { content: '∇'; } .card__medium--2::after { content: 'θ'; } .card__medium--3::after { content: '∂'; } .card__medium--4::after { content: 'ς'; } .card__medium--5::after { content: '♦'; } .card__medium--6::after { content: 'Ω'; } .card__medium--7::after { content: '∞'; } .card__medium--8::after { content: 'ϖ'; } .card__medium--9::after { content: '♣'; } [class*="card__expert--"]::after { color: #373B44; font-size: 58px; line-height: 170px; background: #C4C2B8; height: 100%; width: 100%; position: absolute; left: 0; border-radius: 8px; } .card__expert--0::after { content: '阿'; } .card__expert--1::after { content: '贝'; } .card__expert--2::after { content: '色'; } .card__expert--3::after { content: '德'; } .card__expert--4::after { content: '饿'; } .card__expert--5::after { content: '艾'; } .card__expert--6::after { content: '日'; } .card__expert--7::after { content: '什'; } .card__expert--8::after { content: '伊'; } .card__expert--9::after { content: '卡'; } .card__expert--10::after { content: '马'; } .card__expert--11::after { content: '玉'; } .card__expert--12::after { content: '克'; } .card__expert--13::after { content: '和'; } .card__expert--14::after { content: '马'; } .card__expert--15::after { content: '丝'; } .end { position: absolute; top: 0; left: 0; height: 100%; width: 100%; background: rgb(242, 242, 242); opacity: 0; -webkit-transform: scale(0, 0); -moz-transform: scale(0, 0); -ms-transform: scale(0, 0); -o-transform: scale(0, 0); transform: scale(0, 0); -webkit-transition: all .6s ease-in-out; -moz-transition: all .6s ease-in-out; -ms-transition: all .6s ease-in-out; -o-transition: all .6s ease-in-out; transition: all .6s ease-in-out; } .end--open { opacity: 1; -webkit-transform: scale(1, 1); -moz-transform: scale(1, 1); -ms-transform: scale(1, 1); -o-transform: scale(1, 1); transform: scale(1, 1); z-index: 9999; } .result { margin-top: 100px; text-align: center; }