问题是:在坦克打出炮弹时候,当子弹所在的矩形和敌人坦克所在的矩形相交时,就抛出空指针异常,苦恼...

解决方案 »

  1.   

    连接被重定向到http://download.csdn.net/index.html,好象不能直接下载
      

  2.   

    lz都知道可能是哪里的问题了,用打印语句打印下吧,看看那个变量或者对象的值为null,之后被引用了
      

  3.   


    是不是说你相交矩形后得到了null,如果是这样的话,你再让子弹前进一端距离不就可以了啊,几个象素肉眼也看不出来。
      

  4.   

    import java.awt.Color;
    import java.awt.Frame;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.util.ArrayList;
    import java.util.List;
    public class TankWar extends Frame{    private Image image=null; 
        
        public static final int FRAME_WIDTH=800;
        public static final int FRAME_HEIGHT=600;
            
        Tank myTank=new Tank(40,40,true,this);
        Tank enemyTank=new Tank(100,100,false,this);
        
        List<Bullet> bullets=new ArrayList<Bullet>();
        List<Explode> explodes=new ArrayList<Explode>();    
    public void update(Graphics g) {
       if(image==null){
       image=this.createImage(FRAME_WIDTH,FRAME_HEIGHT);
       }
       Graphics offScreenImage=image.getGraphics();
       Color c=offScreenImage.getColor();//这里的作用只是将画笔颜色取出,以便后面将画笔颜色还原给系统,一个好的编程习惯
       offScreenImage.setColor(Color.black);
       offScreenImage.fillRect(0, 0, FRAME_WIDTH,FRAME_HEIGHT);
       offScreenImage.setColor(c);//将颜色还给系统
       paint(offScreenImage);
       g.drawImage(image,0,0,null);
    }
        
    public void paint(Graphics g) {
    Color c=g.getColor();
    g.setColor(Color.WHITE);
    g.drawString("Bullets:"+bullets.size(), 10, 40);
    //g.drawString("Explodes:"+explodes.size(),10,50);
    g.setColor(c);
    for(int i=0;i<bullets.size();i++){

    Bullet b=bullets.get(i);
    b.shotTank(enemyTank);
    if(b.isliveBullet())
       {
              b.drawBullet(g);
       }
    else {
    bullets.remove(i);
    }

     }



    for(int i=0;i<explodes.size();i++){
    Explode e=explodes.get(i);
    e.drawExplode(g);
    }
            enemyTank.drawTank(g);
    myTank.drawTank(g); } public TankWar(){
         super("坦克大战");
         this.setSize(FRAME_WIDTH,FRAME_HEIGHT);
         this.setLocation(40, 30);
         this.setVisible(true);
         this.setBackground(Color.BLACK);
         this.addWindowListener(new WindowAdapter(){
         public void windowClosing(WindowEvent e){
         System.exit(0);
         }
         });
         this.addKeyListener(new TankMonitor());
         new Thread(new TankThread()).start();
         this.setResizable(false);
          }
    private class TankThread implements Runnable{
    public void run(){
    while(true){
    repaint();
    try {
    Thread.sleep(50);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }
    private class TankMonitor extends KeyAdapter{
    public void keyPressed(KeyEvent e){
    myTank.keyPressed(e);
    }
    public void keyReleased(KeyEvent e){
    myTank.KeyReleased(e);
    }
    }
    public static void main(String[] args) {
    new TankWar(); }}
      

  5.   

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    public class Bullet {
    private int x;//子弹坐标
    private int y;

    public static final int BR=10;//子弹的高和宽

    private Tank.direction bDir;//枚举引用

    private TankWar tw;

    private static final int X_SPEED=15;//子弹速度
    private static final int Y_SPEED=15;

    private boolean liveBullet=true;//子弹存在状态标志

    public boolean isliveBullet() {
    return liveBullet;
    } public Bullet(int x, int y, Tank.direction dir) {
    this.x = x;
    this.y = y;
    bDir = dir;
    }

    public void drawBullet(Graphics g){//画子弹
    if(!liveBullet)return;
    Color c=g.getColor();
    g.setColor(Color.yellow);
    g.fillOval(x, y, BR, BR);
    g.setColor(c);


    move();
    } public void move() {//子弹运动
    switch(bDir){
    case L:x-=X_SPEED;break;
    case LU:x-=X_SPEED;y-=Y_SPEED;break;
    case U:y-=Y_SPEED;break;
    case UR:x+=X_SPEED;y-=Y_SPEED;break;
    case R:x+=X_SPEED;break;
    case RD:x+=X_SPEED;y+=Y_SPEED;break;
    case D:y+=Y_SPEED;break;
    case DL:x-=X_SPEED;y+=Y_SPEED;break;
    }
    if(x<0||y<0||x>TankWar.FRAME_WIDTH||y>TankWar.FRAME_HEIGHT){
    liveBullet=false;
    }
    }

       public Rectangle getRect(){//获取一个矩形
       return new Rectangle(x,y,BR,BR);
       }
       
       public boolean shotTank(Tank t){//打击坦克
        if(this.getRect().intersects(t.getRect())&&t.isLiveTank())//当坦克的所在的矩形和炮弹所在的矩形有相交,并且坦克是活动的
        {                                                               //此时将坦克销毁
        this.setliveBullet(false);
        t.setLiveTank(false);
        Explode c=new Explode(x,y,tw);
        tw.explodes.add(c);
        return true;
        }
        return false;
       }public void setliveBullet(boolean liveBullet) {
    this.liveBullet = liveBullet;
    }

    }import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    import java.awt.event.KeyEvent;
    import java.util.ArrayList;
    import java.util.List;
    public class Tank {
    private int x;//坦克距左上角的坐标
    private int y;

    private static final int X_SPEED=5;//坦克的移动速度
    private static final int Y_SPEED=5;

    private static final int TR=40;//坦克的宽和高

    private boolean tankActor;//坦克角色

    enum direction {L,LU,U,UR,R,RD,D,DL,STOP};

    private direction dir=direction.R;//坦克方向

    private boolean flag_L=false;//方向键的状态
    private boolean flag_U=false;
    private boolean flag_R=false;
    private boolean flag_D=false;

    private direction ptDir=direction.D;//炮筒方向

    private TankWar tw;
    private boolean liveTank=true;//坦克存活标志

    public boolean isLiveTank() {
    return liveTank;
    } public void setLiveTank(boolean liveTank) {
    this.liveTank = liveTank;
    } public Tank(int x, int y,boolean tankActor) {
    this.x = x;
    this.y = y;
    this.tankActor=tankActor;
    } public Tank(int x,int y,boolean tankActor,TankWar tw){
    this(x,y,tankActor);
    this.tw=tw;
    }

    public void drawTank(Graphics g) {
    if(!liveTank)return;

    Color c=g.getColor();
    if(tankActor==true)g.setColor(Color.RED);
    else g.setColor(Color.WHITE);
    g.fillOval(x, y, TR, TR);



    switch(ptDir){//画炮筒
    case L:
            g.drawLine(x-8, y+TR/2, x+TR/2, y+TR/2);
    break;
    case LU:
    g.drawLine(x-2, y-2, x+TR/2, y+TR/2);
    break;
    case U:
    g.drawLine(x+TR/2, y-8, x+TR/2, y+TR/2);
    break;
    case UR:
    g.drawLine(x+TR, y, x+TR/2, y+TR/2);
    break;
    case R:
    g.drawLine(x+TR+8, y+TR/2, x+TR/2, y+TR/2);
    break;
    case RD:
    g.drawLine(x+TR, y+TR, x+TR/2, y+TR/2);
    break;
    case D:
    g.drawLine(x+TR/2, y+TR+8, x+TR/2, y+TR/2);
    break;
    case DL:
    g.drawLine(x, y+TR, x+TR/2, y+TR/2);
    break;
    }

    move();

    }    public void keyPressed(KeyEvent e){
         int key=e.getKeyCode();
        
         switch(key){
        
         case KeyEvent.VK_LEFT: flag_L=true; break;
         case KeyEvent.VK_UP: flag_U=true; break;
         case KeyEvent.VK_RIGHT: flag_R=true; break;
         case KeyEvent.VK_DOWN: flag_D=true; break;
         }
        
        }
        public void KeyReleased(KeyEvent e){
         int key=e.getKeyCode();
         switch(key){
         case KeyEvent.VK_CONTROL:
         tw.bullets.add(shot());
         break;
         case KeyEvent.VK_LEFT: flag_L=false; break;
         case KeyEvent.VK_UP: flag_U=false; break;
         case KeyEvent.VK_RIGHT: flag_R=false; break;
         case KeyEvent.VK_DOWN: flag_D=false; break;
         }
      
        }
        
        public Bullet shot(){//发射炮弹
         Bullet bul=new Bullet(x+Tank.TR/2-Bullet.BR/2,y+Tank.TR/2-Bullet.BR/2,ptDir);
              return bul;
        }
        
        public void move(){//坦克运动
         if(flag_L&&!flag_U&&!flag_R&&!flag_D){x-=X_SPEED;ptDir=direction.L;}//左
           else if(!flag_L&&flag_U&&!flag_R&&!flag_D)//上
           {
           y-=Y_SPEED;
               ptDir=direction.U;
           }
           else if(!flag_L&&!flag_U&&flag_R&&!flag_D)//右
           {
           x+=X_SPEED;
               ptDir=direction.R;
           }
           else if(!flag_L&&!flag_U&&!flag_R&&flag_D)//下
           {
           y+=Y_SPEED;ptDir=direction.D;
           }
           else if(flag_L&&flag_U&&!flag_R&&!flag_D)//左上
           {
           x-=X_SPEED;
                  y-=Y_SPEED;
                  ptDir=direction.LU;
           }
           else if(!flag_L&&flag_U&&flag_R&&!flag_D)//右上
           { 
           x+=X_SPEED;
               y-=Y_SPEED;
               ptDir=direction.UR;
           }
           else if(!flag_L&&!flag_U&&flag_R&&flag_D)//右下
           {
           x+=X_SPEED;
               y+=Y_SPEED;
               ptDir=direction.RD;
           }
           else if(flag_L&&!flag_U&&!flag_R&&flag_D)//左下
           {
           x-=X_SPEED;
               y+=Y_SPEED;
               ptDir=direction.DL;
           }
           else if(!flag_L&&!flag_U&&!flag_R&&!flag_D)//Stop
           {
                  ptDir=this.ptDir;
           }
        
         //不让坦克出界
           if(x<20){x=20;}
           if(y<40){y=40;}
           if(y+TR>TankWar.FRAME_HEIGHT-20){y=TankWar.FRAME_HEIGHT-TR-20;}
           if(x+TR>TankWar.FRAME_WIDTH-20){x=TankWar.FRAME_WIDTH-TR-20;}
           
        
        }
        
        
       
        
        public Rectangle getRect(){
         return new Rectangle(x,y,TR,TR);
        }
        }
    import java.awt.Color;
    import java.awt.Graphics;
    public class Explode {
      private int x;//爆炸图像的x,y坐标
      private int y;
      
      private int[] diameter={2,8,19,40,60,35,10,3};//爆炸图像的直径  private int step=0;//爆炸是一步一步的进行的,表示步数
      
      private TankWar tw;
      
      private boolean liveExplode=true;//爆炸对象的状态
      
      public Explode(int x,int y,TankWar tw){
      this.x=x;
      this.y=y;
      this.tw=tw;
      }
      
      public void drawExplode(Graphics g){//画爆炸
      if(!liveExplode){
      tw.explodes.remove(this);
      return;
      }
      
      if(step==diameter.length)//当步数等于直径数组的长度,将爆炸状态消除,将步数归零
      {
      liveExplode=false;
      step=0;
      return;
      }
      Color c=g.getColor();
      g.setColor(Color.ORANGE);
      g.fillOval(x, y, diameter[step], diameter[step]);
      g.setColor(c);
      step++;
      }
      

    }
    这个是源代码,麻烦各位看看...在线等待。用debug调试了,但是到 public boolean shotTank(Tank t)的
       这条语句 if(this.getRect().intersects(t.getRect())&&t.isLiveTank()不执行里面的就跳过去了...苦恼
      

  6.   

    哦  打扰各位了哈  小弟刚刚调试出来了  是因为在explode里面的tw没有初始化 ,所以导致空指针问题。我想请教一个问题,空指针产生的根本原因是什么啊?
      

  7.   

    “if(x <0 ¦ &brvbary <0 ¦ &brvbarx>TankWar.FRAME_WIDTH ¦ &brvbary>TankWar.FRAME_HEIGHT){ ”是什么,编译失败
      

  8.   


    String s = null;
    s.trim();访问虚无的并不存在的对象的成员(实例域或实例方法)。
      

  9.   

    我知道问题的根源了。是因为我在Bullet,Explode,Tank里面都有一个TankWar的引用tw,而在shotTank里对tw的引用产生了混乱引用,虽然电脑可以知道,但是人很容易就被迷惑了,其实引用了那么多的tw但没一个初始化过,所以会产生空指针异常。