【问题标题】:How to remove an item from an arrayList upon collision?碰撞时如何从arrayList中删除一个项目?
【发布时间】:2019-10-25 11:16:55
【问题描述】:

尝试制作游戏 Tank Trouble 的副本,但我不知道如何对子弹和墙壁/玩家进行碰撞检测。按下鼠标时会生成子弹,但我不知道如何让它们在击中物体后消失。

试图让它们在接触时融入背景,但游戏开始严重滞后。还尝试了人们用来从 arrayLists 中删除项目的向后循环,但无济于事。

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 次。如果它在任何时候接触到玩家,他们都应该消失。

【问题讨论】:

标签: java arraylist processing collision-detection bullet


【解决方案1】:

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 ) 

VD 的点积等于线(OD)与向量V = P - O 夹角的余弦乘以@987654340 的数量(长度) @,因为Dunit vectorD的长度是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);
    }
}

【讨论】:

  • 非常感谢!这并不能完全回答我关于弹跳东西的第二个问题,但它是一个很好的起点。你的图表对理解有很大帮助。我将对此进行调整并将其实现到我的代码中。但是,你能解释一下这条线是什么意思吗?我不想只是盲目地复制粘贴它而不了解它的作用? if (distX > this.vel.mag())
  • @J.Doe distX 是从子弹到线的最短距离。 this.vel.mag() 是速度向量的长度,它是子弹每帧前进的距离。 “这并不能完全回答我的第二个问题” - 这个问题非常广泛,可能非常广泛。如果我在日记中找到一些时间,也许我会回答它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-31
  • 1970-01-01
相关资源
最近更新 更多