0

ACMライブラリを使用してJavaプログラムをコンパイルして実行すると、このエラーが発生し続けます

Exception in thread "Thread-3" java.lang.NullPointerException
    at SpaceTravel.getBlackHoleDistance(SpaceTravel.java:148)
    at SpaceTravel.gameOverBlackHole(SpaceTravel.java:132)
    at BlackHole.oneTimeStep(BlackHole.java:84)
    at BlackHole.run(BlackHole.java:45)
    at java.lang.Thread.run(Unknown Source)

これはゲームクラスです:

import acm.graphics.*;
import acm.program.*;
import acm.util.*;
import java.awt.*;

public class SpaceTravel extends GraphicsProgram {
  // specify the size of the window
  public static int APPLICATION_WIDTH = 1280;
  public static int APPLICATION_HEIGHT = 600;

  // class constants
  private static final double
    PLANET_SIZE = 80,
    BLACK_HOLE_SIZE = 100,
    STAR_SIZE = 2;

  // instance variables
  private GOval ice, fire, iron;
  private GPoint lastPoint;
  private boolean isDragging = false;
  private GLabel gameOverText, goal, win;
  private BlackHole blackhole1, blackhole2;
  private RandomGenerator rand = new RandomGenerator();

  // init method, draw the graphics objects
  public void init() {

    setBackground(Color.BLACK);

    // call the randomly colored stars method
    drawStars();

    // call 1 instance of BlackHole class
    blackhole1 = new BlackHole(BLACK_HOLE_SIZE, 5, 2, this);
    add(blackhole1, APPLICATION_WIDTH-400, APPLICATION_HEIGHT/2 );
    new Thread(blackhole1).start();

    // call 1 instance of BlackHole class, but name it differently
    blackhole2 = new BlackHole(BLACK_HOLE_SIZE, 3, -4, this);
    add(blackhole2, APPLICATION_WIDTH-200, APPLICATION_HEIGHT/2 );
    new Thread(blackhole2).start();

    // draw fire planet
    fire = drawCircleCentered(100, 400, PLANET_SIZE);
    add(fire);
    fire.setFilled(true);
    fire.setColor(Color.RED);

    // draw ice planet
    ice = drawCircleCentered(100, 100, PLANET_SIZE);
    add(ice);
    ice.setFilled(true);
    ice.setColor(Color.BLUE);

    // draw iron planet
    iron = drawCircleCentered(100, 250, PLANET_SIZE);
    add(iron);
    iron.setFilled(true);
    Color grey = new Color(34, 34, 34);
    iron.setColor(grey);

    // game over text
    gameOverText = new GLabel ("GAME OVER", APPLICATION_WIDTH/2 - 250, APPLICATION_HEIGHT/2);
    gameOverText.setColor(Color.RED);
    gameOverText.setFont(new Font("DEFAULT_FONT", Font.BOLD, 90));

    // goal text
    goal = new GLabel ("GOAL", APPLICATION_WIDTH-150, APPLICATION_HEIGHT/2);
    goal.setColor(Color.RED);
    goal.setFont(new Font("DEFAULT_FONT", Font.BOLD, 20));
    add(goal);

    // win text
    win = new GLabel ("WINRAR IS YOU!", APPLICATION_WIDTH/2 - 350, APPLICATION_HEIGHT/2);
    win.setColor(Color.RED);
    win.setFont(new Font("DEFAULT_FONT", Font.BOLD, 90));
  }

  // checker method if the ice and fire plantes touch, call the game over method below.
  private void checkFireIce(GOval fire, GOval ice) {
    if(getDistance(fire, ice) < PLANET_SIZE ) {
      gameOver(fire);
    }
  }

  // checker method for when fire planet gets to the goal text, call the game winning method below
  private void checkPlanetsGoal() {
    if(fire.getBounds().intersects(goal.getBounds())) {
      winGame();
    }
  }

  // start dragging if the ball is pressed
  public void mousePressed(GPoint point) {
    if (ice.contains(point)) {
      isDragging = true;
      lastPoint = point;
    }
  }

  // move the ball when it is dragged, and call checking methods for game winning or game over conditions
  public void mouseDragged(GPoint point) {
    checkFireIce(fire, ice);
    checkPlanetsGoal();
    if (isDragging) {
      ice.move(point.getX()-lastPoint.getX(),
               point.getY()-lastPoint.getY());
      lastPoint = point;
      // bump the planets
      bump(ice, iron);
      bump(iron, fire);
    }
  }

  // checking method for if any of the planets have touched an instance of black hole
  public void gameOverBlackHole(BlackHole blackhole) {
    double a = getBlackHoleDistance(fire, blackhole);
    double b = getBlackHoleDistance(ice, blackhole);
    double c = getBlackHoleDistance(iron, blackhole);
    if(a < BLACK_HOLE_SIZE/2 + PLANET_SIZE/2) {
      gameOver(fire);
    }
    if(b < BLACK_HOLE_SIZE/2 + PLANET_SIZE/2) {
      gameOver(ice);
    }
    if(c < BLACK_HOLE_SIZE/2 + PLANET_SIZE/2) {
      gameOver(iron);
    }
  }

  // get distance between a black hole instance and a planet
  private double getBlackHoleDistance(GOval planet, BlackHole blackhole) {
    return GMath.distance(planet.getX()+PLANET_SIZE/2, planet.getY()+PLANET_SIZE/2,

                          blackhole.getX(), blackhole.getY());
  }

  // bump helper method, calculates how much to move a tangent planet by when it is being bumped by another
  private void bump(GOval planet1, GOval planet2) {
    double offset = PLANET_SIZE+1.5 - getDistance(planet1, planet2);
    if (offset > 0) {
      planet2.move(offset*(planet2.getX()-planet1.getX())/PLANET_SIZE,
                   offset*(planet2.getY()-planet1.getY())/PLANET_SIZE);
    }
  }

  // a helper method, compute the distance between the centers of the balls
  private double getDistance(GOval planet1, GOval planet2) {
    return GMath.distance(planet1.getX()+PLANET_SIZE/2, planet1.getY()+PLANET_SIZE/2,

                          planet2.getX()+PLANET_SIZE/2, planet2.getY()+PLANET_SIZE/2);
  }

  // a helper method, draw a circle centered at the given location
  private GOval drawCircleCentered(double centerX, double centerY, double size) {
    return new GOval(centerX-size/2, centerY-size/2, size, size);
  }

  // a helper method, draw randomly colored stars 
  private void drawStars() {
    for (int i = 0; i < 1000; i++) {
      GOval star = drawCircleCentered(rand.nextDouble(0, APPLICATION_WIDTH), rand.nextDouble(0, APPLICATION_HEIGHT), STAR_SIZE);
      add(star);
      star.setFilled(true);
      star.setColor(rand.nextColor());
    }    
  }

  // helper method to switch dragging off when mouse is released from window
  public void mouseReleased(GPoint point) {
    isDragging = false;
  }

  // helper method to switch dragging off, remove the planet that touched the goal, and display game over text
  public void gameOver(GOval planet) {
    isDragging = false;
    remove(planet);
    add(gameOverText);
  }

  // helper method to switch dragging off, remove planets, and display win text
  private void winGame() {
    isDragging = false;
    add(win);
    remove(fire);
    remove(ice);
    remove(iron);
    remove(goal);
  }
}

そして、これはゲームを終わらせることができるブラックホールを作成するクラスです。

// import libraries
import acm.program.*;
import acm.graphics.*;
import acm.util.*;
import java.awt.*;
import java.util.*;

public class BlackHole extends GCompound implements Runnable {

  // instance variables
  private double size, xSpeed, ySpeed;
  private SpaceTravel game;
  private boolean stopHammerTime = false;

  // constructor for BlackHole
  public BlackHole(double size, double xSpeed, double ySpeed, SpaceTravel game) {

    // save the parameters size, xSpeed, ySpeed, centerX, centerY, and game
    this.size = size;
    this.xSpeed = xSpeed;
    this.ySpeed = ySpeed;
    this.game = game;

    // call method drawBlackhole
    drawBlackhole(0, 0, size, 3, 40);
  }

  // run method, move the black hole until it hits a planet || stopHammerTime = true
  public void run() {
    while(!stopHammerTime) {
      oneTimeStep();
    }
  }

  // helper method, creates a black hole
  private void drawBlackhole(double centerX, double centerY, double size, double gap, int layers) {

    for (int i = 0; i < layers; i++) {

      // this gradient color will lighten each time the for loop completes
      Color gradient = new Color(0 + 5*i, 0 + 5*i, 0 + 5*i);

      GOval ring = drawCircleCentered(centerX, centerY, size-gap*2*i);
      add(ring);
      ring.setFilled(true);
      ring.setColor(gradient);
    }
  }

  // a helper method, draw a circle centered at the given location
  private GOval drawCircleCentered(double centerX, double centerY, double size) {
    return new GOval(centerX-size/2, centerY-size/2, size, size);
  }

  // a helper method, move the blackHole in oneTimeStep
  private void oneTimeStep() {
    double x = getX();
    double y = getY();

    // if the black hole hits the left or the right wall, reverse the x-speed
    if (x < size/2 || x+size/2 > game.getWidth()) xSpeed = -xSpeed;

    // if the black hole hits the top or the bottom wall, reverse the y-speed
    if (y < size/2 || y+size/2 > game.getHeight()) ySpeed = -ySpeed;

    // move the black hole by a small interval, incorporating changes from if statements
    move(xSpeed, ySpeed);

    // check if a planet has touched a blackhole
    game.gameOverBlackHole(this);

    // delay
    pause(20);
  }  
}

クラスの呼び出しは正しいと確信していますが、何らかの理由で、呼び出されたblackhole2がクラッシュします。

4

3 に答える 3

4
Exception in thread "Thread-3" java.lang.NullPointerException

NullPointerExceptionスレッドの実行中に発生します"Thread-3"

SpaceTravel.javaファイルの148行目。

Thread-3実行中に、148行目が参照に対して何らかの操作を実行しようとしているようです。nullその結果、がになりNullPointerExceptionます。

于 2012-10-04T18:43:11.857 に答える
1

明らかにクラッシュするコードは次のようになります。

return GMath.distance(planet.getX()+PLANET_SIZE/2, planet.getY()+PLANET_SIZE/2,
                      blackhole.getX(), blackhole.getY());

ほとんどの場合、planetまたはblackholeパラメータはnullです。デバッガーを使用するか、どれを使用するかを判断println()します。このコードは、次の3つの場所から呼び出されます。

double a = getBlackHoleDistance(fire, blackhole);
double b = getBlackHoleDistance(ice, blackhole);
double c = getBlackHoleDistance(iron, blackhole);

あなたの行番号は少しずれていますが、私はそれが最初の行であるとあえて言うので、またはのどちらfireblackholeですnull

于 2012-10-04T18:45:37.043 に答える
0

簡単な分析:

gameOverBlackHoleメソッドがフォームBlackHoleクラスと呼ばれると、そのメソッド内でremoveが発生するため、問題が発生します。1つのスレッドの実行中に削除が発生した場合、NPEが発生します

これは、複数のスレッド間でオブジェクトの状態を共有する場合に問題が発生する可能性がある例です。

于 2012-10-04T19:00:59.883 に答える