2

Trying to make a copy of the game Tank Trouble and I have no idea how to do collision detection with the bullets and the walls/ players. The bullets are generated when the mouse is pressed but I don't know how to make them despawn once they hit an object.

Tried to make them blend into the background upon contact but game started lagging hard. Have also tried the backwards loop thing that people use to remove items from arrayLists to no avail.

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;
  }
}

Basically want the bullets to bounce 3-4 times before despawning on the last touch. If it touches the player at any point, they should both despawn.

J. Doe
  • 21
  • 1
  • Have a look at the below link---https://stackoverflow.com/questions/5737484/collision-detection-remove-object-from-arraylist?rq=1 –  Jun 11 '19 at 05:36
  • Also this https://stackoverflow.com/questions/30858004/removing-items-from-arraylist-upon-collision-java –  Jun 11 '19 at 05:37
  • Welcome to SO. Is your issue with collision detection or removing the items from the list? – sprinter Jun 11 '19 at 05:55

1 Answers1

0

Add method to the class Bullet, which verified if a bullet is out of the window:

class Bullet extends PVector {

    // [...]

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

Add a collision check with a line to the class Bullet. To check if the bullet hits the lien, you've to calculate the nearest point on the line and to verify if the distance to the line is less than the velocity of the bullet and if the bullet doesn't miss the line at its sides.

If you have a line, given by a point (O) and an direction (D), then the nearest point on the line, to a point p can be calculated as follows

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

The dot product of 2 vectors is equal the cosine of the angle between the 2 vectors multiplied by the magnitude (length) of both vectors.

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

The dot product of V and D is equal the cosine of the angle between the line (O, D) and the vector V = P - O, multiplied by the amount (length) of V, because D is a unit vector (the lenght of D is 1.0),

Applying this to your code, leads to the following method:

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;   
    }
}

Remove the bullet form the list by its index (in reverse order), if they are out of bounds or collide to the line:

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);
    }
}

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Thank you so much! This doesn't completely answer my secondary question about the bouncing stuff but its a great starting off point. Your diagrams helped a lot with the comprehension. I will adjust this and implement it into my code. However, could you explain what this line means? I don't want to just blindly copy-paste it without understanding what it does? if (distX > this.vel.mag()) – J. Doe Jun 11 '19 at 12:56
  • @J.Doe `distX` ist the shortest distance form the bullet to the line. `this.vel.mag()` is the length of the velocity vector, it is the distance the bullet steps forward per frame. *"This doesn't completely answer my secondary question"* - this question is very very broad, possibly far to broad. May be I'll answer it, if I find some time in my diary. – Rabbid76 Jun 11 '19 at 13:05