How Can I Create An Animated Escape Game,css
In this article, you will exist recreating the guessing game Wordle. This article covers the core game logic but does non implement sharing your results. The article also doesn't cover the functionality that generates game statistics.
This tutorial is intended for beginner front-finish developers that want to build a fun, vanilla JavaScript project.
You tin check out a demo of the finished project hither.
Prerequisites
This tutorial assumes a bones agreement of:
- HTML
- CSS
- Javascript
- NPM
How to Build the Wordle Clone
These are the steps you'll be taking to build the Wordle clone:
- Project Setup
- Creating the game board
- Creating the on-screen keyboard
- Accepting user input
- Adding notifications
- Making the on-screen keyboard generate input
- Adding animation
Projection Setup
Before edifice the game, you need to get some components in place. First, you need to create a binder for all the source code of our clone. Call this folder build.
After yous've done that, set upwardly your evolution server.
Live-server
Yous'll exist using a evolution server called live-server. This step is optional, simply saves you the trouble of reloading the page later every change to the source lawmaking.
Install live-server by typing the following in your final :
npm install live-server
HTML Setup
Inside build, create an HTML file and proper name it index.html. Put the following code into it:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="Ten-UA-Uniform" content="IE=border"> <meta proper name="viewport" content="width=device-width, initial-scale=1.0"> <championship>Wordle</title> </head> <body> <h1> Wordle Clone </h1> <div id="game-board"> </div> </body> </html>
The HTML code creates a header for our game and makes the container for the game board.
You're going to be using a JavaScript library called Toastr for in-game notifications and a CSS library called Breathing.css for the board animations.
To include them in your project, add together the post-obit links to the head of your index.html file.
<link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" rel="stylesheet"/> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/iv.1.1/animate.min.css" />
Those links volition fetch the CSS for both Animate.css and Toastr. Put the following lawmaking in alphabetize.html, just before the closing trunk tag:
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
That code will fetch the JavaScript for Toastr and jQuery (considering Toastr depends on it).
JavaScript Setup
Your JavaScript will live in a file called script.js. Create script.js, and place it inside build.
Put this code at the top of script.js:
import { WORDS } from "./words.js"; const NUMBER_OF_GUESSES = six; let guessesRemaining = NUMBER_OF_GUESSES; permit currentGuess = []; let nextLetter = 0; let rightGuessString = WORDS[Math.floor(Math.random() * WORDS.length)] panel.log(rightGuessString)
This lawmaking snippet initialises the global variables we'll be using for our game and picks a random word from the array WORDS
equally the right gauge for this round. We also log the right gauge to the console, to debug our code if necessary.
The list of immune words we'll exist using will be hardcoded and stored as an array in the file words.js. Create words.js, inside build, and re-create the JavaScript from this link into it.
Words.js should look similar this:
CSS Setup
Name your CSS file mode.css. Style.css should also exist placed in build.
h1 { text-marshal: center; }
The only CSS setup we need is a bit of code to centre the text of our header
Putting it all together
Finally, link script.js as a module in your alphabetize.html, then link style.css.
At this point, your index.html should look similar this:
<!DOCTYPE html> <html lang="en"> <caput> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Wordle</championship> <link rel="stylesheet" href="style.css"> <link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" rel="stylesheet"/> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.ane.1/breathing.min.css" /> </caput> <body> <h1> Wordle Clone </h1> <div id="game-board"> </div> <script src="https://code.jquery.com/jquery-3.half dozen.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script> <script src="script.js" type="module"></script> </body> </html>
and your file structure should look like this:
Start alive-server past typing this into your console:
live-server build
That's it for setup.
How to Create the Game Board
You're going to create the game board by writing a JavaScript function. Allow's call the role initBoard
. Add this code to your script.js file:
function initBoard() { permit board = document.getElementById("game-lath"); for (allow i = 0; i < NUMBER_OF_GUESSES; i++) { let row = document.createElement("div") row.className = "letter of the alphabet-row" for (let j = 0; j < five; j++) { let box = document.createElement("div") box.className = "letter-box" row.appendChild(box) } lath.appendChild(row) } } initBoard()
So what does this code practise? initBoard
creates i row for each guess nosotros give the user and creates 5 boxes for each row. There is i box for each letter of the alphabet of the judge, and the function makes them all children of the row.
initBoard
then adds each row to the board container. Each row is given the class letter-row
, and each box is assigned letter-box
.
Side by side, you lot're going to style the board with some CSS. Place the following code in your fashion.css file:
#game-board { display: flex; align-items: centre; flex-management: cavalcade; } .letter-box { border: 2px solid gray; border-radius: 3px; margin: 2px; font-size: ii.5rem; font-weight: 700; superlative: 3rem; width: 3rem; brandish: flex; justify-content: heart; align-items: center; text-transform: uppercase; } .filled-box { edge: 2px solid black; } .letter-row { brandish: flex; }
This CSS does a few things:
- centers the rows of the board horizontally and vertically
- sets a height, width, and border for each box on the board
- creates a singled-out look for a box filled with a letter
At this point, when you lot load index.html in your browser, it should look like this:
How to Create the On-screen Keyboard
The simplest way to create the keyboard is with HTML. Add this code to your index.html, later the game board div:
<div id="keyboard-cont"> <div grade="first-row"> <button class="keyboard-push button">q</button> <push class="keyboard-push button">west</button> <button grade="keyboard-button">e</push> <push button class="keyboard-push button">r</button> <button class="keyboard-push">t</button> <button course="keyboard-button">y</button> <push form="keyboard-push button">u</button> <button class="keyboard-push">i</push> <button class="keyboard-button">o</button> <button class="keyboard-button">p</button> </div> <div class="2d-row"> <push course="keyboard-button">a</button> <button course="keyboard-push button">s</button> <button course="keyboard-button">d</push button> <button course="keyboard-push">f</button> <button class="keyboard-button">thousand</push button> <button grade="keyboard-button">h</push button> <push class="keyboard-push button">j</push button> <button class="keyboard-button">grand</button> <button class="keyboard-button">l</push button> </div> <div class="third-row"> <button course="keyboard-button">Del</button> <push button course="keyboard-button">z</button> <button course="keyboard-button">x</button> <push button class="keyboard-button">c</button> <button class="keyboard-button">5</button> <push button class="keyboard-push">b</button> <button class="keyboard-button">due north</push> <button class="keyboard-push">m</button> <push button class="keyboard-button">Enter</button> </div> </div>
Now, way the markup by calculation this CSS to the stop of style.css:
#keyboard-cont { margin: 1rem 0; display: flex; flex-direction: column; marshal-items: heart; } #keyboard-cont div { display: flex; } .second-row { margin: 0.5rem 0; } .keyboard-push button { font-size: 1rem; font-weight: 700; padding: 0.5rem; margin: 0 2px; cursor: pointer; text-transform: capital letter; }
This is what your index.html should look like in the browser at present:
How to Accept User Input
The strategy for user input is unproblematic: when the thespian presses a primal on the keyboard, we want to identify that key in the right place on the board. You're going to reach this past listening for the keyup event.
When the actor presses a key, you want to find out what that primal was. If the key was a unmarried letter, you want to put information technology in the right spot on the lath.
Y'all figure out where the right spot on the board is by checking the number of guesses the actor has left and how many messages the player has entered and then far.
If the primal pressed was Enter or Backspace, you check the guess or delete one letter of the alphabet from the electric current gauge. Any other central we ignore.
Add this code to script.js:
document.addEventListener("keyup", (due east) => { if (guessesRemaining === 0) { render } allow pressedKey = String(eastward.key) if (pressedKey === "Backspace" && nextLetter !== 0) { deleteLetter() render } if (pressedKey === "Enter") { checkGuess() return } permit found = pressedKey.match(/[a-z]/gi) if (!plant || found.length > 1) { render } else { insertLetter(pressedKey) } })
The code uses a regular expression to check that the cardinal nosotros pressed was an alphabetical key representing a single letter. If the proper noun of the key doesn't have any letters (it was a number), or it has multiple letters (Shift, Tab), nosotros ignore the upshot. Otherwise, we insert the letter of the alphabet into the lath.
insertLetter
Permit'south ascertain the insertLetter
function. It looks similar this:
function insertLetter (pressedKey) { if (nextLetter === 5) { return } pressedKey = pressedKey.toLowerCase() permit row = document.getElementsByClassName("letter-row")[6 - guessesRemaining] let box = row.children[nextLetter] box.textContent = pressedKey box.classList.add("filled-box") currentGuess.push(pressedKey) nextLetter += ane }
insertLetter
checks that there's all the same infinite in the estimate for this letter, finds the appropriate row, and puts the letter in the box.
deleteLetter
deleteLetter
looks similar this:
function deleteLetter () { allow row = document.getElementsByClassName("letter-row")[6 - guessesRemaining] permit box = row.children[nextLetter - 1] box.textContent = "" box.classList.remove("filled-box") currentGuess.popular() nextLetter -= 1 }
deleteLetter
gets the correct row, finds the final box and empties it, and then resets the nextLetter counter.
checkGuess
The checkGuess
function looks like this:
function checkGuess () { permit row = document.getElementsByClassName("letter-row")[half-dozen - guessesRemaining] let guessString = '' permit rightGuess = Assortment.from(rightGuessString) for (const val of currentGuess) { guessString += val } if (guessString.length != five) { alert("Not enough letters!") render } if (!WORDS.includes(guessString)) { alarm("Give-and-take not in list!") return } for (let i = 0; i < 5; i++) { let letterColor = '' allow box = row.children[i] permit letter of the alphabet = currentGuess[i] let letterPosition = rightGuess.indexOf(currentGuess[i]) // is letter in the correct estimate if (letterPosition === -i) { letterColor = 'grey' } else { // now, letter is definitely in word // if letter index and right guess index are the same // letter is in the right position if (currentGuess[i] === rightGuess[i]) { // shade greenish letterColor = 'green' } else { // shade box yellowish letterColor = 'yellow' } rightGuess[letterPosition] = "#" } let delay = 250 * i setTimeout(()=> { //shade box box.style.backgroundColor = letterColor shadeKeyBoard(letter of the alphabet, letterColor) }, delay) } if (guessString === rightGuessString) { alert("You guessed right! Game over!") guessesRemaining = 0 return } else { guessesRemaining -= 1; currentGuess = []; nextLetter = 0; if (guessesRemaining === 0) { alert("You've run out of guesses! Game over!") alert(`The correct word was: "${rightGuessString}"`) } } }
checkGuess
is pretty long, then let's pause it down. It does a few things:
- Makes sure the guess is v letters
- Makes sure the guess is a valid list
- Checks each letter of the give-and-take and shades them
- Tells the user near the end of the game
checkGuess
uses a simple algorithm to decide what colour to shade each letter:
- Checks if the letter is in the correct word
- If the letter is non in the discussion, shades letter grey
- If the letter is in the word, check if it'due south in the right position
- If the alphabetic character is in the right position, shades dark-green
- Else, shades yellowish
checkGuess
uses a function shadeKeyboard
to color the keys of the on-screen keyboard, simply information technology'south not defined yet. Let's do that next.
shadeKeyboard
role shadeKeyBoard(alphabetic character, color) { for (const elem of document.getElementsByClassName("keyboard-push button")) { if (elem.textContent === letter) { permit oldColor = elem.style.backgroundColor if (oldColor === 'dark-green') { return } if (oldColor === 'yellow' && colour !== 'green') { render } elem.style.backgroundColor = colour intermission } } }
shadeKeyBoard
receives the letter of the alphabet on the on-screen keyboard we desire to shade and the colour we want to shade information technology. This is the algorithm:
- Find the key that matches the given letter
- If the central is already green, practise zip
- If the key is currently yellowish, just allow it to become light-green
- Else, shade the central passed to the role
How to Add Notifications
Next, you volition replace the JavaScript alerts in checkGuess
with toasts, using Toastr.
Go over checkGuess
, and replace all the alerts that notify the user of a mistake with calls to toastr.error()
.
The alert that notifies the user of a correct guess should be replaced with toastr.success()
, and the warning that tells the user what the right guess was should be replaced with toastr.info()
.
This is what checkGuess should look like after you're done:
function checkGuess () { permit row = certificate.getElementsByClassName("alphabetic character-row")[6 - guessesRemaining] let guessString = '' allow rightGuess = Array.from(rightGuessString) for (const val of currentGuess) { guessString += val } if (guessString.length != 5) { toastr.mistake("Not enough letters!") render } if (!WORDS.includes(guessString)) { toastr.error("Word not in list!") return } for (allow i = 0; i < five; i++) { let letterColor = '' let box = row.children[i] allow letter = currentGuess[i] let letterPosition = rightGuess.indexOf(currentGuess[i]) // is letter in the right approximate if (letterPosition === -1) { letterColor = 'grey' } else { // at present, letter is definitely in word // if letter of the alphabet index and right estimate index are the same // letter is in the correct position if (currentGuess[i] === rightGuess[i]) { // shade green letterColor = 'dark-green' } else { // shade box xanthous letterColor = 'yellow' } rightGuess[letterPosition] = "#" } let filibuster = 250 * i setTimeout(()=> { //shade box box.style.backgroundColor = letterColor shadeKeyBoard(letter, letterColor) }, delay) } if (guessString === rightGuessString) { toastr.success("Y'all guessed right! Game over!") guessesRemaining = 0 render } else { guessesRemaining -= ane; currentGuess = []; nextLetter = 0; if (guessesRemaining === 0) { toastr.error("You lot've run out of guesses! Game over!") toastr.info(`The correct word was: "${rightGuessString}"`) } } }
How to Make the On-screen Keyboard Generate Input
To go your on-screen keyboard functioning, all you have to do is dispatch a central up outcome whenever any key on your on-screen keyboard is clicked. To exercise that, add this code to script.js:
document.getElementById("keyboard-cont").addEventListener("click", (east) => { const target = e.target if (!target.classList.contains("keyboard-button")) { return } let key = target.textContent if (primal === "Del") { key = "Backspace" } document.dispatchEvent(new KeyboardEvent("keyup", {'cardinal': key})) })
This function listens for a click on the keyboard container or any of its children (the buttons). If the clicked element was not a button, we leave the function. Else, we dispatch a fundamental up event corresponding to the clicked key.
How to Add Animation
We already installed animate.css, so now permit's write a JavaScript function to use it.
const animateCSS = (chemical element, animation, prefix = 'animate__') => // We create a Promise and return it new Promise((resolve, reject) => { const animationName = `${prefix}${animation}`; // const node = certificate.querySelector(element); const node = element node.mode.setProperty('--breathing-duration', '0.3s'); node.classList.add(`${prefix}animated`, animationName); // When the animation ends, nosotros clean the classes and resolve the Promise function handleAnimationEnd(event) { event.stopPropagation(); node.classList.remove(`${prefix}animated`, animationName); resolve('Animation ended'); } node.addEventListener('animationend', handleAnimationEnd, {once: true}); });
This function comes from the Animate.css homepage. It applies classes to the animation target to trigger an animation, and when the animation ends, it removes the classes it added.
The role returns a promise to allow you to perform actions that need to run only afterwards the animation ends, but yous won't need to implement that in this tutorial.
At present that nosotros have a part to breathing whatever element, let's utilize it. Go back to our insertLetter
function, and add the following line before nosotros replace the textContent
of box
:
animateCSS(box, "pulse")
This is what insertLetter
should wait like now:
function insertLetter (pressedKey) { if (nextLetter === v) { return } pressedKey = pressedKey.toLowerCase() let row = document.getElementsByClassName("letter-row")[6 - guessesRemaining] let box = row.children[nextLetter] animateCSS(box, "pulse") box.textContent = pressedKey box.classList.add("filled-box") currentGuess.push button(pressedKey) nextLetter += ane }
The lawmaking tells insertLetter
to pulse each box rapidly, only before we make full information technology with a letter.
Next, y'all want to animate each letter of a guess while yous're checking it.
Get back and modify checkGuess
, like so:
permit delay = 250 * i setTimeout(()=> { //flip box animateCSS(box, 'flipInX') //shade box box.style.backgroundColor = letterColor shadeKeyBoard(letter, letterColor) }, delay)
This code adds an animation to flip each box vertically, just before we change the color.
Conclusion
That concludes the tutorial. You only built a Wordle clone, andI hope you had fun along the fashion. Yous tin detect the complete lawmaking at the GitHub repository for this project.
If y'all enjoyed this article, yous can find more of my writing at my here, or follow me on Twitter.
Acquire to code for free. freeCodeCamp'southward open source curriculum has helped more than than twoscore,000 people get jobs as developers. Go started
Source: https://www.freecodecamp.org/news/build-a-wordle-clone-in-javascript/
Posted by: bahrpossent.blogspot.com
0 Response to "How Can I Create An Animated Escape Game,css"
Post a Comment