HomeUncategorisedFlags Game With Javascript

Flags Game With Javascript

Hey everyone. Welcome to today’s tutorial. In today’s tutorial, we will learn how to create a flags game. To build this project, you will need HTML, CSS and Javascript.

This is an intermediate-level javascript project. If you are looking for more projects to improve your javascript skills, you can check out this playlist here. This playlist consists of more than 100+ javascript projects. The difficulty of these projects varies from easy to quite complex.

Let us take a look at how this project works. We begin the game with a start screen. When the user clicks on the ‘Start Game’ button, we present the user with three random flag images.

Along with the flag images, we also provide empty boxes with corresponding country names. These boxes are placed in random order. To win this game, the user has to drag the flag images and drop them over the corresponding country-name box.

When all the three flags are in their right place, we display the win screen. The win screen consists of a ‘You Won’ message and a ‘Start Button.

Video Tutorial:

If you are interested to learn by watching a video tutorial rather than reading this blog post, you can watch the video down below. Also subscribe to my youtube channel where I post new tips, tricks and tutorials every alternate day.

Project Folder Structure:

Before we start coding let us take a look at the project folder structure. We create a project folder called – ‘Flags Game’. Inside this folder, we have three files. These files are – index.html, style.css and script.js. The first file is the HTML document, the next is the stylesheet and finally, we have the script file.

HTML:

We begin with the HTML code. First, copy the code below and paste it into your HTML document.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Flags Game</title>
    <!-- Google Fonts -->
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap"
      rel="stylesheet"
    />
    <!-- Stylesheet -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="container">
      <h3>Drag & Drop The Flags Over Their Respective Country Names</h3>
      <div class="draggable-objects"></div>
      <div class="drop-points"></div>
    </div>
    <div class="controls-container">
      <p id="result"></p>
      <button id="start">Start Game</button>
    </div>
    <!-- Script -->
    <script src="script.js"></script>
  </body>
</html>

CSS:

Next, we style our project with CSS. For this copy, the code provided to you below and paste it into your stylesheet.

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}
body {
  background-color: #5372ef;
}
.container {
  width: 90%;
  max-width: 37.5em;
  background-color: #ffffff;
  padding: 3em 0.5em;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 0.8em;
}
h3 {
  text-align: center;
  width: 60%;
  margin: 0 auto 2em auto;
  font-size: 1.2em;
  font-weight: 600;
  letter-spacing: 0.03em;
  line-height: 1.8em;
  color: #010c39;
}
.draggable-objects,
.drop-points {
  display: flex;
  justify-content: space-around;
  padding: 2em;
}
.draggable-image {
  width: 8em;
  cursor: move;
}
img {
  width: 8em;
  filter: drop-shadow(0 0.3em 0.9em rgba(0, 0, 0, 0.25));
}
.countries {
  width: 10em;
  height: 8em;
  display: grid;
  place-items: center;
  border: 0.25em dashed #010c39;
  border-radius: 0.8em;
}
.dropped {
  padding: 0;
  background-color: #e5ffc8;
}
.controls-container {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
  background-color: #5372ef;
  flex-direction: column;
  top: 0;
}
.controls-container button {
  font-size: 1.12em;
  padding: 0.8em 1em;
  border-radius: 0.2em;
  border: none;
  outline: none;
  color: #010c39;
  letter-spacing: 0.06em;
  cursor: pointer;
}
.controls-container p {
  color: #ffffff;
  font-size: 2em;
  margin-bottom: 1em;
}
.hide {
  display: none;
}

Javascript:

Finally, we add functionality using Javascript. For this copy the code below and paste it into your script file.

//Initial References
let draggableObjects;
let dropPoints;
const startButton = document.getElementById("start");
const result = document.getElementById("result");
const controls = document.querySelector(".controls-container");
const dragContainer = document.querySelector(".draggable-objects");
const dropContainer = document.querySelector(".drop-points");
const data = [
  "belgium",
  "bhutan",
  "brazil",
  "china",
  "cuba",
  "ecuador",
  "georgia",
  "germany",
  "hong-kong",
  "india",
  "iran",
  "myanmar",
  "norway",
  "spain",
  "sri-lanka",
  "sweden",
  "switzerland",
  "united-states",
  "uruguay",
  "wales",
];

let deviceType = "";
let initialX = 0,
  initialY = 0;
let currentElement = "";
let moveElement = false;

//Detect touch device
const isTouchDevice = () => {
  try {
    //We try to create Touch Event (It would fail for desktops and throw error)
    document.createEvent("TouchEvent");
    deviceType = "touch";
    return true;
  } catch (e) {
    deviceType = "mouse";
    return false;
  }
};

let count = 0;

//Random value from Array
const randomValueGenerator = () => {
  return data[Math.floor(Math.random() * data.length)];
};

//Win Game Display
const stopGame = () => {
  controls.classList.remove("hide");
  startButton.classList.remove("hide");
};

//Drag & Drop Functions
function dragStart(e) {
  if (isTouchDevice()) {
    initialX = e.touches[0].clientX;
    initialY = e.touches[0].clientY;
    //Start movement for touch
    moveElement = true;
    currentElement = e.target;
  } else {
    //For non touch devices set data to be transfered
    e.dataTransfer.setData("text", e.target.id);
  }
}

//Events fired on the drop target
function dragOver(e) {
  e.preventDefault();
}

//For touchscreen movement
const touchMove = (e) => {
  if (moveElement) {
    e.preventDefault();
    let newX = e.touches[0].clientX;
    let newY = e.touches[0].clientY;
    let currentSelectedElement = document.getElementById(e.target.id);
    currentSelectedElement.parentElement.style.top =
      currentSelectedElement.parentElement.offsetTop - (initialY - newY) + "px";
    currentSelectedElement.parentElement.style.left =
      currentSelectedElement.parentElement.offsetLeft -
      (initialX - newX) +
      "px";
    initialX = newX;
    initialY - newY;
  }
};

const drop = (e) => {
  e.preventDefault();
  //For touch screen
  if (isTouchDevice()) {
    moveElement = false;
    //Select country name div using the custom attribute
    const currentDrop = document.querySelector(`div[data-id='${e.target.id}']`);
    //Get boundaries of div
    const currentDropBound = currentDrop.getBoundingClientRect();
    //if the position of flag falls inside the bounds of the countru name
    if (
      initialX >= currentDropBound.left &&
      initialX <= currentDropBound.right &&
      initialY >= currentDropBound.top &&
      initialY <= currentDropBound.bottom
    ) {
      currentDrop.classList.add("dropped");
      //hide actual image
      currentElement.classList.add("hide");
      currentDrop.innerHTML = ``;
      //Insert new img element
      currentDrop.insertAdjacentHTML(
        "afterbegin",
        `<img src= "${currentElement.id}.png">`
      );
      count += 1;
    }
  } else {
    //Access data
    const draggedElementData = e.dataTransfer.getData("text");
    //Get custom attribute value
    const droppableElementData = e.target.getAttribute("data-id");
    if (draggedElementData === droppableElementData) {
      const draggedElement = document.getElementById(draggedElementData);
      //dropped class
      e.target.classList.add("dropped");
      //hide current img
      draggedElement.classList.add("hide");
      //draggable set to false
      draggedElement.setAttribute("draggable", "false");
      e.target.innerHTML = ``;
      //insert new img
      e.target.insertAdjacentHTML(
        "afterbegin",
        `<img src="${draggedElementData}.png">`
      );
      count += 1;
    }
  }
  //Win
  if (count == 3) {
    result.innerText = `You Won!`;
    stopGame();
  }
};

//Creates flags and countries
const creator = () => {
  dragContainer.innerHTML = "";
  dropContainer.innerHTML = "";
  let randomData = [];
  //for string random values in array
  for (let i = 1; i <= 3; i++) {
    let randomValue = randomValueGenerator();
    if (!randomData.includes(randomValue)) {
      randomData.push(randomValue);
    } else {
      //If value already exists then decrement i by 1
      i -= 1;
    }
  }
  for (let i of randomData) {
    const flagDiv = document.createElement("div");
    flagDiv.classList.add("draggable-image");
    flagDiv.setAttribute("draggable", true);
    if (isTouchDevice()) {
      flagDiv.style.position = "absolute";
    }
    flagDiv.innerHTML = `<img src="${i}.png" id="${i}">`;
    dragContainer.appendChild(flagDiv);
  }
  //Sort the array randomly before creating country divs
  randomData = randomData.sort(() => 0.5 - Math.random());
  for (let i of randomData) {
    const countryDiv = document.createElement("div");
    countryDiv.innerHTML = `<div class='countries' data-id='${i}'>
    ${i.charAt(0).toUpperCase() + i.slice(1).replace("-", " ")}
    </div>
    `;
    dropContainer.appendChild(countryDiv);
  }
};

//Start Game
startButton.addEventListener(
  "click",
  (startGame = async () => {
    currentElement = "";
    controls.classList.add("hide");
    startButton.classList.add("hide");
    //This will wait for creator to create the images and then move forward
    await creator();
    count = 0;
    dropPoints = document.querySelectorAll(".countries");
    draggableObjects = document.querySelectorAll(".draggable-image");

    //Events
    draggableObjects.forEach((element) => {
      element.addEventListener("dragstart", dragStart);
      //for touch screen
      element.addEventListener("touchstart", dragStart);
      element.addEventListener("touchend", drop);
      element.addEventListener("touchmove", touchMove);
    });
    dropPoints.forEach((element) => {
      element.addEventListener("dragover", dragOver);
      element.addEventListener("drop", drop);
    });
  })
);

That’s it for this tutorial. If you face any issues while creating this project you can download the source code by clicking on the ‘Download Code’ button below. Also, I would love to hear from you guys. So if you have any queries, suggestions or feedback you can comment below.
Happy Coding!

Previous articleMCQ – 18/8/22
Next articleMCQ – 20/8/22
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

eight + 2 =

Most Popular