简体   繁体   中英

NullPointerException after pressing reset button. (Processing)

I am trying to make a reset button for this program and I've looked everywhere and i can't find a method that works. i tried to have it so at the end of the game, when you lose, you press "Restart" the game would start from the beginning of the sketch. The program works fine but once you press the Restart button, I get a NullPointerException error in the console area and the game doesn't restart. I get the NullPointerException error in the line "if (!drop[i].finished) {". I've read that it has to do with the constructor not initializing the array, but it already initialized it. Does this have to do with the reset button and the constructor not re-initializing the array or is it something else? I don't know why, but very rarely it works, but all the text is shifted over to the left and it goes off the screen. Thank you for the help.

boolean button = false;
Catcher catcher;    
Timer timer;        
Drop[] drops;      
int totalDrops = 0; 
int x = 200;
int y = 100;
int w = 150;
int h = 60;

// Is the game over?
boolean gameOver = false;

// Variables for score level lives and level counter
int score = 0;     
int level = 1;      
int lives = 10;     //10 lives per level, resets at next level
int levelCounter = 0;

PFont f;
void reset() {
  score = 0;
  level = 1;
  levelCounter = 0;
  lives = 10;
  timer.setTime(constrain(300-level*25,0,300));
  totalDrops = 0; 
  gameOver = false;
  button = false;
}


void setup() {
  size(400,400);
  smooth();
  catcher = new Catcher(32);
  drops = new Drop[50];    
  timer = new Timer(300);   
  timer.start();  
  gameOver = false;  
  finished = false;
  level = 1;
  score = 0;


  f = createFont("Arial",12,true); 
}

void draw() {
  background(255);

  // If the game is over
  rectMode (CENTER);
  if (gameOver) {
    textFont(f,48);
    textAlign(CENTER);
    fill(0);
    text("GAME OVER",width/2,height/2);
    textFont(f,24);
    text("Your score was "+ score,200,225);
    textFont(f,16);
    text("You reached level "+ level,200,245);
    fill(255);
    stroke(0);
    rect(200,100,150,60);
    stroke(255);
    fill(0);
    textFont(f,20);
    text("Restart",200,107);


  } 
  else {

    // Set catcher location
    catcher.setLocation(mouseX,mouseY); 

    catcher.display(); 

    // Check the timer
    if (timer.isFinished()) {
      if (totalDrops < drops.length) {
        drops[totalDrops] = new Drop();

        totalDrops++;
      }
      timer.start();
    }

    // Move and display all drops
    for (int i = 0; i < totalDrops; i++ ) {


      if (!drops[i].finished) {

        drops[i].move();
        drops[i].display();
        if (drops[i].reachedBottom()) {
          levelCounter++;
          drops[i].finished(); 
          // If the drop reaches the bottom a live is lost and you lose 5 points
          lives--;
          score=score-5;
          // If lives reach 0 the game is over
          if (lives <= 0) {
            gameOver = true; 
          }
        } 

        // Everytime you catch a drop, the score goes up
        if (catcher.intersect(drops[i])) {
          drops[i].finished();
          levelCounter++;
          score=score+10;
        }
      }
    }


    // If all the drops are done, that level is over!
    if (levelCounter >= drops.length) {
      // Go up a level
      level++;
      // Reset all game elements
      levelCounter = 0;
      lives = 10;
      timer.setTime(constrain(300-level*25,0,300));
      totalDrops = 0; 
    }





    // Display number of lives left
    rectMode(CORNER);
    textFont(f,14);
    fill(0);
    text("Lives left: " + lives,10,20);
    rect(10,24,lives*10,10);

    text("Level: " + level,300,20);
    text("Score: " + score,300,40);
  }

if (mousePressed) {
  if (mouseX >= x && mouseX <= x + w && mouseY >= y && mouseY <= y + h && gameOver == true){
    setup();
  }
}
println();
}
//----------------------Drop Class-----------------------------
class Drop {
  float x,y;  
  float speed; 
  color c;
  float r;     

  //Is the drop used?
  boolean finished = false;

  Drop() {
    r = 8;               
    x = random(width);     
    y = -r*4;              
    speed = random(2,5);   
    c = color(random(255),random(255),random(255)); 
  }


  void move() {

    y += speed; 
  }

  // Check if it hits the bottom
  boolean reachedBottom() {
    // If it passes the bottom
    if (y > height + r*4) { 
      return true;
    } 
    else {
      return false;
    }
  }


  void display() {
    fill(c);
    noStroke();
    for (int i = 2; i < r; i++ ) {
      ellipse(x,y + i*4,i*2,i*2);
    }
  }

  // If the drop is caught
  void finished() {
    finished = true;
  }
}

Here is the stack trace:

Exception in thread "Animation Thread" java.lang.NullPointerException
    at Raindrop_Catcher.draw(Raindrop_Catcher.java:113)
    at processing.core.PApplet.handleDraw(Unknown Source)
    at processing.core.PApplet.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:662)

It looks like you're only filling the array drops with objects inside an if statement:

// Check the timer
if (timer.isFinished()) {
  if (totalDrops < drops.length) {
    drops[totalDrops] = new Drop(); 

    totalDrops++;
  }
  timer.start();
}

So if the if statement evaluates to false, the array is still filled with null values, leading to NullPointerException . Make sure the array contains objects before you try to use them.

In your setup method, add this to make sure your array is filled with non-null values:

for (int i = 0; i < drops.length; i++)
{
     drops[i] = new Drop();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM