Cara Membuat Memory Game dengan JavaScript
Ada banyak sekali aplikasi bermanfaat dan aplikasi game yang dibuat dengan bahasa pemrograman JavaScript. Didukung dengan tampilan menarik dari bahasa pemrograman CSS, membuat aplikasi lebih mudah untuk dipahami dan digunakan oleh pengguna. Kali ini, kita akan mencoba membuat sebuah aplikasi memori game.
Memori game
Memori game merupakan salah satu game pendidikan yang berfungsi untuk mengasah ingatan pemain. Selain itu game ini juga dilengkapi dengan perhitungan jumlah langkah strategi dan waktu bermain.
Lalu, bagaimana caranya membuat aplikasi memori game dengan bahasa pemrograman JavaScript? Yuk langsung saja buka komputer kamu dan ikuti beberapa langkah di bawah ini.
Tutorial
1. Buka XAMPP Control Panel, serta aktifkan Apache.
2. Buka program teks editor yang ter-install di komputer kamu, disini saya menggunakan teks editor Notepad++. Ketikkan kode HTML5 berikut ini.
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Membuat Memory Game dengan JavaScript</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet prefetch" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css"> <link rel="stylesheet prefetch" href="https://fonts.googleapis.com/css?family=Coda"> <link rel="stylesheet prefetch" href="https://fonts.googleapis.com/css?family=Gloria+Hallelujah|Permanent+Marker" > <link rel="stylesheet" href="css/style.css"> </head> <body> <div class="container"> <header> <h1>Memory Game</h1> </header> <section class="score-panel"> <ul class="stars"> <li><i class="fa fa-star"></i></li> <li><i class="fa fa-star"></i></li> <li><i class="fa fa-star"></i></li> </ul> <span class="moves">0</span> Move(s) <div class="timer"> </div> <div class="restart" onclick=startGame()> <i class="fa fa-repeat"></i> </div> </section> <ul class="deck" id="card-deck"> <li class="card" type="diamond"> <i class="fa fa-diamond"></i> </li> <li class="card" type="plane"> <i class="fa fa-paper-plane-o"></i> </li> <li class="card match" type="anchor"> <i class="fa fa-anchor"></i> </li> <li class="card" type="bolt" > <i class="fa fa-bolt"></i> </li> <li class="card" type="cube"> <i class="fa fa-cube"></i> </li> <li class="card match" type="anchor"> <i class="fa fa-anchor"></i> </li> <li class="card" type="leaf"> <i class="fa fa-leaf"></i> </li> <li class="card" type="bicycle"> <i class="fa fa-bicycle"></i> </li> <li class="card" type="diamond"> <i class="fa fa-diamond"></i> </li> <li class="card" type="bomb"> <i class="fa fa-bomb"></i> </li> <li class="card" type="leaf"> <i class="fa fa-leaf"></i> </li> <li class="card" type="bomb"> <i class="fa fa-bomb"></i> </li> <li class="card open show" type="bolt"> <i class="fa fa-bolt"></i> </li> <li class="card" type="bicycle"> <i class="fa fa-bicycle"></i> </li> <li class="card" type="plane"> <i class="fa fa-paper-plane-o"></i> </li> <li class="card" type="cube"> <i class="fa fa-cube"></i> </li> </ul> <div id="popup1" class="overlay"> <div class="popup"> <h2>Congratulations 🎉</h2> <a class="close" href=# >×</a> <div class="content-1"> Congratulations you're a winner 🎉🎉 </div> <div class="content-2"> <p>You made <span id=finalMove> </span> moves </p> <p>in <span id=totalTime> </span> </p> <p>Rating: <span id=starRating></span></p> </div> <button id="play-again"onclick="playAgain()"> Play again 😄</a> </button> </div> </div> </div> <script src="js/app.js"></script> </body> </html>
Simpan kode HTLM5 di atas di folder xampplite – htdocs – buat folder baru dengan nama MemoryGame – simpan kode di atas dengan nama index.html.
3. Untuk melihat hasil script code di atas, kamu bisa buka browser kamu ketiklah http://localhost/MemoryGame.
4. Untuk membuat background game, ketikkan kode CSS berikut ini.
html { box-sizing: border-box; } *, *::before, *::after { box-sizing: inherit; } html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { background: #dcdcdc; font-family: sans-serif; font-size: 16px; } .container { display: flex; justify-content: center; align-items: center; flex-direction: column; } h1 { font-family: sans-serif; } /* * Styles for the deck of cards */ .deck { width: 85%; background: #716F71; padding: 1rem; border-radius: 4px; box-shadow: 8px 9px 26px 0 rgba(46, 61, 73, 0.5); display: flex; flex-wrap: wrap; justify-content: space-around; align-items: center; margin: 0 0 3em; } .deck .card { height: 3.7rem; width: 3.7rem; margin: 0.2rem 0.2rem; background: #141214;; font-size: 0; color: #ffffff; border-radius: 5px; cursor: pointer; display: flex; justify-content: center; align-items: center; box-shadow: 5px 2px 20px 0 rgba(46, 61, 73, 0.5); } .deck .card.open { transform: rotateY(0); background: #02b3e4; cursor: default; animation-name: flipInY; -webkit-backface-visibility: visible !important; backface-visibility: visible !important; animation-duration: .75s; } .deck .card.show { font-size: 33px; } .deck .card.match { cursor: default; background: #E5F720; font-size: 33px; animation-name: rubberBand; -webkit-backface-visibility: visible !important; backface-visibility: visible !important; animation-duration: .75s; } .deck .card.unmatched { animation-name: pulse; -webkit-backface-visibility: visible !important; backface-visibility: visible !important; animation-duration: .75s; background: #e2043b; } .deck .card.disabled { pointer-events: none; opacity: 0.9; } /* * Styles for the Score Panel */ .score-panel { text-align: left; margin-bottom: 10px; } .score-panel .stars { margin: 0; padding: 0; display: inline-block; margin: 0 5px 0 0; } .score-panel .stars li { list-style: none; display: inline-block; } .score-panel .restart { float: right; cursor: pointer; } .fa-star { color: #FFD700; } .timer { display: inline-block; margin: 0 1rem; } /* * Styles for congratulations modal */ .overlay { position: fixed; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.7); transition: opacity 500ms; visibility: hidden; opacity: 0; } .overlay:target { visibility: visible; opacity: 1; } .popup { margin: 70px auto; padding: 20px; background: #ffffff; border-radius: 5px; width: 85%; position: relative; transition: all 5s ease-in-out; font-family: sans-serif; } .popup h2 { margin-top: 0; color: #333; font-family: sans-serif; } .popup .close { position: absolute; top: 20px; right: 30px; transition: all 200ms; font-size: 30px; font-weight: bold; text-decoration: none; color: #333; } .popup .close:hover { color: #E5F720; } .popup .content-1, .content-2 { max-height: 30%; overflow: auto; text-align: center; } .show { visibility: visible !important; opacity: 100 !important; } #starRating li { display: inline-block; } #play-again { background-color: #141214; padding: 0.7rem 1rem; font-size: 1.1rem; display: block; margin: 0 auto; width: 50%; font-family: sans-serif; color: #ffffff; border-radius: 5px; } /* animations */ @keyframes flipInY { from { transform: perspective(400px) rotate3d(0, 1, 0, 90deg); animation-timing-function: ease-in; opacity: 0; } 40% { transform: perspective(400px) rotate3d(0, 1, 0, -20deg); animation-timing-function: ease-in; } 60% { transform: perspective(400px) rotate3d(0, 1, 0, 10deg); opacity: 1; } 80% { transform: perspective(400px) rotate3d(0, 1, 0, -5deg); } to { transform: perspective(400px); } } @keyframes rubberBand { from { transform: scale3d(1, 1, 1); } 30% { transform: scale3d(1.25, 0.75, 1); } 40% { transform: scale3d(0.75, 1.25, 1); } 50% { transform: scale3d(1.15, 0.85, 1); } 65% { transform: scale3d(.95, 1.05, 1); } 75% { transform: scale3d(1.05, .95, 1); } to { transform: scale3d(1, 1, 1); } } @keyframes pulse { from { transform: scale3d(1, 1, 1); } 50% { transform: scale3d(1.2, 1.2, 1.2); } to { transform: scale3d(1, 1, 1); } } /****** Media queries ***************************/ @media (max-width: 320px) { .deck { width: 85%; } .deck .card { height: 4.7rem; width: 4.7rem; } } /* For Tablets and larger screens ****************/ @media (min-width: 768px) { .container { font-size: 22px; } .deck { width: 660px; height: 680px; } .deck .card { height: 125px; width: 125px; } .popup { width: 60%; } }
Simpan kode CSS di folder xampplite – htdocs – pilih folder MemoryGame – buat folder baru dengan nama CSS – simpan code CSS dengan nama style.css.
5. Reload alamat url : http://localhost/MemoryGame. Tampilan dari background game, namun game belum bisa dimainkan.
6. Agar game dapat dimainkan, ketikkan kode JavaScript berikut ini.
// cards array holds all cards let card = document.getElementsByClassName("card"); let cards = [...card]; // deck of all cards in game const deck = document.getElementById("card-deck"); // declaring move variable let moves = 0; let counter = document.querySelector(".moves"); // declare variables for star icons const stars = document.querySelectorAll(".fa-star"); // declaring variable of matchedCards let matchedCard = document.getElementsByClassName("match"); // stars list let starsList = document.querySelectorAll(".stars li"); // close icon in modal let closeicon = document.querySelector(".close"); // declare modal let modal = document.getElementById("popup1") // array for opened cards var openedCards = []; // @description shuffles cards // @param {array} // @returns shuffledarray function shuffle(array) { var currentIndex = array.length, temporaryValue, randomIndex; while (currentIndex !== 0) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; array[randomIndex] = temporaryValue; } return array; }; // @description shuffles cards when page is refreshed / loads document.body.onload = startGame(); // @description function to start a new play function startGame(){ // empty the openCards array openedCards = []; // shuffle deck cards = shuffle(cards); // remove all exisiting classes from each card for (var i = 0; i < cards.length; i++){ deck.innerHTML = ""; [].forEach.call(cards, function(item) { deck.appendChild(item); }); cards[i].classList.remove("show", "open", "match", "disabled"); } // reset moves moves = 0; counter.innerHTML = moves; // reset rating for (var i= 0; i < stars.length; i++){ stars[i].style.color = "#FFD700"; stars[i].style.visibility = "visible"; } //reset timer second = 0; minute = 0; hour = 0; var timer = document.querySelector(".timer"); timer.innerHTML = "0 mins 0 secs"; clearInterval(interval); } // @description toggles open and show class to display cards var displayCard = function (){ this.classList.toggle("open"); this.classList.toggle("show"); this.classList.toggle("disabled"); }; // @description add opened cards to OpenedCards list and check if cards are match or not function cardOpen() { openedCards.push(this); var len = openedCards.length; if(len === 2){ moveCounter(); if(openedCards[0].type === openedCards[1].type){ matched(); } else { unmatched(); } } }; // @description when cards match function matched(){ openedCards[0].classList.add("match", "disabled"); openedCards[1].classList.add("match", "disabled"); openedCards[0].classList.remove("show", "open", "no-event"); openedCards[1].classList.remove("show", "open", "no-event"); openedCards = []; } // description when cards don't match function unmatched(){ openedCards[0].classList.add("unmatched"); openedCards[1].classList.add("unmatched"); disable(); setTimeout(function(){ openedCards[0].classList.remove("show", "open", "no-event","unmatched"); openedCards[1].classList.remove("show", "open", "no-event","unmatched"); enable(); openedCards = []; },1100); } // @description disable cards temporarily function disable(){ Array.prototype.filter.call(cards, function(card){ card.classList.add('disabled'); }); } // @description enable cards and disable matched cards function enable(){ Array.prototype.filter.call(cards, function(card){ card.classList.remove('disabled'); for(var i = 0; i < matchedCard.length; i++){ matchedCard[i].classList.add("disabled"); } }); } // @description count player's moves function moveCounter(){ moves++; counter.innerHTML = moves; //start timer on first click if(moves == 1){ second = 0; minute = 0; hour = 0; startTimer(); } // setting rates based on moves if (moves > 8 && moves < 12){ for( i= 0; i < 3; i++){ if(i > 1){ stars[i].style.visibility = "collapse"; } } } else if (moves > 13){ for( i= 0; i < 3; i++){ if(i > 0){ stars[i].style.visibility = "collapse"; } } } } // @description game timer var second = 0, minute = 0; hour = 0; var timer = document.querySelector(".timer"); var interval; function startTimer(){ interval = setInterval(function(){ timer.innerHTML = minute+"mins "+second+"secs"; second++; if(second == 60){ minute++; second=0; } if(minute == 60){ hour++; minute = 0; } },1000); } // @description congratulations when all cards match, show modal and moves, time and rating function congratulations(){ if (matchedCard.length == 16){ clearInterval(interval); finalTime = timer.innerHTML; // show congratulations modal modal.classList.add("show"); // declare star rating variable var starRating = document.querySelector(".stars").innerHTML; //showing move, rating, time on modal document.getElementById("finalMove").innerHTML = moves; document.getElementById("starRating").innerHTML = starRating; document.getElementById("totalTime").innerHTML = finalTime; //closeicon on modal closeModal(); }; } // @description close icon on modal function closeModal(){ closeicon.addEventListener("click", function(e){ modal.classList.remove("show"); startGame(); }); } // @desciption for user to play Again function playAgain(){ modal.classList.remove("show"); startGame(); } // loop to add event listeners to each card for (var i = 0; i < cards.length; i++){ card = cards[i]; card.addEventListener("click", displayCard); card.addEventListener("click", cardOpen); card.addEventListener("click",congratulations); };
Simpan kode JavaScript di folder xampplite – htdocs – pilih folder MemoryGame – buat folder baru dengan nama JavaScript – simpan code CSS dengan nama app.js.
7. Reload alamat url : http://localhost/MemoryGame. Tampilan awal game, klik ikon reload untuk mendapatkan permainan baru.
Mulailah bermain dengan menebak dua gambar yang sama dalam satu kali tebak.
Game ini juga dilengkapi dengan perhitungan jumlah langkah strategi dan waktu bermain.
Tampilan ketika game selesai.
8. Karena gambar game berasal dari:
<link rel="stylesheet prefetch" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
Jadi komputer kamu harus terkoneksi internet, jika tidak maka gambar game tidak akan muncul.
9. Selesai, menarik sekali bukan?
Demikian penjelasan dari tutorial ‘Cara Membuat Memory Game dengan JavaScript’. Selamat mencoba.