Ballo Adam
Ballo Adam

Reputation: 105

p5.js collision between array elements

I am learning p5.js and I have come upon a problem that I cannot yet solve. So I'm making this little game in which you have to shoot the enemies and dodge their skills. This is how to looks:enter image description here

On the right side we have the player, in the middle the bullet ( that is handled with an array ) and on the left side the enemies ( an array ). Both enemies and the bullets have their own object. This is the code to spawn the enemies and the bullets:

For bullets

function shoot() {
    x = p.x + 6.5;
    y = p.y + 12.5;
    bullets.push(new Bullet(x, y));
}

for enemies:

function spawnEnemies() {
    let x = 650;
    let y = 30;

    for (let i = 0; i < 14; i++) {
        enemies.push(new Enemy(x, y));
        y += 40
    }
}

What I am trying to do, is to detect the collision when the bullet reaches the targets. This is how I tried it:

// check hit
for (let i = 0; i < bullets.length; i++){
    for (let j = 0; j < enemies.length; j++){
        let d = dist(bullets[i].x, bullets[i].y, enemies[j].x, enemies[j].y)
        if (d < 1){
            console.log('hit');
        }
    }
}

The check hit code is inside of p5's draw function, therefore it is executed continuously. Can anyone help me out?

Thank you in advance!

Upvotes: 1

Views: 1358

Answers (1)

Nenad Vracar
Nenad Vracar

Reputation: 122037

You could check for collision inside draw loop. With circles is simple you can just check if distance is less then sum of two elements radiuses DEMO

dist < circleOne.radius + circleTwo.radius

But since you have squares then its little more difficult because size != diagonal so the code could look something like this. DEMO

if (Math.abs(this.position.x - player.position.x) < this.size/2 + player.size/2 && Math.abs(this.position.y - player.position.y) < this.size/2 + player.size/2) collision = true; 

Also here I used p5.Vector for position but you don't have to, just use dist instead of p5.Vector.dist

const targets = [];
let player = null;
let canvas = null;

function setup() {
  canvas = createCanvas(400, 400);
  player = new Player(0, 0, 30, 'green');

  for (var i = 0; i < 10; i++) {
    const w = random(width);
    const h = random(height);
    const size = random(5, 40);
    targets.push(new Target(w, h, size, 'blue'));
  }

  canvas.mouseMoved(function() {
    player.position.x = mouseX;
    player.position.y = mouseY;
  })
}

function draw() {
  background(220);
  player.show()
  targets.forEach(target => {
    target.show();
    target.hit(player)
  })
}

class Element {
  constructor(x, y, size, color) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.color = color;
    this.position = new p5.Vector(this.x, this.y);
  }

  show() {
    fill(this.color);
    rectMode(CENTER)
    rect(this.position.x, this.position.y, this.size, this.size)
  }
}

class Player extends Element {}
class Target extends Element {
  hit(player) {
    let collision = false;

    if (Math.abs(this.position.x - player.position.x) < this.size / 2 + player.size / 2 && Math.abs(this.position.y - player.position.y) < this.size / 2 + player.size / 2) collision = true;
    else collision = false;
    if (collision) this.color = 'red';
    else this.color = 'blue';
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.js"></script>

To detect collision between two arrays of elements you could use nested for loop because you need to check if any element from first array collide with any element from second array.

const targets = [];
const bullets = [];
let canvas = null;

function setup() {
  canvas = createCanvas(400, 400);

  for (var i = 0; i < 10; i++) {
    const w = random(width);
    const h = random(height);
    const size = random(5, 50);
    targets.push(new Target(w, h, size, 'blue'));
  }

  for (var j = 0; j < 30; j++) {
    const w = random(width);
    const h = random(height);
    const size = random(5, 20);
    bullets.push(new Bullet(w, h, size, 'green'));
  }
}

function draw() {
  background(220);
  bullets.forEach(bullet => {
    bullet.show();
    bullet.move();
  });

  for (var i = 0; i < targets.length; i++) {
    for (var j = 0; j < bullets.length; j++) {
      const hit = targets[i].hit(bullets[j]);
      if (hit) {
        targets[i].color = 'red';
        break;
      } else targets[i].color = 'blue'
    }
  }

  targets.forEach(target => target.show());
}

class Element {
  constructor(x, y, size, color) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.color = color;
    this.position = new p5.Vector(this.x, this.y);
  }

  show() {
    const c = color(this.color);
    c.setAlpha(150);
    fill(c);
    rectMode(CENTER)
    rect(this.position.x, this.position.y, this.size, this.size)
  }
}

class Bullet extends Element {
  move() {
    this.position.add(p5.Vector.random2D())
  }
}
class Target extends Element {
  hit(player) {
    if (Math.abs(this.position.x - player.position.x) < this.size / 2 + player.size / 2 && Math.abs(this.position.y - player.position.y) < this.size / 2 + player.size / 2) return true;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.js"></script>

Upvotes: 1

Related Questions