Как удалить элемент из arrayList при столкновении? - PullRequest
2 голосов
/ 11 июня 2019

Попытка сделать копию игры Tank Trouble, и я понятия не имею, как сделать обнаружение столкновений с пулями и стенами / игроками.Пули генерируются при нажатии мыши, но я не знаю, как заставить их исчезнуть после удара по объекту.

Пытался заставить их смешаться с фоном при контакте, но игра начала сильно отставать.Также пытались использовать обратную петлю, которую люди используют для удаления элементов из списков массива, но безрезультатно.

PVector player = new PVector (300, 400);
ArrayList <Bullet> bullets = new ArrayList <Bullet> ();
float maxSpeed = 3; //speed of bullets

void setup() {
   size(800, 600);
   fill(0);
}

void draw() {
  background(255);
  line(20, 200, 400, 200);
  rect(300, 400, 50, 50);

  //creates an aiming tool for the players
  PVector mouse = new PVector(mouseX, mouseY);
  fill(255);
  ellipse(mouse.x, mouse.y, 8, 8);

  if (frameCount%5==0 && mousePressed) {
     PVector dir = PVector.sub(mouse, player);
     dir.normalize();
     dir.mult(maxSpeed*3);
     Bullet b = new Bullet(player, dir);
     bullets.add(b);
  }

  for (Bullet b : bullets) {
     b.update();
     b.display();
  }
}

class Bullet extends PVector {
  PVector vel;

  Bullet(PVector loc, PVector vel) {
    super(loc.x, loc.y);
    this.vel = vel.get();
  }

  void update() {
    add(vel);
  }

  void display() {
    fill(0);
    ellipse(x, y, 5, 5);
  }

  float bulletX() {
    return x;
  }
}

В основном хочется, чтобы пули отскакивали 3-4 раза, прежде чем исчезнуть при последнем касании.Если это касается игрока в любой момент, они оба должны исчезнуть.

1 Ответ

1 голос
/ 11 июня 2019

Добавить метод к классу Bullet, который проверяет, находится ли пуля вне окна:

class Bullet extends PVector {

    // [...]

    boolean outOfBounds() {
        return this.x<0 || this.x>width || this.y<0 || this.y>height;
    }
}

Добавить проверку столкновения со строкой в ​​класс Bullet.Чтобы проверить, попадает ли пуля в селезенку, необходимо рассчитать ближайшую точку на линии и проверить, меньше ли расстояние до линии, чем скорость пули, и не попадает ли пуля в линию по бокам..

Если у вас есть линия, заданная точкой (O) и направлением (D), то ближайшая точка на линии к точке p может быть рассчитана следующим образом

X = O + D * dot(P-O, D);

Точечное произведение двух векторов равно косинусу угла между двумя векторами, умноженному на величину (длину) обоих векторов.

dot( A, B ) == | A | * | B | * cos( alpha ) 

Точечное произведение V и D равно косинусу угла между линией (O,D) и вектор V = P - O, умноженный на сумму (длину) V, поскольку D представляет собой единичный вектор (длина D равна 1,0),

Применение этого к вашему коду приводит к следующему методу:

class Bullet extends PVector {

    // [...]

    boolean collideline(float x1, float y1, float x2, float y2) {
        PVector O = new PVector(x1, y1);
        PVector L2 = new PVector(x2, y2);
        float len = O.dist(L2);
        PVector D = L2.sub(O).normalize();
        PVector P = this;
        PVector X = add(O, mult(D, sub(P, O).dot(D)));

        // distance to the line has to be less than velocity
        float distX = X.dist(P);
        if (distX > this.vel.mag())
            return false;

        // very if bullet doesn't "miss" the line
        PVector VX = X.sub(O); 
        float distO = VX.dot(D);
        return distO > -5 && distO < len+5;   
    }
}

Удалить маркер из списка по егоиндекс (в обратном порядке), если они выходят за границы или сталкиваются с линией:

void draw() {

    // [...]

        for (int j = bullets.size()-1; j >= 0; j--) {
            if (bullets.get(j).outOfBounds() || bullets.get(j).collideline(20, 200, 400, 200))
                bullets.remove(j);
    }
}

...