需要协助处理3中的敌人交互的子弹

时间:2015-11-14 02:13:21

标签: processing collision-detection collision detection

我正在为我的编程课写一个游戏。这是一个飞机射击游戏,其他飞机作为“敌人”进入。射击的飞机射出小椭圆。我无法弄清楚如何让被击中的敌人从游戏中移除。我知道如何消除“敌人”,但不知道如何在碰撞时发生这种情况。这是我目前的代码。

    ArrayList <Bullet> bullets = new ArrayList <Bullet> ();
    ArrayList enemies;
    PVector player, playerSpeed;
    float maxSpeed = 3;
    PImage jet;
    PImage enemy;
    PImage laser;
    void setup() {
      size(600, 600);
      player = new PVector(300, 550);
      playerSpeed = new PVector();
      noCursor();
      noStroke();
      smooth();
      String jeturl = "http://s1.postimg.org/dhe38w1rv/fighter_jet_md_20.png";
      String enemyurl =                "http://s29.postimg.org/cdaj0d7z7/fighter_jet_md_20.png";
      String laserurl = "http://s13.postimg.org/fq00vsl37/red_Laser_Ray.png";
      // Load image from a web server
      jet = loadImage(jeturl, "png");
      enemy = loadImage(enemyurl, "png");
      laser = loadImage(laserurl, "png");
      enemies = new ArrayList();
    }

    void draw() {
      background(255);

      player.add(playerSpeed);
      //fill(255, 0, 0);
      image(jet, player.x, player.y);

      PVector mouse = new PVector(mouseX, mouseY);
              fill(10);
      ellipse(mouse.x, mouse.y, 5, 5);

      if (frameCount%7==0 && mousePressed) {
        PVector dir = PVector.sub(mouse, player);
        dir.normalize();
        dir.mult(maxSpeed*3);
        Bullet b = new Bullet(player, dir);
        bullets.add(b);
      }
     for(int i = enemies.size()-1; i>=0; i--) {
        Enemy b = (Enemy) enemies.get(i);
        b.move();
        b.draw();



      }

      if (frameCount%50==0) {
        enemies.add(new Enemy());


      }

      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, 0, 255);
        ellipse(x, y, 3, 3);
      }
    }

    class Enemy {
      float x, y;
      Enemy() {
            x = random(20, 580);
            y = random(-20, -580);

      }

      void move() {
        y = y + random(1,3);

      }

      void draw() {
        image(enemy, x, y);

      }
    }

    void keyPressed() {

      if (keyCode == LEFT)  { 

      playerSpeed.x = -maxSpeed; 

       }
      if (keyCode == RIGHT) { 

      playerSpeed.x = maxSpeed;

       }
    }

    void keyReleased() {

      if (keyCode == LEFT || keyCode == RIGHT) { 
      playerSpeed.x = 0; 
    }
    }

2 个答案:

答案 0 :(得分:0)

你需要为你的敌人类添加一个监听器。它应该是子弹列表上的无限循环。当子弹坐标等于敌人坐标时,它应具有执行on_delete回调的逻辑。我不是Java开发人员,但我会给你写一些伪代码,它们应该指向正确的方向。需要进行一个小的改动,Enemy类需要使用enemies数组上元素的索引进行初始化,以便可以使用回调来正确销毁它。

Class Enemy (int idx){
    void on_delete(){
         enemies = ArrayUtils.removeElement(idx)};
    void listen(){
    cycle{ 
           for(i=0; bullets.count()-1;i++){
           bullet_x = bullets(i).getX
           bullet_y = bullets(i).getY
           if (bullet_x==x) && (bullet_y==y)
           on_delete();
           }
       } 
}

答案 1 :(得分:0)

你知道子弹和敌人的坐标,因此你可以检查碰撞。内置dist()函数可计算两点之间的欧几里德距离。

虽然不是非常有效,也不准确,但您可以这样做:

ArrayList <Bullet> bullets = new ArrayList <Bullet> ();
ArrayList enemies;
PVector player, playerSpeed;
float maxSpeed = 3;

PImage jet;
PImage enemy;
PImage laser;

int lives = 3;
int score = 0;

void setup() {
  size(600, 600);
  player = new PVector(300, 550);
  playerSpeed = new PVector();
  noCursor();
  noStroke();
  smooth();
  String jeturl = "http://s1.postimg.org/dhe38w1rv/fighter_jet_md_20.png";
  String enemyurl = "http://s29.postimg.org/cdaj0d7z7/fighter_jet_md_20.png";
  String laserurl = "http://s13.postimg.org/fq00vsl37/red_Laser_Ray.png";
  // Load image from a web server
  jet = loadImage(jeturl, "png");
  enemy = loadImage(enemyurl, "png");
  laser = loadImage(laserurl, "png");
  enemies = new ArrayList();


}

void draw() {
  background(255);

  player.add(playerSpeed);
  //fill(255, 0, 0);
  image(jet, player.x, player.y);

  PVector mouse = new PVector(mouseX, mouseY);
  fill(10);
  ellipse(mouse.x, mouse.y, 5, 5);

  if (frameCount%7==0 && mousePressed) {
    PVector dir = PVector.sub(mouse, player);
    dir.normalize();
    dir.mult(maxSpeed*3);
    Bullet b = new Bullet(player, dir);
    bullets.add(b);
  }
  for (int i = enemies.size ()-1; i>=0; i--) {
    Enemy b = (Enemy) enemies.get(i);
    b.move();
    b.draw();
    //check enemy to bullet collisions
    //for each bullet
    for(Bullet blt : bullets) {
      //if the distance between the bullet and enemy is less than the enemy's width
      if(dist(blt.x,blt.y,b.x,b.y) < enemy.width){
        //remove the enemy
        enemies.remove(b);
        //optional, add score
        score += 10;
      }
    }
    //check enemy to player collision
    if(dist(player.x,player.y,b.x,b.y) < jet.width){
      enemies.remove(b);//remove current enely

      //optional, update lives, reset score/game if needed
      lives--;
      println("player hit: " + lives + " lives left");

      if(lives < 1){
        println("Game Over!\nscore:" + score);
        lives = 3;
        score = 0;
      }

    }
  }

  if (frameCount%50==0) {
    enemies.add(new Enemy());
  }

  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, 0, 255);
    ellipse(x, y, 3, 3);
  }
}

class Enemy {
  float x,y;

  Enemy() {
    x = random(20, 580);
    y = random(-20, -580);
  }

  void move() {
    y = y + random(1, 3);
  }

  void draw() {
    image(enemy, x, y);
  }
}

void keyPressed() {

  if (keyCode == LEFT) { 

    playerSpeed.x = -maxSpeed;
  }
  if (keyCode == RIGHT) { 

    playerSpeed.x = maxSpeed;
  }
}

void keyReleased() {

  if (keyCode == LEFT || keyCode == RIGHT) { 
    playerSpeed.x = 0;
  }
}

上述代码不准确的原因是因为它根据距离检查碰撞。想象一下检查对象周围的圆圈。 如果你的对象是圆圈,这将是完美的,但你大多是矩形(PImages)。

上面的代码很慢的原因与dist()函数的工作方式有点关系。想象一下屏幕上两个对象之间的一条线。从一个对象到另一个对象绘制两条直线仅限于水平和垂直,将为您提供直角三角形的两边,连接对象的原始线是连字符。为了找到距离,你可以求解hypothenuse,它是两边相加的平方根。你不必太担心这个,因为dist()会为你做这个数学计算,但请记住它使用的是平方根,这在CPU上可能很昂贵。 解决这个问题的一种方法是使用平方距离(并检查半径的平方),但这不会太准确。

另一种选择是进行简单的矩形边界检查。 你知道每个盒子(PImage)在屏幕上的位置以及每个子弹的绘制位置,因此如果每个子弹都在敌人中,你就可以锻炼。 同样,您可以检查两个矩形是否相交(玩家PImage和敌人PImage与更新的坐标)。

这是矩形交叉的最小示例,利用java.awt.Rectangle类(已经提供交叉检查):

import java.awt.Rectangle;

//based on jet image from previous code
int jetWidth = 20;
int jetHeight = 28;

Rectangle playerBox,enemyBox;

void setup(){
  size(600, 600);
  noFill();strokeWeight(3);
  //bounding boxes
  playerBox = new Rectangle(width / 2, height-jetHeight*2,jetWidth,jetHeight);
  enemyBox = new Rectangle((int)random(width),-jetHeight,jetWidth,jetHeight);
}

void draw(){
  //update enemy
  enemyBox.y += 3;
  //reset enemy position if out of screen
  if(enemyBox.y > height) {
    enemyBox.y = -jetHeight;
  }
  playerBox.x = (int)(mouseX - jetWidth * .5);

  //check collision
  if(playerBox.intersects(enemyBox)){
    strokeWeight(10);
  }else{
    strokeWeight(3);
  }

  background(255);
  stroke(192,0,0);
  rect(enemyBox.x,enemyBox.y,enemyBox.width,enemyBox.height);
  stroke(0,192,0);
  rect(playerBox.x,playerBox.y,playerBox.width,playerBox.height);
}

如果您想要像素精确度,您可以利用所加载图像的Alpha通道,并且:

  1. 最初进行边界框测试
  2. 如果(并且仅当)绑定框相交,则循环通过一个图像的非透明像素以检查另一个图像的非透明像素)。 (如果您知道对象的方向,则可以使用它来开始计算更接近可能的碰撞的像素)
  3. 接下来的步骤,我建议基于边界框实现碰撞检测。稍后您可能需要查看基本state machines以跟踪游戏的状态(例如,介绍屏幕,级别1,级别2,...,屏幕上的游戏,高分屏幕等)。

    玩得开心! :)