Build a Scratch Card Web Game

JavaScriptJavaScriptBeginner
Practice Now

Introduction

In this project, we will guide you through the process of creating a simple web-based Scratch Card game. This game allows users to scratch off a gray overlay to reveal an underlying image, which will either be a "winner" or a "try again" message. We will use HTML for the structure, CSS for styling, and JavaScript for interactivity.

👀 Preview

🎯 Tasks

In this project, you will learn:

  • How to set up a basic web project with HTML, CSS, and JavaScript
  • How to manipulate the HTML5 canvas to create interactive effects
  • How to use JavaScript to handle user interactions such as mouse clicks and movements
  • How to work with images in web development, including loading and displaying them dynamically
  • How to implement a simple game logic that randomly decides the outcome for the user

🏆 Achievements

After completing this project, you will be able to:

  • Demonstrate a solid understanding of the HTML5 canvas and its capabilities for web-based games and interactive applications
  • Showcase proficiency in using JavaScript to create dynamic content and respond to user inputs
  • Integrate various web technologies to create a complete and functional web application
  • Design a simple yet engaging user interface for a web-based game
  • Apply basic game development concepts such as random outcomes and user interaction

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL css(("`CSS`")) -.-> css/CoreLayoutGroup(["`Core Layout`"]) css(("`CSS`")) -.-> css/IntermediateStylingGroup(["`Intermediate Styling`"]) html(("`HTML`")) -.-> html/BasicStructureGroup(["`Basic Structure`"]) javascript(("`JavaScript`")) -.-> javascript/BasicConceptsGroup(["`Basic Concepts`"]) javascript(("`JavaScript`")) -.-> javascript/AdvancedConceptsGroup(["`Advanced Concepts`"]) javascript(("`JavaScript`")) -.-> javascript/DOMManipulationGroup(["`DOM Manipulation`"]) css/CoreLayoutGroup -.-> css/positioning("`Positioning`") css/IntermediateStylingGroup -.-> css/backgrounds("`Backgrounds`") html/BasicStructureGroup -.-> html/basic_elems("`Basic Elements`") html/BasicStructureGroup -.-> html/head_elems("`Head Elements`") javascript/BasicConceptsGroup -.-> javascript/variables("`Variables`") javascript/BasicConceptsGroup -.-> javascript/arith_ops("`Arithmetic Operators`") javascript/BasicConceptsGroup -.-> javascript/array_methods("`Array Methods`") javascript/BasicConceptsGroup -.-> javascript/obj_manip("`Object Manipulation`") javascript/AdvancedConceptsGroup -.-> javascript/async_prog("`Asynchronous Programming`") javascript/DOMManipulationGroup -.-> javascript/dom_select("`DOM Selection`") javascript/DOMManipulationGroup -.-> javascript/event_handle("`Event Handling`") subgraph Lab Skills css/positioning -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} css/backgrounds -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} html/basic_elems -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} html/head_elems -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} javascript/variables -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} javascript/arith_ops -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} javascript/array_methods -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} javascript/obj_manip -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} javascript/async_prog -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} javascript/dom_select -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} javascript/event_handle -.-> lab-298999{{"`Build a Scratch Card Web Game`"}} end

Create the HTML Structure

In this step, we set up the basic structure of the web page in index.html, including the DOCTYPE declaration, the html element, and the head and body sections. We define the character set as UTF-8 for universal character recognition and set the viewport for responsive design, ensuring that our scratch card application looks good on devices of varying sizes.

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Scratch Card</title>
  </head>
  <body>
    <div id="main">
      <div class="msg">
        Feeling Lucky? Try!
        <a href="#" onclick="window.location.reload()">Try Again</a>
      </div>
      <div>
        <canvas></canvas>
      </div>
    </div>
    <script src="main.js"></script>
  </body>
</html>

Inside the body, we create a div element with an id of "main" that serves as the container for our application. Within this container, we include a div with a class of "msg" to display a playful message inviting the user to try their luck. This message also includes a link that, when clicked, reloads the page, allowing users to try the scratch card again without having to manually refresh the browser.

Finally, we include a canvas element where the scratch card effect will be implemented, and we link an external JavaScript file named "main.js" where our application's logic will reside.

This HTML structure provides the necessary foundation for our scratch card application, defining the areas where text and the scratchable surface will be displayed.

Style the Canvas

In the main.js JavaScript file, we start by selecting the canvas element and applying some initial styles.

const canvas = document.querySelector("canvas");
canvas.style.backgroundColor = "transparent";
canvas.style.position = "absolute";

We set the backgroundColor to "transparent" to ensure that the canvas background doesn't obscure any part of the web page it's placed on. By setting the position to "absolute", we allow more flexibility in positioning the canvas over other elements if needed.

This step is crucial for preparing the canvas element, ensuring it integrates seamlessly with the rest of the web page's design and is ready for the dynamic elements we'll add to it in subsequent steps.

Load the Scratch Image

Here, we load a random image to be used as the scratch card background.

// Continue in main.js

// Array of possible images to reveal
const images = ["winner.png", "try_again.png"];
const selectedImage = images[Math.floor(Math.random() * images.length)];

// Create a new Image object and set the source
const img = new Image();
img.src = selectedImage;

// Once the image is loaded, adjust canvas size and background
img.onload = () => {
  const ctx = canvas.getContext("2d");
  const w = img.width;
  const h = img.height;
  canvas.width = w;
  canvas.height = h;
  canvas.style.backgroundImage = `url(${img.src})`;

We create an array named images containing the filenames of possible images. Then, we randomly select one image from this array using Math.floor(Math.random() * images.length).

We create a new Image object and set its source (src) to the chosen image. The onload event listener ensures that we only proceed with the rest of the script once the image is fully loaded, preventing any issues that might arise from trying to manipulate an image that hasn't been completely downloaded.

This step is crucial for the dynamic nature of the scratch card, as it introduces variability and surprise each time the application is loaded or refreshed. By loading a random image, we simulate the uncertain outcome of a real scratch card, enhancing the user experience.

Prepare the Scratch Layer

After loading the selected image onto the canvas, we need to prepare the scratch layer. This is achieved by covering the entire canvas with a gray rectangle. This gray layer serves as the scratchable surface that the user will interact with to reveal the image underneath.

// Continue in main.js

// Cover the canvas with a gray rectangle to act as the scratch layer
ctx.fillStyle = "gray";
ctx.fillRect(0, 0, w, h);

// Prepare the canvas for the scratching effect
ctx.globalCompositeOperation = "destination-out";

In this step, we set the fill style to gray and draw a rectangle covering the entire canvas, creating a scratch-off layer over the selected image. The globalCompositeOperation set to "destination-out" ensures that any new drawing on the canvas will make the underlying layers transparent, allowing the image underneath to be revealed wherever the user scratches.

Create the Scratch Function

To implement the scratch effect, we define a draw function that will be called whenever the user interacts with the canvas. This function checks if the user is currently drawing (isDrawing flag) and then calculates the position of the cursor or touch relative to the canvas. It then draws a circle at this position with a composite operation that makes the gray layer transparent, revealing the image below.

// Continue in main.js

let isDrawing = false;

// Define the function to simulate scratching
const draw = (e) => {
  if (!isDrawing) return;
  e.preventDefault();
  const clientX = e.clientX || e.touches[0].clientX;
  const clientY = e.clientY || e.touches[0].clientY;
  const rect = canvas.getBoundingClientRect();
  const x = clientX - rect.left;
  const y = clientY - rect.top;

  // Draw a circle at the cursor or touch position
  ctx.beginPath();
  ctx.arc(x, y, 10, 0, Math.PI * 2);
  ctx.fill();
};

This function first ensures that the isDrawing flag is true, indicating that the user has initiated a scratch action. It then calculates the precise position where the scratch is occurring and draws a circle at that position, effectively scratching off the gray layer to reveal parts of the underlying image.

Add Event Listeners for Scratch Actions

Finally, we need to detect when the user performs actions on the canvas to trigger the scratch effect.

// Continue in main.js

  // Event listeners to handle mouse and touch interactions
  canvas.addEventListener("mousedown", (e) => {
    isDrawing = true;
    draw(e);
  });
  canvas.addEventListener("touchstart", (e) => {
    isDrawing = true;
    draw(e);
  });
  canvas.addEventListener("mousemove", draw);
  canvas.addEventListener("touchmove", draw);
  canvas.addEventListener("mouseup", () => {
    isDrawing = false;
  });
  canvas.addEventListener("touchend", () => {
    isDrawing = false;
  });
}

We add event listeners for mousedown, mousemove, mouseup, touchstart, touchmove, and touchend. These listeners set the isDrawing flag and call the draw function accordingly to create an interactive scratch effect.

When the user presses the mouse button or touches the screen (mousedown or touchstart), we set isDrawing to true and start tracking their movement to create the scratch effect. When they release the button or stop touching the screen (mouseup or touchend), we set isDrawing to false, stopping the scratching action. The mousemove and touchmove events continue to call the draw function as long as isDrawing is true, allowing the user to scratch off the gray layer and reveal the image beneath as they move their mouse or finger over the canvas.

To see the following effects, click on Go Live button in the bottom right corner of WebIDE, and switch to the "Web 8080" tab.

Summary

In this project, we've created a simple Scratch Card game where users can scratch off a layer to reveal a hidden message. We set up the HTML structure, initialized the canvas in JavaScript, loaded and displayed images, and implemented the scratch effect using the canvas API. This project can be a fun addition to web pages and can be extended in various ways, such as adding more images, improving the design, or integrating it into a larger game.

Other JavaScript Tutorials you may like