Creating a Candy Crush Clone: HTML, CSS, and JavaScript Tutorial (Source Code)

Faraz

By Faraz -

Turn your game development dreams into reality! Learn HTML, CSS, and JavaScript to build your Candy Crush clone from scratch with our comprehensive guide.


Creating a Candy Crush Clone HTML, CSS, and JavaScript Tutorial.jpg

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Preview
  6. Conclusion

Welcome, aspiring game developers and coding enthusiasts! In the vibrant realm of web development, creating your own interactive games is both an art and a thrilling adventure. In this comprehensive guide, we will embark on a journey together to build a Candy Crush clone from scratch using the powerful trio of HTML, CSS, and JavaScript.

Unleashing the Power of Web Technologies

Candy Crush, with its addictive gameplay and vibrant visuals, has captured the hearts of millions. Now, it's your turn to dive into the world of game development and bring your creative ideas to life. Whether you're a beginner eager to learn the basics or a seasoned coder looking for a new project, this tutorial is designed to cater to all skill levels.

What Lies Ahead

Our guide will take you step by step through the process, from setting up the basic HTML structure to adding interactive elements with JavaScript and enhancing the visual appeal using CSS.

So, grab your coding tools, unleash your imagination, and let's begin the exciting journey of crafting your very own Candy Crush clone. By the end of this tutorial, you'll not only have a functional game but also a solid foundation in web game development. Let's code and conquer!

Source Code

Step 1 (HTML Code):

To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our game.

After creating the files just paste the following codes into your file. Make sure to save your HTML document with a .html extension, so that it can be properly viewed in a web browser.

Let's break down the code:

1. <!DOCTYPE html>: This declaration defines the document type and version of HTML being used. In this case, it indicates an HTML5 document.

2. <html lang="en" dir="ltr">: This is the root element of the HTML document. The lang attribute is set to "en" (English), indicating the language of the document. The dir attribute is set to "ltr" (left-to-right), indicating the text direction.

3. <head>: This section contains meta-information about the document, such as the character set, title, stylesheets, and scripts.

  • <meta charset="utf-8">: This meta tag sets the character encoding of the document to UTF-8, which is a widely used character encoding for the web.
  • <title>JS Candy Crush</title>: This sets the title of the web page to "JS Candy Crush," which is typically displayed in the browser's title bar or tab.
  • <link rel="stylesheet" href="style.css">: This link tag includes an external stylesheet named "style.css." This stylesheet is used to define the presentation (styles) of the HTML document.
  • <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400&display=swap" rel="stylesheet">: This link tag includes an external stylesheet from Google Fonts. It imports the Montserrat font in weights 300 and 400 for use in the web page.
  • <script src="script.js" charset="utf-8"></script>: This script tag includes an external JavaScript file named "script.js." This JavaScript file contains the logic and functionality for the web page.

4. <body>: This is the main content of the HTML document.

5. <div class="scoreBoard">: This div element represents a container with the class "scoreBoard." It contains elements related to scoring in a game.

  • <h3>score</h3>: This heading element (h3) contains the text "score."
  • <h1 id="score"></h1>: This heading element (h1) with the id "score" is a placeholder for displaying the actual score. The content of this element will be dynamically updated using JavaScript.

6. <div class="grid"></div>: This div element represents a container with the class "grid." It is used to create a grid layout for the game, possibly for displaying candies in a Candy Crush-like game.

This is the basic structure of our Candy Crush clone using HTML, and now we can move on to styling it using CSS.

Step 2 (CSS Code):

Once the basic HTML structure of the clone game is in place, the next step is to add styling to the clone game using CSS.

Next, we will create our CSS file. In this file, we will use some basic CSS rules to style our clone game. Let's break down the code section by section:

1. .grid:

  • display: flex;: This property turns the container into a flex container, enabling the use of flex properties for its children.
  • flex-wrap: wrap;: This allows the flex items (children) to wrap onto multiple lines if they exceed the container's width.
  • height: 560px;: Sets the height of the container to 560 pixels.
  • min-width: 560px;: Specifies the minimum width of the container to be 560 pixels.
  • margin-left: 80px;: Adds a left margin of 80 pixels to the container.
  • margin-top: 50px;: Adds a top margin of 50 pixels to the container.
  • background-color: rgba(109, 127, 151, 0.5);: Sets the background color of the container with an RGBA value (semi-transparent blue).
  • padding: 5px;: Adds 5 pixels of padding to the container.
  • color: #85796b;: Sets the text color inside the container to a specific shade of brown.
  • border-radius: 10px;: Rounds the corners of the container by 10 pixels.
  • box-shadow: ...;: Adds a box shadow to the container for a visual effect. It includes an inset shadow and a shadow with a white color.

2. .grid div:

  • This selector targets the div elements inside the container with the class .grid.
  • height: 70px;: Sets the height of these div elements to 70 pixels.
  • width: 70px;: Sets the width of these div elements to 70 pixels.

3. h3 and h1:

  • These selectors style h3 and h1 HTML heading elements.
  • font-family: "Montserrat", sans-serif;: Specifies the font family for these elements.
  • text-transform: uppercase;: Transforms the text to uppercase.

4. .invisible:

  • This class is defined but not used in the provided code. If applied to an element, it would set the background color to white.

5. body:

  • background-image: url('...');: Sets the background image of the entire webpage to the specified URL.
  • max-width: 100vh;: Sets the maximum width of the body to 100 viewport heights.
  • display: flex;: Turns the body into a flex container.

6. .scoreBoard:

  • Defines styles for an element with the class .scoreBoard.
  • background-color: cyan;: Sets the background color of the element to cyan.
  • border-radius: 20px;: Rounds the corners of the element by 20 pixels.
  • margin-top: 200px;: Adds a top margin of 200 pixels to the element.
  • margin-left: 200px;: Adds a left margin of 200 pixels to the element.
  • width: auto;: Allows the element to have a width determined by its content.
  • height: 120px;: Sets the height of the element to 120 pixels.
  • padding: 20px;: Adds 20 pixels of padding to the element.
  • display: flex;: Turns the element into a flex container.
  • flex-direction: column;: Arranges the children of the flex container in a column.
  • justify-content: space-between;: Distributes the children with space between them along the column axis.
  • align-items: center;: Centers the children along the cross axis.
  • text-align: center;: Centers the text inside the element.
  • color: #85796b;: Sets the text color inside the element to a specific shade of brown.

This will give our Candy Crush clone game an upgraded presentation. Create a CSS file with the name of styles.css and paste the given codes into your CSS file. Remember that you must create a file with the .css extension.

.grid {
  display: flex;
  flex-wrap: wrap;
  height: 560px;
  min-width: 560px;
  margin-left: 80px;
  margin-top: 50px;
  background-color: rgba(109, 127, 151, 0.5);
  padding: 5px;
  color: #85796b;
  border-radius: 10px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5) inset, 0 1px 0 #fff;
}

.grid div {
  height: 70px;
  width: 70px;
}

h3 {
  font-family: "Montserrat", sans-serif;
  text-transform: uppercase;
}

h1 {
  font-family: "Montserrat", sans-serif;
  text-transform: uppercase;
  margin-top: -10px;
}

.invisible {
  background-color: white;
}

body {
  background-image: url('https://raw.githubusercontent.com/arpit456jain/Amazing-Js-Projects/master/Candy%20Crush/utils/bg.png');
  max-width: 100vh;
  display: flex;
}

.scoreBoard {
  background-color: cyan;
  border-radius: 20px;
  margin-top: 200px;
  margin-left: 200px;
  width: auto;
  height: 120px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  text-align: center;
  color: #85796b;
} 

Step 3 (JavaScript Code):

Finally, we need to create a function in JavaScript. Let's break down the code into sections:

1. Initialization:

  • The code starts with an event listener that waits for the DOM to be fully loaded before calling the candyCrushGame function.

2. candyCrushGame Function:

  • This function sets up the Candy Crush game by creating the game board, defining the initial variables, and handling drag-and-drop events for candies.
  • It creates an 8x8 grid and fills it with candies of different colors. The candies are represented by div elements with background images.
  • Event listeners are added to each candy div for drag-and-drop functionality. The drag-and-drop events include dragstart, dragend, dragover, dragenter, dragleave, and drop.
  • The function also defines variables to store information about the candies being dragged, replaced, and the corresponding square IDs.
  • The dragDrop function swaps the background images of the dragged and dropped candies.
  • The dragEnd function determines the validity of the move and updates the background images accordingly.
  • The moveIntoSquareBelow function is responsible for dropping candies into empty squares below when candies are cleared.

3. Checking for Matches:

  • The code includes functions to check for matches in the game board. Matches can be in rows or columns of three or four candies.
  • Functions like checkRowForFour, checkColumnForFour, checkRowForThree, and checkColumnForThree iterate through the grid, identify matching candies, and remove them.
  • The score is updated based on the number of candies cleared.

4. Interval Function:

  • The setInterval function is used to repeatedly check for matches and move candies down every 100 milliseconds.

Create a JavaScript file with the name script.js and paste the given codes into your JavaScript file and make sure it's linked properly to your HTML document so that the scripts are executed on the page. Remember, you’ve to create a file with .js extension.

document.addEventListener("DOMContentLoaded", () => {
    candyCrushGame();
});

function candyCrushGame() {
    const grid = document.querySelector(".grid");
    const scoreDisplay = document.getElementById("score");
    const width = 8;
    const squares = [];
    let score = 0;

    const candyColors = [
        "url(https://raw.githubusercontent.com/arpit456jain/Amazing-Js-Projects/master/Candy%20Crush/utils/red-candy.png)",
        "url(https://raw.githubusercontent.com/arpit456jain/Amazing-Js-Projects/master/Candy%20Crush/utils/blue-candy.png)",
        "url(https://raw.githubusercontent.com/arpit456jain/Amazing-Js-Projects/master/Candy%20Crush/utils/green-candy.png)",
        "url(https://raw.githubusercontent.com/arpit456jain/Amazing-Js-Projects/master/Candy%20Crush/utils/yellow-candy.png)",
        "url(https://raw.githubusercontent.com/arpit456jain/Amazing-Js-Projects/master/Candy%20Crush/utils/orange-candy.png)",
        "url(https://raw.githubusercontent.com/arpit456jain/Amazing-Js-Projects/master/Candy%20Crush/utils/purple-candy.png)",
    ];

    // Creating Game Board
    function createBoard() {
        for (let i = 0; i < width * width; i++) {
            const square = document.createElement("div");
            square.setAttribute("draggable", true);
            square.setAttribute("id", i);
            let randomColor = Math.floor(Math.random() * candyColors.length);
            square.style.backgroundImage = candyColors[randomColor];
            grid.appendChild(square);
            squares.push(square);
        }
    }
    createBoard();

    // Dragging the Candy
    let colorBeingDragged;
    let colorBeingReplaced;
    let squareIdBeingDragged;
    let squareIdBeingReplaced;

    squares.forEach((square) =>
        square.addEventListener("dragstart", dragStart)
    );
    squares.forEach((square) => square.addEventListener("dragend", dragEnd));
    squares.forEach((square) => square.addEventListener("dragover", dragOver));
    squares.forEach((square) =>
        square.addEventListener("dragenter", dragEnter)
    );
    squares.forEach((square) =>
        square.addEventListener("drageleave", dragLeave)
    );
    squares.forEach((square) => square.addEventListener("drop", dragDrop));

    function dragStart() {
        colorBeingDragged = this.style.backgroundImage;
        squareIdBeingDragged = parseInt(this.id);
        // this.style.backgroundImage = ''
    }

    function dragOver(e) {
        e.preventDefault();
    }

    function dragEnter(e) {
        e.preventDefault();
    }

    function dragLeave() {
        this.style.backgroundImage = "";
    }

    function dragDrop() {
        colorBeingReplaced = this.style.backgroundImage;
        squareIdBeingReplaced = parseInt(this.id);
        this.style.backgroundImage = colorBeingDragged;
        squares[
            squareIdBeingDragged
        ].style.backgroundImage = colorBeingReplaced;
    }

    function dragEnd() {
        //Defining, What is a valid move?
        let validMoves = [
            squareIdBeingDragged - 1,
            squareIdBeingDragged - width,
            squareIdBeingDragged + 1,
            squareIdBeingDragged + width
        ];
        let validMove = validMoves.includes(squareIdBeingReplaced);

        if (squareIdBeingReplaced && validMove) {
            squareIdBeingReplaced = null;
        } else if (squareIdBeingReplaced && !validMove) {
            squares[
                squareIdBeingReplaced
            ].style.backgroundImage = colorBeingReplaced;
            squares[
                squareIdBeingDragged
            ].style.backgroundImage = colorBeingDragged;
        } else
            squares[
                squareIdBeingDragged
            ].style.backgroundImage = colorBeingDragged;
    }

    //Dropping candies once some have been cleared
    function moveIntoSquareBelow() {
        for (i = 0; i < 55; i++) {
            if (squares[i + width].style.backgroundImage === "") {
                squares[i + width].style.backgroundImage =
                    squares[i].style.backgroundImage;
                squares[i].style.backgroundImage = "";
                const firstRow = [0, 1, 2, 3, 4, 5, 6, 7];
                const isFirstRow = firstRow.includes(i);
                if (isFirstRow && squares[i].style.backgroundImage === "") {
                    let randomColor = Math.floor(
                        Math.random() * candyColors.length
                    );
                    squares[i].style.backgroundImage = candyColors[randomColor];
                }
            }
        }
    }

    ///-> Checking for Matches <-///

    //For Row of Four
    function checkRowForFour() {
        for (i = 0; i < 60; i++) {
            let rowOfFour = [i, i + 1, i + 2, i + 3];
            let decidedColor = squares[i].style.backgroundImage;
            const isBlank = squares[i].style.backgroundImage === "";

            const notValid = [
                5,
                6,
                7,
                13,
                14,
                15,
                21,
                22,
                23,
                29,
                30,
                31,
                37,
                38,
                39,
                45,
                46,
                47,
                53,
                54,
                55
            ];
            if (notValid.includes(i)) continue;

            if (
                rowOfFour.every(
                    (index) =>
                        squares[index].style.backgroundImage === decidedColor &&
                        !isBlank
                )
            ) {
                score += 4;
                scoreDisplay.innerHTML = score;
                rowOfFour.forEach((index) => {
                    squares[index].style.backgroundImage = "";
                });
            }
        }
    }
    checkRowForFour();

    //For Column of Four
    function checkColumnForFour() {
        for (i = 0; i < 39; i++) {
            let columnOfFour = [i, i + width, i + width * 2, i + width * 3];
            let decidedColor = squares[i].style.backgroundImage;
            const isBlank = squares[i].style.backgroundImage === "";

            if (
                columnOfFour.every(
                    (index) =>
                        squares[index].style.backgroundImage === decidedColor &&
                        !isBlank
                )
            ) {
                score += 4;
                scoreDisplay.innerHTML = score;
                columnOfFour.forEach((index) => {
                    squares[index].style.backgroundImage = "";
                });
            }
        }
    }
    checkColumnForFour();

    //For Row of Three
    function checkRowForThree() {
        for (i = 0; i < 61; i++) {
            let rowOfThree = [i, i + 1, i + 2];
            let decidedColor = squares[i].style.backgroundImage;
            const isBlank = squares[i].style.backgroundImage === "";

            const notValid = [
                6,
                7,
                14,
                15,
                22,
                23,
                30,
                31,
                38,
                39,
                46,
                47,
                54,
                55
            ];
            if (notValid.includes(i)) continue;

            if (
                rowOfThree.every(
                    (index) =>
                        squares[index].style.backgroundImage === decidedColor &&
                        !isBlank
                )
            ) {
                score += 3;
                scoreDisplay.innerHTML = score;
                rowOfThree.forEach((index) => {
                    squares[index].style.backgroundImage = "";
                });
            }
        }
    }
    checkRowForThree();

    //For Column of Three
    function checkColumnForThree() {
        for (i = 0; i < 47; i++) {
            let columnOfThree = [i, i + width, i + width * 2];
            let decidedColor = squares[i].style.backgroundImage;
            const isBlank = squares[i].style.backgroundImage === "";

            if (
                columnOfThree.every(
                    (index) =>
                        squares[index].style.backgroundImage === decidedColor &&
                        !isBlank
                )
            ) {
                score += 3;
                scoreDisplay.innerHTML = score;
                columnOfThree.forEach((index) => {
                    squares[index].style.backgroundImage = "";
                });
            }
        }
    }
    checkColumnForThree();


    window.setInterval(function () {
        checkRowForFour();
        checkColumnForFour();
        checkRowForThree();
        checkColumnForThree();
        moveIntoSquareBelow();
    }, 100);
}

Final Output:

Creating a Candy Crush Clone HTML, CSS, and JavaScript Tutorial.gif

Conclusion:

Congratulations on completing this exhilarating journey into the world of game development! We've covered the essential steps in creating a Candy Crush clone using HTML, CSS, and JavaScript.

As you wrap up this tutorial, remember that your journey in game development doesn't end here. Use the knowledge and skills you've gained to explore further, experiment with new features, and unleash your creativity. Game development is a dynamic field, and there's always more to learn and discover.

On behalf of the coding community and enthusiasts worldwide, we extend our gratitude for embarking on this adventure with us. We hope this guide has not only equipped you with technical know-how but has also sparked a passion for creating innovative and captivating web games.

As you step into the future of game development, remember that every line of code is a stroke on the canvas of your imagination. Keep coding, keep creating, and may your journey be filled with endless possibilities. Happy coding!

Credit: arpit456jain

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post