How To Set Up Array Class Collisions?

I'm attempting to give my array classes 'Opp' and 'Ally' the same behaviours as the playable 'Balls' So they must all collide with one another and to collide with the puck in order to manoeuvre it in the correct and appropriate direction. Any assistance would be more than greatly appreciated. Thank you! Miles. M

(Please forgive the poor structure of my code, if that can be improved also any advice would be very helpful)

>

boolean keyW = false;
boolean keyA = false;
boolean keyS = false;
boolean keyD = false;

boolean keyUp = false;
boolean keyLeft = false;
boolean keyDown = false;
boolean keyRight = false;


float gVelocity     = .2;
final float gVelocityFriction = .99;
final float gElasticity    = 1;

ArrayList<Opp> Opps;
ArrayList<Ally> Allys;

Ball player1;
Ball player2;
Ball puck;

int score1, score2;

PFont title;

int mode;
int stage;

void setup() {

  stage = 1;
  mode = 0;

  size(1280, 720);
  frameRate(60);

  Opps = new ArrayList<Opp>();
  for (int i = 0; i < 2; i++) {
    Opps.add(new Opp(random(640,1280),random(height)));
  }
    Allys = new ArrayList<Ally>();
  for (int i = 0; i < 2; i++) {
    Allys.add(new Ally(random(0,640),random(height)));
  }

  player1 = new Ball(new PVector(width*3/4, height/2), 
  new PVector(width*3/4, height/2), 
  64, 24);
  player2 = new Ball(new PVector(width/4, height/2), 
  new PVector(width/4, height/2), 
  192, 24);
  puck = new Ball(new PVector(width/2, height/2), 
  new PVector(width/2, height/2), 
  128, 16);                   

  score1 = 0;
  score2 = 0;
}

void draw() {

  background(205, 255, 255);

    if(stage==1){

      rectMode(CENTER);
      noStroke();
      fill(255, 55, 55, 185);
      rect(640, 170, 430, 160);
      fill(55, 255, 55, 185);
      rect(640, 350, 430, 160);
      fill(55, 55, 255, 185);
      rect(640, 530, 430, 160);

      textAlign(CENTER);
      textSize(32);
      fill(0);
      text("Demo", 640, 180);
      text("One Player Start", 640, 360);
      text("Two Player Start", 640, 540);

      if(mousePressed) {
        if (mouseX > 425 && mouseX < 855 && mouseY > 85 && mouseY < 255) {
        stage = 2; 
        mode = 1;
      }
    }
      if(mousePressed) {  
        if (mouseX > 425 && mouseX < 855 && mouseY > 265 && mouseY < 435) { 
        stage = 2;
        mode = 2;
      }
    }

      if(mousePressed) {
        if (mouseX > 425 && mouseX < 855 && mouseY > 445 && mouseY < 615) {
        stage = 2; 
        mode = 3;
      }
    }
  }

if(stage==2){

  rectMode(CORNER);
  background(205, 255, 255);

  noStroke();
  fill(255, 55, 55, 185);
  rect(0, 0, width/2, height);
  fill(55, 55, 255, 185);
  rect(width/2, 0, width, height);

  fill(205, 5, 5, 95);
  rect(0, 180, width/16, height/2);
  fill(5, 5, 205, 95);
  rect(width*15/16, 180, width, height/2);

  for (Opp o : Opps) {
    o.applyBehaviors(Opps);
    o.update();
    o.display();
  }

    for (Ally a : Allys) {
    a.applyBehaviors(Allys);
    a.update();
    a.display();
  }

  if (puck.position.x < width/16 && puck.position.y > 180 && puck.position.y < 540 ) {
    score2++;
    reset(-1);
  }
  if (puck.position.x > width*15/16 && puck.position.y > 180 && puck.position.y < 540 ) {
    score1++;
    reset(1);
  }

  // Ticks and renders test balls
  player1.tick();
  player2.tick();
  puck.tick();

  player1.render();
  player2.render();
  puck.render();

  if (mode==1) {
  hal(player1, puck, player2, 1);
  hal(player2, puck, player1, -1);
  }

  if (mode==2) {
  hal(player1, puck, player2, 1);
  //hal(player2, puck, player1, -1);
  }

  if (mode==3) {
  //hal(player1, puck, player2, 1);
  //hal(player2, puck, player1, -1);
  }

  arrowkeyS(player1);
  wasd(player2);

  Ball tempb1 = new Ball(new PVector(player1.position.x, player1.position.y), 
  new PVector(player1.last.x, player1.last.y), 
  0, player1.radius);
  Ball tempb2 = new Ball(new PVector(player2.position.x, player2.position.y), 
  new PVector(player2.last.x, player2.last.y), 
  0, player2.radius);
  Ball temppuck = new Ball(new PVector(puck.position.x, puck.position.y), 
  new PVector(puck.last.x, puck.last.y), 
  0, puck.radius);

  // Colliding balls 1 and 2
  player1.collide(tempb2);
  player2.collide(tempb1);
  player1.collide(temppuck);
  player2.collide(temppuck);
  puck.collide(tempb2);
  puck.collide(tempb1);

  fill(0);
  textSize(16);
  text("FPS:" + floor(frameRate), width-64, height-8);

  fill(0);
  textSize(32);
  text(score1, width/4, height/16);
  text(score2, width*3/4, height/16);

  if (score1==5){
    stage = 3;
  }

   if (score2==5){
    stage = 4;
  }

  }

  if (stage==3) {

    background(205, 255, 255);

    noStroke();
    fill(255, 55, 55, 185);
    rect(0, 0, 1280, 720);

    textAlign(CENTER);
    textSize(64);
    fill(0);
    text("Red Team Wins!", 640, 340);
    textSize(32);
    text("Press 'R' To Restart!", 640, 400);

    if (keyPressed) {
      if (key == 'r' || key == 'R') {

        stage = 1;
        score1 = 0;
        score2 = 0;

      }

    }

  }

  if (stage==4) {

    background(205, 255, 255);


    noStroke();
    fill(55, 55, 255, 185);
    rect(0, 0, 1280, 720);

    textAlign(CENTER);
    textSize(64);
    fill(0);
    text("Blue Team Wins!", 640, 340);
    textSize(32);
    text("Press 'R' To Restart!", 640, 400);

    if (keyPressed) {
      if (key == 'r' || key =='R') {

        stage = 1;
        score1 = 0;
        score2 = 0;

      }

    }

  }


}
// Input
void keyPressed() {
  gameKeyPressed();
}

void keyReleased() {
  gameKeyReleased();
}

void reset(int winner) {
  player1.reset(new PVector(width*3/4, height/2));
  player2.reset(new PVector(width/4, height/2));
  puck.reset(new PVector(width/2+winner*(width/8), random(height/4, height*3/4)));
}

void hal(Ball tb, Ball tp, Ball opp,int side){
  PVector ratio = new PVector(0, 0);
  if(tp.position.y != tb.position.y) ratio.y += getSign(tp.position.y-tb.position.y);
  if(tp.position.x != tb.position.x) ratio.x += getSign(side*12+tp.position.x-tb.position.x);

  if(tp.position.y != opp.position.y) ratio.y += .02*getSign(tp.position.y-opp.position.y);

  if(ratio.x != 0) tb.position.x += (gVelocity) * getSign(ratio.x) * sqrt(abs(ratio.x)) / (abs(ratio.x)+abs(ratio.y));
  if(ratio.y != 0) tb.position.y += (gVelocity) * getSign(ratio.y) * sqrt(abs(ratio.y)) / (abs(ratio.x)+abs(ratio.y));
}

float getSign(float num) {return num/abs(num);}

// Detects active keyS
void gameKeyPressed() {

  if (key == CODED) {
    if (keyCode == UP) {
      keyUp = true;    
      keyDown = false;
    }
    if (keyCode == LEFT) {
      keyLeft = true;  
      keyRight = false;
    }
    if (keyCode == RIGHT) {
      keyRight = true; 
      keyLeft = false;
    }
    if (keyCode == DOWN) {
      keyDown = true;  
      keyUp = false;
    }
  }

  if (key == 'w' || key == 'W') {
    keyW = true; 
    keyS = false;
  }
  if (key == 'a' || key == 'A') {
    keyA = true; 
    keyD = false;
  }
  if (key == 'd' || key == 'D') {
    keyD = true; 
    keyA = false;
  }
  if (key == 's' || key == 'S') {
    keyS = true; 
    keyW = false;
  }
  if (key == 'r' || key == 'R') reset(0);
}

// Detects when keyS go inactive
void gameKeyReleased() {
  if (key == CODED) {
    if (keyCode == UP) keyUp = false;
    if (keyCode == LEFT) keyLeft = false;
    if (keyCode == DOWN) keyDown = false;
    if (keyCode == RIGHT) keyRight = false;

  }

  if (key == 'w' || key == 'W') keyW = false;
  if (key == 'a' || key == 'A') keyA = false;
  if (key == 's' || key == 'S') keyS = false;
  if (key == 'd' || key == 'D') keyD = false;

}


void arrowkeyS(Ball tb) {

  if (keyDown == true) 
    // Limits positioneration when two directions are active
    if (keyLeft == true || keyRight == true) 
      tb.position.y += gVelocity/sqrt(2);
    else 
      tb.position.y += gVelocity;
  else if (keyUp == true) { 
    if (keyLeft == true || keyRight == true) 
      tb.position.y -= gVelocity/sqrt(2);
    else 
      tb.position.y -= gVelocity;
  }

  if (keyRight == true) 
    if (keyUp == true || keyDown == true) 
      tb.position.x += gVelocity/sqrt(2);
    else 
      tb.position.x += gVelocity;
  else if (keyLeft == true) {
    if (keyUp == true || keyDown == true) 
      tb.position.x -= gVelocity/sqrt(2);
    else 
      tb.position.x -= gVelocity;
  }
}

void wasd(Ball tb) {
  // Test ball 2
  if (keyS == true)
    if (keyA == true || keyD == true) 
      tb.position.y += gVelocity/sqrt(2);
    else  
      tb.position.y += gVelocity;
  else if (keyW == true) {  
    if (keyA == true || keyD == true) 
      tb.position.y -= gVelocity/sqrt(2);
    else 
      tb.position.y -= gVelocity;
  }

  if (keyD == true) 
    if (keyW == true || keyS == true) 
      tb.position.x += gVelocity/sqrt(2);
    else 
      tb.position.x += gVelocity;
  else if (keyA == true) {
    if (keyW == true || keyS == true) 
      tb.position.x -= gVelocity/sqrt(2);
    else 
      tb.position.x -= gVelocity;
  }
}

class Ally {

  // All the usual stuff
  PVector position;
  PVector velocity;
  PVector acceleration;
  float r;
  float maxforce;    // Maximum steering force
  float maxspeed;    // Maximum speed

  Ally(float x, float y) {
    position = new PVector(x, y);
    r = 12;
    maxspeed = 3;
    maxforce = 0.2;
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
  }

  void applyForce(PVector force) {
    acceleration.add(force);
  }

  void applyBehaviors(ArrayList<Ally> Allys) {
     PVector separateForce = separate(Allys);
     PVector seekForce = seek(new PVector(puck.position.x,puck.position.y));
     separateForce.mult(2);
     seekForce.mult(1);
     applyForce(separateForce);
     applyForce(seekForce); 
  }

  PVector seek(PVector target) {
    PVector desired = PVector.sub(target,position);  // A vector pointing from the position to the target

    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired,velocity);
    steer.limit(maxforce);  // Limit to maximum steering force

    return steer;
  }

  PVector separate (ArrayList<Ally> Allys) {
    float desiredseparation = r*2;
    PVector sum = new PVector();
    int count = 0;
    for (Ally other : Allys) {
      float d = PVector.dist(position, other.position);
      if ((d > 0) && (d < desiredseparation)) {
        PVector diff = PVector.sub(position, other.position);
        diff.normalize();
        diff.div(d);        // Weight by distance
        sum.add(diff);
        count++;            // Keep track of how many
      }
    }
    // Average -- divide by how many
    if (count > 0) {
      sum.div(count);
      sum.normalize();
      sum.mult(maxspeed);
      sum.sub(velocity);
      sum.limit(maxforce);
    }
    return sum;
  }


  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    position.add(velocity);
    acceleration.mult(0);
  }

  void display() {
    fill(182, 45, 182, 245);
    noStroke();
    pushMatrix();
    translate(position.x, position.y);
    ellipse(0, 0, 50, 50);
    popMatrix();
  }

}

class Opp {

  // All the usual stuff
  PVector position;
  PVector velocity;
  PVector acceleration;
  float r;
  float maxforce; 
  float maxspeed;  


  Opp(float x, float y) {
    position = new PVector(x, y);
    r = 12;
    maxspeed = 3;
    maxforce = 0.2;
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0); 
  }

  void applyForce(PVector force) {
    acceleration.add(force);
  }

  void applyBehaviors(ArrayList<Opp> Opps) {
     PVector separateForce = separate(Opps);
     PVector seekForce = seek(new PVector(puck.position.x,puck.position.y));
     separateForce.mult(2);
     seekForce.mult(1);
     applyForce(separateForce);
     applyForce(seekForce); 
  }


  PVector seek(PVector target) {
    PVector desired = PVector.sub(target,position);  

    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired,velocity);
    steer.limit(maxforce);  // Limit to maximum steering force

    return steer;
  }


  PVector separate (ArrayList<Opp> Opps) {
    float desiredseparation = r*2;
    PVector sum = new PVector();
    int count = 0;
    for (Opp other : Opps) {
      float d = PVector.dist(position, other.position);
      if ((d > 0) && (d < desiredseparation)) {
        PVector diff = PVector.sub(position, other.position);
        diff.normalize();
        diff.div(d);        
        sum.add(diff);
        count++;           
      }
    }
    if (count > 0) {
      sum.div(count);
      sum.normalize();
      sum.mult(maxspeed);
      sum.sub(velocity);
      sum.limit(maxforce);
    }
    return sum;
  }

  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    position.add(velocity);
    acceleration.mult(0);
  }

  void display() {
    fill(62, 43, 181, 245);
    noStroke();
    pushMatrix();
    translate(position.x, position.y);
    ellipse(0, 0, 50, 50);
    popMatrix();
  }

}

class Ball {

  PVector position, last;
  private int hue, radius;

  Ball(PVector t, PVector tl, int th,  int tr) {
    position   = t;
    last  = tl;
    hue = th;
    radius = tr;
  }

  void tick() {
    PVector tempp = new PVector();
    tempp.set(position.x, position.y);

    position.set(position.x + gVelocityFriction*((position.x - last.x)), 
            position.y + gVelocityFriction*(position.y - last.y));
    last.set(tempp.x, tempp.y);

    if (position.x < 0)      bounceX(0);
    if (position.x > width)  bounceX(width);
    if (position.y < 0)      bounceY(0);
    if (position.y > height) bounceY(height);
  }

    void render() {
    noStroke();
    fill(hue, 25, 185);
    ellipse(position.x, position.y, radius*2, radius*2);
  }

  void collide(Ball hit) {
    if (dist(hit.position.x, hit.position.y, position.x, position.y) < hit.radius+radius) {
      float phi = atan2(hit.position.y - position.y, hit.position.x - position.x);

      float v1 = dist(position.x, position.y, last.x, last.y);
      float ang1 = atan2(position.y - last.y, position.x - last.x);
      float v2 = dist(hit.position.x, hit.position.y, hit.last.x, hit.last.y);
      float ang2 = atan2(hit.position.y - hit.last.y, hit.position.x - hit.last.x);

      last.x = position.x-gElasticity*(v2*cos(ang2-phi)*cos(phi)+v1*sin(ang1-phi)*cos(phi+PI/2));
      last.y = position.y-gElasticity*(v2*cos(ang2-phi)*sin(phi)+v1*sin(ang1-phi)*sin(phi+PI/2));

      tick();
    }
  }

  void bounceY(float bound) {
    last.y = bound + gElasticity * (position.y - last.y);
    position.y  = bound;
  }

  void bounceX(float bound) {
    last.x = bound + gElasticity * (position.x - last.x);
    position.x  = bound;
  }

  void reset(PVector t) {
    position    = t;
    last.x = position.x;
    last.y = position.y;
  }
}

Answers

Sign In or Register to comment.