Yorg Yorg - 4 months ago 9
Javascript Question

Select an array?

So I'm a bit stuck making a game here.

I have a canvas, and within that canvas I have an array to hold all of my enemies. I want it so that if you click on ONE enemy in the array, ONLY that enemy will die.

My problem lies with the click event. I want the enemy to die when clicked on, but I can't seem to get any click event (including event listeners or onclick methods) to work for my defined array.

So my final question here is: is there a way to make any item in an array clickable?

Answer

The canvas element only response to the click event of the canvas. We can get the coordinates of the mouse, but we need to compare the coordinates of the mouse and the items on the canvas ourselves.

In the snippet below I've created a basic example with 3 enemies as simply balls. When you click a ball it removes that enemy from the array and redraws them to the screen. Now, if we simply compare the exact coordinates of the mouse and a enemy it would be quite hard to click them. As you need to click the exact pixel of the x,y position of the enemy. For circular enemies we can find the "circle" of the clicked enemy by using the distance formula and the radius of the enemy. I've noted that in a function called selectEnemy():

function selectEnemy(X, Y){
    for(var i = 0; i < enemies.length; i++) {
        if(dist(X, Y, enemies[i].x, enemies[i].y ) < enemies[i].r) return i;
  }
  return -1;
}

What this does is compare the mouse coordinates X,Y in this example, to each of the enemies coordinates. If we clicked on the enemy (the distance from the center of the enemy is less than their radius), then this will return their index position in the array. If none of them where clicked we return -1. Later we can use that index to remove them from the array:

...
// Get the enemy the mouse clicked
var removal = selectEnemy(canvasX, canvasY);
// If we clicked a enemy, remove it from the array
if (removal > -1) enemies.splice(removal, 1);
...

The full snippet example is below:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var enemies = [new Enemy(100,100,10), new Enemy(200,100,10), new Enemy(300,100,10)];

canvas.addEventListener("click", function(e) 
{ 
  var cRect = canvas.getBoundingClientRect();
  // Get the mouse coords
  var canvasX = e.clientX - cRect.left;
  var canvasY = e.clientY - cRect.top;
  // clear the canvas
  ctx.clearRect(0,0,canvas.width,canvas.height);
  // Get the enemy the mouse clicked
  var removal = selectEnemy(canvasX, canvasY);
  // If we clicked a enemey, remove it from the array
  if (removal > -1) enemies.splice(removal, 1);
  // Draw the enemies from the array
  drawAll();
});

function Enemy(x, y, r) {
   this.x = x;
   this.y = y;
   this.r = r;
   
   this.draw = function() {
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
      ctx.fillStyle = 'red';
      ctx.fill();
   }
}

function selectEnemy(X, Y){
    for(var i = 0; i < enemies.length; i++) {
        if(dist(X, Y, enemies[i].x, enemies[i].y ) < enemies[i].r) return i;
    }
    return -1;
}

function drawAll() {
    for(var i = 0; i < enemies.length; i++) enemies[i].draw();
}

function dist(x1, y1, x2, y2) {
    return Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
}
drawAll();
#canvas{ 
  border: 1px solid black; 
}
<canvas id="canvas" width=400 height=200></canvas>

Comments