2014-04-17 139 views
0

因此,我遵循一个免费手册,指导如何在Java中编写Asteroids,并且它运行良好。我想将它添加到程序中,以便我可以调用它,运行一段时间,然后让它返回一个int。我正在制作的程序是一个应用程序,我一直在寻找一段时间尝试和失败,找出如何使它作为应用程序运行。我在这里读的东西,说我应该这样做:将Java Applet转换为应用程序

public class Main extends JFrame { 
public static void main(String[] args) {   
    AsteroidsGame game = new AsteroidsGame(); 
    JFrame frame = new JFrame(); 
    frame.setLayout(new GridLayout (1,1)); 
    frame.add(game); 
    frame.setSize(500,500);   
    game.init(); 
    game.start();  
    frame.setVisible(true); 
    } 

}

但后来我得到一个错误

异常线程 “main” 显示java.lang.NullPointerException

在AsteroidsGame.init(AsteroidsGame.java:49)

在Main.main(Main.java:15)

指向我到下面的线49,和我的game.init()为线15

 g = img.getGraphics(); 

下面是该AsteroidsGame的代码,我太累了,想了。我只需要让它作为应用程序运行,其他任何代码更改都是无关紧要的。我知道这是很多代码,但我希望这是我错过的一件简单的事情。任何帮助是极大的赞赏。谢谢!

import java.applet.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.util.Random; 

public class AsteroidsGame extends Applet implements Runnable, KeyListener { 
Thread thread; 
Dimension dim; 
Image img; 
Graphics g; 
long endTime, startTime, framePeriod; 
Ship ship; 
boolean paused; // True if the game is paused. Enter is the pause key 
Shot[] shots; 
int numShots; 
boolean shooting; 
Asteroid[] asteroids; // the array of asteroids 
int numAsteroids; // the number of asteroids currently in the array 
double astRadius, minAstVel, maxAstVel; // values used to create 
// asteroids 
int astNumHits, astNumSplit; 
int level; // the current level number 
int money; 
double fuel; 
Random rand = new Random(); 

public void init() { 
    resize(500, 500); 
    shots = new Shot[41]; // 41 is a shot's life period plus one. 
    // since at most one shot can be fired per frame, 
    // there will never be more than 41 shots if each one only 
    // lives for 40 frames. 
    numAsteroids = 0; 
    level = rand.nextInt(25)+1; // will be incremented to 1 when first level is set up 
    astRadius = 10; // values used to create the asteroids 
    minAstVel = 2; 
    maxAstVel = 8; 
    astNumHits = 3; 
    astNumSplit = 2; 
    money = 0; 
    fuel = 100; 

    endTime = 0; 
    startTime = 0; 
    framePeriod = 25; 
    addKeyListener(this); // tell it to listen for KeyEvents 
    dim = getSize(); 
    img = createImage(dim.width, dim.height); 
    g = img.getGraphics(); 
    thread = new Thread(this); 
    thread.start(); 
} 

public void setUpNextLevel() { // start new level with one more asteroid 
    level++; 
    // create a new, inactive ship centered on the screen 
    // I like .35 for acceleration, .98 for velocityDecay, and 
    // .1 for rotationalSpeed. They give the controls a nice feel. 
    ship = new Ship(250, 250, 0, .35, .98, .1, 12); 
    numShots = 0; // no shots on the screen at beginning of level 
    paused = false; 
    shooting = false; 
    // create an array large enough to hold the biggest number 
    // of asteroids possible on this level (plus one because 
    // the split asteroids are created first, then the original 
    // one is deleted). The level number is equal to the 
    // number of asteroids at it's start. 
    asteroids = new Asteroid[level 
      * (int) Math.pow(astNumSplit, astNumHits - 1) + 1]; 
    numAsteroids = level; 
    // create asteroids in random spots on the screen 
    for (int i = 0; i < numAsteroids; i++) 
     asteroids[i] = new Asteroid(Math.random() * dim.width, 
       Math.random() * dim.height, astRadius, minAstVel, 
       maxAstVel, astNumHits, astNumSplit); 
} 

public void paint(Graphics gfx) { 
    g.setColor(Color.black); 
    g.fillRect(0, 0, 500, 500); 
    for (int i = 0; i < numShots; i++) 
     // draw all the shots on the screen 
     shots[i].draw(g); 
    for (int i = 0; i < numAsteroids; i++) 
     asteroids[i].draw(g); 
    ship.draw(g); // draw the ship 
    g.setColor(Color.cyan); // Display level number in top left corner 
    g.drawString("Level " + level, 20, 20); 
    g.drawString("Money " + money, 80, 20); 
    g.drawString("Fuel " + fuel, 20, 50); 
    gfx.drawImage(img, 0, 0, this); 
} 

public void update(Graphics gfx) { 
    paint(gfx); 
} 

public void run() { 
    for (;;) { 
     startTime = System.currentTimeMillis(); 
     // start next level when all asteroids are destroyed 
     if (numAsteroids <= 0) 
      setUpNextLevel(); 
     if (!paused) { 
      ship.move(dim.width, dim.height); // move the ship 
      // move shots and remove dead shots 
      for (int i = 0; i < numShots; i++) { 
       shots[i].move(dim.width, dim.height); 
       // removes shot if it has gone for too long 
       // without hitting anything 
       if (shots[i].getLifeLeft() <= 0) { 
        // shifts all the next shots up one 
        // space in the array 
        deleteShot(i); 
        i--; // move the outer loop back one so 
        // the shot shifted up is not skipped 
       } 

      } 
      if(ship.accelerating && fuel>0){ 
       fuel -= 1.5; 
      } 
      if(ship.accelerating && fuel == 0) 
      { 
       ship.accelerating = false; 
      } 
      // move asteroids and check for collisions 
      updateAsteroids(); 
      if (shooting && ship.canShoot()) { 
       // add a shot on to the array 
       shots[numShots] = ship.shoot(); 
       numShots++; 
      } 
     } 
     repaint(); 
     try { 
      endTime = System.currentTimeMillis(); 
      if (framePeriod - (endTime - startTime) > 0) 
       Thread.sleep(framePeriod - (endTime - startTime)); 
     } catch (InterruptedException e) { 
     } 
    } 
} 

private void deleteShot(int index) { 
    // delete shot and move all shots after it up in the array 
    numShots--; 
    for (int i = index; i < numShots; i++) 
     shots[i] = shots[i + 1]; 
    shots[numShots] = null; 
} 

private void deleteAsteroid(int index) { 
    // delete asteroid and shift ones after it up in the array 
    numAsteroids--; 
    for (int i = index; i < numAsteroids; i++) 
     asteroids[i] = asteroids[i + 1]; 

    asteroids[numAsteroids] = null; 
} 

private void addAsteroid(Asteroid ast) { 
    // adds the asteroid passed in to the end of the array 
    asteroids[numAsteroids] = ast; 
    numAsteroids++; 
} 

private void updateAsteroids() { 
    for (int i = 0; i < numAsteroids; i++) { 
     // move each asteroid 
     asteroids[i].move(dim.width, dim.height); 
     // check for collisions with the ship, restart the 
     // level if the ship gets hit 
     if (asteroids[i].shipCollision(ship)) { 
      money+= Math.random()*1000; 
      deleteAsteroid(i); 

      //level--; // restart this level 
      //numAsteroids = 0; 
      return; 
     } 
     // check for collisions with any of the shots 
     for (int j = 0; j < numShots; j++) { 
      if (asteroids[i].shotCollision(shots[j])) { 
       // if the shot hit an asteroid, delete the shot 
       deleteShot(j); 
       // split the asteroid up if needed 
       if (asteroids[i].getHitsLeft() > 1) { 
        for (int k = 0; k < asteroids[i].getNumSplit(); k++) 
         addAsteroid(asteroids[i].createSplitAsteroid(
           minAstVel, maxAstVel)); 
       } 
       // delete the original asteroid 
       deleteAsteroid(i); 
       j = numShots; // break out of inner loop - it has 
       // already been hit, don't need to check 
       // for collision with other shots 
       i--; // don't skip asteroid shifted back into 
       // the deleted asteroid's position 
      } 
     } 
    } 
} 

public void keyPressed(KeyEvent e) { 
    if (e.getKeyCode() == KeyEvent.VK_ENTER) { 
     // These first two lines allow the asteroids to move 
     // while the player chooses when to enter the game. 
     // This happens when the player is starting a new life. 
     if (!ship.isActive() && !paused) 
      ship.setActive(true); 
     else { 
      paused = !paused; // enter is the pause button 
      if (paused) // grays out the ship if paused 
       ship.setActive(false); 
      else 

       ship.setActive(true); 
     } 
    } else if (paused || !ship.isActive()) // if the game is 
     return; // paused or ship is inactive, do not respond 
    // to the controls except for enter to unpause 
    else if (e.getKeyCode() == KeyEvent.VK_UP) 
    {if(fuel>0){ 
     ship.setAccelerating(true); 

     //fuel -= 1.5; 
     } 
    else{ 
     fuel = 0; 
    } 
} 
    else if (e.getKeyCode() == KeyEvent.VK_LEFT) 
    { 

     ship.setTurningLeft(true); 
    } 

    else if (e.getKeyCode() == KeyEvent.VK_RIGHT) 
     ship.setTurningRight(true); 
     //else if (e.getKeyCode() == KeyEvent.VK_CONTROL) 
     //shooting = true; // Start shooting if ctrl is pushed 
} 

public void keyReleased(KeyEvent e) { 
    if (e.getKeyCode() == KeyEvent.VK_UP) 
     ship.setAccelerating(false); 
    else if (e.getKeyCode() == KeyEvent.VK_LEFT) 
     ship.setTurningLeft(false); 
    else if (e.getKeyCode() == KeyEvent.VK_RIGHT) 
     ship.setTurningRight(false); 
    //else if (e.getKeyCode() == KeyEvent.VK_CONTROL) 
     //shooting = false; 
} 

public void keyTyped(KeyEvent e) { 
} 
} 
+0

什么是你的createImage(dim.width,dim.height)方法返回? – Diluu

回答

0

我相信,createImage()将返回null,直到组件实际在屏幕上,而我相信是线程启动后。

取而代之的是:

img = createImage(dim.width, dim.height); 
g = img.getGraphics(); 
thread = new Thread(this); 
thread.start(); 

尝试:

new Thread(new Runnable() { 
    public void run() { 
     do { 
      try { 
       Thread.sleep(25); 
      } catch(InterruptedException e) { 
       System.out.println("wait interrupted"); 
       break; 
      } 
     } while(!isDisplayable()); 
     // Now it should be safe to make these calls. 
     img= createImage(dim.width, dim.height); 
     g = img.getGraphics(); 
     start(); 
    } 
}).start();