试图发射子弹并检测矩形以进行碰撞

时间:2014-04-10 06:08:16

标签: java

我创造了一个射出子弹(矩形)的椭圆形,如果它碰到红色矩形,碰撞就会发现子弹击中了矩形。然而,当我运行程序时,碰撞已经完成,我甚至没有按空格键进行拍摄。我想要发生的是,当我射击并且子弹击中矩形时,那就是当它发现碰撞时。我试图分析它并做一些事情,但我无法得到它。这是我的源代码:

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class JavaGame2 extends JPanel implements KeyListener,Runnable{

//variables
JFrame frame;
int x, y, xDir, yDir,bx,by;
Rectangle bullet;
boolean readyTofire, shot = false;


//constructor for game
public JavaGame2(){

    frame = new JFrame("Java Game");
    int x=150;
    int y=150;


}



//drawings
public void paintComponent(Graphics g){

    super.paintComponent(g);
    this.setBackground(Color.WHITE);
    Rectangle rec = new Rectangle(50, 20, 50, 50);
    g.setColor(Color.BLUE);
    g.fillOval(x, y, 55, 55);
    g.fillRect(x+23, y-15, 10, 20);
    g.setColor(Color.RED);
    g.fillRect(rec.x, rec.y, rec.width, rec.height);
    bullet = new Rectangle(bx, by, 5, 3);


    if(shot){
        g.setColor(Color.BLACK);
        g.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
    }

    if(bullet.intersects(rec));
        g.drawString("collision!", 50, 20);

    repaint();

}

public void setxDir(int xdir){
    xDir = xdir;
}
public void setyDir(int ydir){
    yDir = ydir;
}



//key event listener keypressed

public void keyPressed(KeyEvent e) {
    int code = e.getKeyCode();
    if(code == KeyEvent.VK_UP){
        setyDir(-1);
     }
     if(code == KeyEvent.VK_DOWN){
        setyDir(+1);
     }
     if(code == KeyEvent.VK_LEFT){
        setxDir(-1);
     }
     if(code == KeyEvent.VK_RIGHT){
        setxDir(+1);

     }
     if(code == KeyEvent.VK_SPACE){
        if(bullet == null ){

            readyTofire = true;
            if(readyTofire){
                bx = x+26;
                by = y-15;
                bullet = new Rectangle(bx, by, 5, 3);
                shot = true;


            }

        }
     }
}

//key event listener for key released
public void keyReleased(KeyEvent e) {
    int code = e.getKeyCode();
    if(code == KeyEvent.VK_UP){
        setyDir(0);
     }
     if(code == KeyEvent.VK_DOWN){
        setyDir(0);
     }
     if(code == KeyEvent.VK_LEFT){
        setxDir(0);
     }
     if(code == KeyEvent.VK_RIGHT){
        setxDir(0);

     }
     if(code == KeyEvent.VK_SPACE){
         readyTofire = false;
         if(bullet.y <= -5){
             bullet = new Rectangle(0, 0, 0, 0);
             shot = false;
             readyTofire = true;

         }
     }
}

public void keyTyped(KeyEvent e) {

}

//shot of bullet
public void shoot(){

    if(shot){
        bullet.y--;
    }

}

//movement of the oval
public void move(){
    x += xDir;
    y += yDir;
    if(x <= 0){
        x = 0;
    }
    else if(x >= 500){
        x = 500;
    }
    else if(y <= 0){
        y = 0;
    }
    else if(y >= 500){
        y = 500;
    }

}

//thread
public void run() {

    try{
        while(true){
            shoot();
            move();



            Thread.sleep(5);
        }

    }
    catch(Exception e){
        System.out.println("error!");
    }
}




}

1 个答案:

答案 0 :(得分:2)

花点时间看看你的碰撞检测声明......

if (bullet.intersects(rec));
    g.drawString("collision!", 50, 20);

问题是,您已使用if

结束了;声明
if (bullet.intersects(rec));
                           ^---

这意味着该语句被有效忽略,它将与......相同。

if (bullet.intersects(rec)) {
}
g.drawString("collision!", 50, 20);

首先会提醒您注意这个问题

相反,请尝试使用

if (bullet.intersects(rec)) {
    g.drawString("collision!", 50, 20);
}

现在,请勿使用任何repaint方法调用repaint或任何可能调用setBackground的方法(如paint)。这将设置一个重复绘制事件的循环,最终消耗你的CPU。

我认为你真的不需要200fps而且大约40的Thread.sleep会给你25fps,并且通常会超出你的目的。

您还应该考虑使用key bindings,这样您就可以解决与KeyListener相关的焦点问题。

我还鼓励您探索Swing Timer的使用,这将减少模型和视图之间未同步更新的可能性,这可能导致随机且难以解决的问题或其他问题。 ..

拍摄问题

存在许多逻辑问题和错误使用变量......

首先......

  • 删除bxby,您不需要它们。你实际上并不需要xy,但随着我们的到来,这可能会更加明显......
  • 请勿在{{1​​}}中创建bullet,这会造成一些混淆......
  • 您可能不需要对paintComponent进行keyReleased检查,但如果您这样做,则应将VK_SPACE设为shot,将false设为bullet } ...
  • 在检查null是否readyToFire之前将true设置为true但是,当您在VK_SPACE中检测到keyPressed时检查bullet是否为null,如果不是,则bullet已经存在,不知道这是否是一个问题,但是如果您要使用{ {1}},您可以同时触发多个子弹......任何方式,创建新的List并分配给Rectangle


bullet
  • if (code == KeyEvent.VK_SPACE) { readyTofire = true; if (readyTofire) { int bx = x + 26; int by = y - 15; bullet = new Rectangle(bx, by, 5, 3); shot = true; } } 方法中,忘记进行边界检查......


shoot
  • 最后,把它全部涂抹......在这里你应该利用2D Graphics API


public void shoot() {

    if (shot) {
        bullet.y--;
        // Have we past the edge of the screen
        if (bullet.y < 0) {
            shot = false;
            bullet = null;
        }
    }

}

如果我错过了什么,这就是我测试的代码......

public void paintComponent(Graphics g) {

    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g.create();
    Rectangle rec = new Rectangle(50, 20, 50, 50);
    g.setColor(Color.BLUE);
    g.fillOval(x, y, 55, 55);
    g.fillRect(x + 23, y - 15, 10, 20);
    g.setColor(Color.RED);
    g.fillRect(rec.x, rec.y, rec.width, rec.height);

    if (shot && bullet != null) {
        g2d.setColor(Color.BLACK);
        g2d.fill(bullet);

        if (bullet.intersects(rec)) {
            g2d.drawString("collision!", 50, 20);
        }
    }
    g2d.dispose();

}

没有冒犯,但你的方法有点原始。您不应该将整个游戏模型包含在尝试显示它的同一个类中,而应该将游戏“逻辑”分离为模型并更新模型状态,然后让您的视图绘制模型...恕我直言