javascript – How can i add a 'hidden' grid over canvas that has background picture?-ThrowExceptions

Exception or error:

I am making a html/js turn based game and I have created canvas element using javascript.
I have put a repeated background picture so it looks like a 10 X 10 squared board but want to put a grid over that so I can eventually make each ‘square’ clickable for characters to move, squares to light up upon hover etc.

How might I do that in the simplest way possible?

Thank you.

Here is the code I used to create the canvas in javascript:

var myGameArea = {
    canvas : document.createElement("canvas"),
    start : function() {
        this.canvas.width = 480;
        this.canvas.height = 480;
        this.canvas.style.cursor = "default"; 
        this.context = this.canvas.getContext("2d");
        document.body.append(this.canvas, document.body.childNodes[0]);
        this.frameNo = 0;
        this.interval = setInterval(updateGameArea, 20);
        window.addEventListener('onclick()', function (e) {
          myGameArea.x = e.pageX;
          myGameArea.y = e.pageY;
        })
How to solve:

Well, you could create an image with the grid and overlay that. Otherwise you can use lineTo to create a line on the grid. Then do that repeatedly to create a grid.

let canvas = <link to canvas>;
let context = canvas.getContext('2d');
let gridSize = 10;
let canvasSize = {
    width:400;
    height:400;
}
for(let i=0;i<canvasSize.height;i+=gridSize){
    context.beginPath();
    context.moveTo(i,0);
    context.lineTo(i,canvasSize.height);
    context.strokeStyle = "#222222";
    context.stroke();
}

for(let i=0;i<canvasSize.width;i+=gridSize){
    context.beginPath();
    context.moveTo(0,i);
    context.lineTo(canvasSize.width,i);
    context.strokeStyle = "#222222";
    context.stroke();
}

I recommend checking out: https://www.html5canvastutorials.com/tutorials/html5-canvas-lines/ I got a lot of help there when using canvases.

###

One way to achieve a grid overlay that allows your game to determine which grid cell was clicked, would be to generate separate DOM elements per cell of the grid where each cell is aligned/sized to the grid itself.

You could use CSS to define the common styling rules for each grid cell, and also use the :hover selector to define “hover” styling to reveal the cell that the user is hovering over:

/* Styling for each tile in grid with absolute 
position against relative wrapper */
.gameAreaWrapper a {
  display:block;
  position: absolute;
  width: 10%;
  height: 10%;
}

/* Cause visual feedback to user when
tile is hovered */
.gameAreaWrapper a:hover {
  background:rgba(255,255,0,0.5);
}

A function in your script would then use a nested loop to generate cells for the 10×10 grid like this:

function generateGameBoardSquares(wrapper) {

  for(let x = 0; x < 10; x++) {
    for(let y = 0; y < 10; y++) {

      /* Create the cell element */
      const cell = document.createElement("a");

      /* Position relative to top-left corner of parent */
      cell.style.left = `${x*10}%`
      cell.style.top = `${y*10}%`      

      /* Add cell to wrapper parent */
      wrapper.append(cell);
    }  
  }
}

Here’s a complete demo:

/* Define helper function that generates grid of square
elements across specified wrapper element */
function generateGameBoardSquares(wrapper) {

  function onClick(x,y) {
    alert(`You clicked ${x},${y}`);
  }

  for(let x = 0; x < 10; x++) {
    for(let y = 0; y < 10; y++) {
      
      const tile = document.createElement("a");
      tile.style.left = `${x*10}%`
      tile.style.top = `${y*10}%`      
      tile.addEventListener("click", () => onClick(x,y));
      
      wrapper.append(tile);
    }  
  }
}

var myGameArea = {
  canvas: document.createElement("canvas"),
  start: function() {
    this.canvas.width = 480;
    this.canvas.height = 480;
    this.canvas.style.cursor = "default";
    this.context = this.canvas.getContext("2d");

    const gameAreaWrapper = document.querySelector(".gameAreaWrapper");
    gameAreaWrapper.append(this.canvas);    
    
    /* Cause wrapper to perfectly wrap the canvas that we want 
    to align with */
    gameAreaWrapper.style.width = `${this.canvas.width}px`;
    gameAreaWrapper.style.height = `${this.canvas.height}px`;
    
    /* Generate grid cells */
    generateGameBoardSquares(gameAreaWrapper);

    this.frameNo = 0;
    /*
    this.interval = setInterval(updateGameArea, 20);
    */
    
    /* correct event name is "click" */
    window.addEventListener('click', function(e) {
      myGameArea.x = e.pageX;
      myGameArea.y = e.pageY;
    })
  }
}

myGameArea.start()
/* Added to show grid boundary */
canvas {
  background:rgba(255,0,0,0.1);
}

/* Style wrapper to support placement of 
each tile in grid with relative positioning */
.gameAreaWrapper {
  position: relative;
}

/* Styling for each tile in grid with absolute 
position against relative wrapper */
.gameAreaWrapper a {
  display:block;
  position: absolute;
  width: 10%;
  height: 10%;
}

/* Cause visual feedback to user when
tile is hovered */
.gameAreaWrapper a:hover {
  background:rgba(255,255,0,0.5);
}
<div class="gameAreaWrapper">
  <!--
  Added by your script
  <canvas />
-->
</div>

Hope this helps!

Leave a Reply

Your email address will not be published. Required fields are marked *