skip to Main Content

I’m working on a project for school which is based on the idea of one ball starting movement and bumping into a ball, starting that ball moving, and then going and bumping another, until eventually the entire grid is moving and changing colours.

The issues I am currently having are as follows.

First, the balls will occasionally just keep colliding and bouncing off of one another and basically cause people a seizure from them flashing all different colours.

Second, the balls will bounce off of the screen, where I’d like the edge of the screen to be like a bumper or collision object so that things can’t bounce to outside of the screen.

Here is my code

function setup() {
  createCanvas(750, 750);
 
  noStroke();
  balls = [];
  for (x=0;x<25;x++){
    for (y=0;y<25;y++){
      b = new Ball(10+ x*30, 10+ y*30);
      balls.push(b);
    }
  }
  balls[210].vel = p5.Vector.random2D().mult(0.3);
}

function draw(){
  background(220);
  for (b of balls){
    b.update();
    b.checkCollision(balls);
  }
  for (b of balls){
    b.draw();
  }
}

class Ball{
  constructor(x,y){
    this.pos = createVector(x,y);
    this.vel = createVector(0,0);
    this.color = 'white';
  }
  update(){
    this.pos.add(this.vel);
  }
  draw(){
    fill(this.color);
    circle(this.pos.x, this.pos.y, 20);
  }
  checkCollision(others){
    for (const other of others){
      if (other != this){
        const d = this.pos.dist(other.pos);
        if (d < 20){
          this.vel.mult(-0.3);
          this.pos = this.pos.sub(1,1);
          other.pos = other.pos;
          other.vel = p5.Vector.random2D().mult(0.3);
          this.color = random(['red','pink','purple','blue','green','orange','yellow','olive','maroon','magenta','indigo','teal','violet','crimson','gold','azure','coral','cyan','emerald']);
          other.color = random(['red','pink','purple','blue','green','orange','yellow','olive','maroon','magenta','indigo','teal','violet','crimson','gold','azure','coral','cyan','emerald']);
        }
      }
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

Any help is appreciated!

I have tried adding in a position modifier to deal with two circles continually colliding non-stop, but that just seems to make it bounce out of the screen as a bigger issue. I haven’t been able to think of a solution to the issue of it going out of bounds, or to make it so the screen bounds act as a bumper.

2

Answers


  1. Chosen as BEST ANSWER

    Ultimately the problem was with the fact that the balls were moving in random directions with no stipulation as to what was and wasn’t a viable area to move to - I.e if collision occurred from a downward motion, don’t then move upwards, and conversely, if moving downwards and colliding with something, don’t continue moving downwards. To resolve, I stipulated directions based on hit conditions - enhancing the collision detection past simply detecting that a collision happened


  2. I added some things to your code and changed the colors to be set based on the current velocity, for a better interaction visualization for testing.

    const c_colors = ['red', 'pink', 'purple', 'blue', 'green', 'orange', 'yellow', 'olive', 'maroon', 'magenta', 'indigo', 'teal', 'violet', 'crimson', 'gold', 'azure', 'coral', 'cyan', 'emerald'];
    
    function setup() {
      createCanvas(750, 750);
    
      noStroke();
      balls = [];
      for (x = 0; x < 9; x++) {
        for (y = 0; y < 9; y++) {
          b = new Ball(35 + x * 80, 35 + y * 80);
          balls.push(b);
        }
      }
    
      balls[55].vel = p5.Vector.random2D().mult(5);
    }
    
    function draw() {
      background(220);
      for (b of balls) {
        //b.checkCollision(balls);
        b.update();
      }
    
      for (b of balls) {
        b.draw();
      }
    }
    
    class Ball {
      constructor(x, y) {
        this.pos = createVector(x, y);
        this.vel = createVector(0, 0);
        this.color = 'white';
        this.radius = 25;
      }
    
      update() {
        this.pos.add(this.vel);
        this.vel.mult(0.99);
    
        this.checkCollision(balls);
        let velMagNorm = p5.Vector.mag(this.vel);
        this.color = lerpColor(color(255), color(255, 0, 0), velMagNorm);
      }
    
      draw() {
        fill(this.color);
        circle(this.pos.x, this.pos.y, this.radius * 2);
      }
    
      checkCollision(others) {
        if (this.pos.x <= this.radius || this.pos.x >= width - this.radius)
          this.vel.x *= -1;
    
        if (this.pos.y <= this.radius || this.pos.y >= height - this.radius)
          this.vel.y *= -1;
    
        for (const other of others) {
          if (this == other)
            continue;
    
          const d = this.pos.dist(other.pos);
          const vec = p5.Vector.sub(this.pos, other.pos);
          const velMag = p5.Vector.mag(this.vel);
          const normVec = vec.normalize();
    
          if (d < this.radius * 2) {
            this.vel.add(p5.Vector.mult(normVec, velMag * 0.99));
    
            other.vel.add(p5.Vector.mult(normVec, -velMag * 0.99));
    
            //this.color = random(c_colors);
            //other.color = random(c_colors);
          }
        }
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search