Отталкивайте пузыри друг от друга (Обработка)

Я работаю над проектом обработки для школы. Идея состоит в том, чтобы иметь переменное количество пузырьков, которые отскакивают друг от друга и меняют свой цвет (значение) при каждом щелчке. Это основа многопользовательской игры с одним устройством.

Так что у меня есть это

//ArrayList<Bubble> bubbles;
int firstBubbles = 80;
ArrayList<Bubble> bubbles = new ArrayList<Bubble>(10);

void setup() {
  size(1200,800);
  for (int i = 0; i < firstBubbles; ++i) {
    bubbles.add(new Bubble(int(random(0,width-100)),int(random(0,height-100)),true));
    //bubbles.get(i).addfirstbubbles();
    //println("Value: " + bubble.get(i).value);
    bubbles.get(i).addfirstbubbles();
  }
}

void draw() {
  background(200,200,200);
  for (int i = 0; i < bubbles.size(); i++) {

    Bubble bubble = bubbles.get(i); //get reference bubble

    bubble.move();
    bubble.display();
    bubble.bounceWalls();

    for (int j = 0; j < bubbles.size(); j++) {

      Bubble compare = bubbles.get(j); //compare bubble

      PVector vect = PVector.sub(compare.position, bubble.position);
      float magnitude = vect.mag();
      if(magnitude < bubble.size/2 + compare.size/2) {
        bubble.collide(compare); 
      }
    }


  }
}

void mouseReleased() {
  println("Released");
  for (Bubble b : bubbles) {
    if(mouseX > b.position.x - (b.size/2) && mouseX < b.position.x + (b.size/2) && mouseY > b.position.y - (b.size/2) && mouseY < b.position.y + (b.size/2)) {
      b.click();
    }    
  }
}

class Bubble {
  int value, size, xpos, ypos;
  PVector position, speed;
  Boolean comein;

  Bubble(int pos1, int pos2, Boolean ci) {
    xpos = pos1;
    ypos = pos2;
    comein = ci;
  }

  void addfirstbubbles() {
      size = 50;
      value = int(random(2));
      speed = new PVector(random(0.1, 2), (random(0.1, 2)));
      position = new PVector(xpos, ypos);
  }

  void bounceWalls() {
    if (position.x > width-size/2) {
      position.x = width-size/2;
      speed.x *= -1;
    } 
    else if (position.x < size/2) {
      position.x = size/2;
      speed.x *= -1;
    } 
    else if (position.y > height-size/2) {
      position.y = height-size/2;
      speed.y *= -1;
    } 
    else if (position.y < size/2) {
      position.y = size/2;
      speed.y *= -1;
    } 
  }

  //----- Update position -----
  void move() {
    position.add(speed);
  }

  //----- Draw on screen -----
  void display() {
    if (value == 1) {
      fill(255, 50, 100);
    } else {
      fill(100, 50, 255);
    }
    noStroke();
    ellipse(position.x, position.y, size, size);
  }

  //----- Collision -----
  void collide(Bubble other) {
    PVector bVect = PVector.sub(other.position, position);

    float bVectMag = bVect.mag();

    if (bVectMag < size/2 + other.size/2) {
      float theta  = bVect.heading();
      float sine = sin(theta);
      float cosine = cos(theta);

      PVector[] bTemp = {
        new PVector(), new PVector()
        };

        bTemp[1].x  = cosine * bVect.x + sine * bVect.y;
        bTemp[1].y  = cosine * bVect.y - sine * bVect.x;

      PVector[] vTemp = {
        new PVector(), new PVector()
        };

      vTemp[0].x  = cosine * speed.x + sine * speed.y;
      vTemp[0].y  = cosine * speed.y - sine * speed.x;
      vTemp[1].x  = cosine * other.speed.x + sine * other.speed.y;
      vTemp[1].y  = cosine * other.speed.y - sine * other.speed.x;

      PVector[] vFinal = {  
        new PVector(), new PVector()
        };

      vFinal[0].x = ((size - other.size) * vTemp[0].x + 2 * other.size * vTemp[1].x) / (size + other.size);
      vFinal[0].y = vTemp[0].y;

      vFinal[1].x = ((other.size - size) * vTemp[1].x + 2 * size * vTemp[0].x) / (size + other.size);
      vFinal[1].y = vTemp[1].y;

      bTemp[0].x += vFinal[0].x;
      bTemp[1].x += vFinal[1].x;

      PVector[] bFinal = { 
        new PVector(), new PVector()
        };

      bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
      bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
      bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
      bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;

      other.position.x = position.x + bFinal[1].x;
      other.position.y = position.y + bFinal[1].y;

      position.add(bFinal[0]);

      speed.x = cosine * vFinal[0].x - sine * vFinal[0].y;
      speed.y = cosine * vFinal[0].y + sine * vFinal[0].x;
      other.speed.x = cosine * vFinal[1].x - sine * vFinal[1].y;
      other.speed.y = cosine * vFinal[1].y + sine * vFinal[1].x;
    }
  }

  void click() {
    value*=-1;
    //println("Value changed to" + value);
  }
}

Пока что пузырьки более или менее отскакивают друг от друга, но иногда они ведут себя странно и кружатся вокруг друг друга или просто держатся вместе какое-то время. Коллизия в основном основана на http://processing.org/examples/circlecollision.html. изменил его, чтобы он соответствовал массиву.

Кто-нибудь знает, почему они ведут себя так странно, хотя приведенный выше пример работает отлично?


person tafelrunde    schedule 11.12.2014    source источник


Ответы (1)


TLDR вашего кода, но распространенной ошибкой при реализации обнаружения столкновений является обнаружение столкновения, принятие мер для отскока сталкивающихся объектов... но затем не обеспечение того, чтобы объекты находились в таком состоянии, что они не столкнутся снова на следующей итерации и снова отскакивать, возможно, назад друг к другу (что могло бы объяснить ваше «прилипающее» поведение; ваши объекты, вероятно, на самом деле колеблются отскоками на каждой итерации; немного регистрации в коде должно подтвердить).

person timday    schedule 11.12.2014
comment
Что ж, именно этим я и занимался последние пару дней, но до сих пор не имею ни малейшего представления, почему... - person tafelrunde; 12.12.2014