在开始之前,我知道我应该使用Swing而不是AWT,但这就是我正在使用的书所教的内容,因此,我现在才开始学习。

现在,我的问题是,为什么AppletViewer可以很好地运行此代码,但是我尝试过的每个浏览器(Chrome,Firefox,IE)都会引发以下错误:

java.lang.NullPointerException
   at ImageEntity.load(ImageEntity.java:61)
   at GalacticWar.init(GalacticWar.java:55)
   at com.sun.deploy.uitoolkit.impl.awt.AWTAppletAdapter.init(Unknown Source)
   at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
   at java.lang.Thread.run(Unknown Source)




GalacticWar.java

/*****************************************************
 * Beginning Java Game Programming, 2nd Edition
 * by Jonathan S. Harbour
 * GALACTIC WAR, Chapter 11
 *****************************************************/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.util.*;

/*****************************************************
 * Primary class for the game
 *****************************************************/
public class GalacticWar extends Applet implements Runnable, KeyListener  {
        //the main thread becomes the game loop
        Thread gameloop;
        //use this as a double buffer
        BufferedImage backbuffer;
        //the main drawing object for the back buffer
        Graphics2D g2d;
        //toggle for drawing bounding boxes
        boolean showBounds = false;

        //create the asteroid array
        int ASTEROIDS = 20;
        Asteroid[] ast = new Asteroid[ASTEROIDS];

        //create the bullet array
        int BULLETS = 10;
        Bullet[] bullet = new Bullet[BULLETS];
        int currentBullet = 0;

        //the player's ship
        ImageEntity ship = new ImageEntity(this);

        //create the identity transform
        AffineTransform identity = new AffineTransform();

        //create a random number generator
        Random rand = new Random();

        /*****************************************************
         * applet init event
         *****************************************************/
        public void init() {
            //create the back buffer for smooth graphics
            backbuffer = new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB);
            g2d = backbuffer.createGraphics();

            //set up the ship
            ship.setX(320);
            ship.setY(240);
            ship.load("spaceship1.png");
            ship.setGraphics(g2d);

            //set up the bullets
            for (int n = 0; n<BULLETS; n++) {
                bullet[n] = new Bullet();
            }

            //set up the asteroids
            for (int n = 0; n<ASTEROIDS; n++) {
                ast[n] = new Asteroid();
                ast[n].setRotationVelocity(rand.nextInt(3)+1);
                ast[n].setX((double)rand.nextInt(600)+20);
                ast[n].setY((double)rand.nextInt(440)+20);
                ast[n].setMoveAngle(rand.nextInt(360));
                double ang = ast[n].getMoveAngle() - 90;
                ast[n].setVelX(calcAngleMoveX(ang));
                ast[n].setVelY(calcAngleMoveY(ang));
            }

            //start the user input listener
            addKeyListener(this);
        }

        /*****************************************************
         * applet update event to redraw the screen
         *****************************************************/
        public void update(Graphics g) {
            //start off transforms at identity
            g2d.setTransform(identity);

            //erase the background
            g2d.setPaint(Color.BLACK);
            g2d.fillRect(0, 0, getSize().width, getSize().height);

            //print some status information
            g2d.setColor(Color.WHITE);
            g2d.drawString("Ship: " + Math.round(ship.getX()) + "," +
                Math.round(ship.getY()) , 5, 10);
            g2d.drawString("Move angle: " + Math.round(
                ship.getMoveAngle())+90, 5, 25);
            g2d.drawString("Face angle: " +  Math.round(
                ship.getFaceAngle()), 5, 40);

            //draw the game graphics
            drawShip();
            drawBullets();
            drawAsteroids();

            //repaint the applet window
            paint(g);
        }

        /*****************************************************
         * drawShip called by applet update event
         *****************************************************/
        public void drawShip() {
           // set the transform for the image
           ship.transform();
           ship.draw();

            //draw bounding rectangle around ship
            if (showBounds) {
                g2d.setTransform(identity);
                g2d.setColor(Color.BLUE);
                g2d.draw(ship.getBounds());
            }
        }

        /*****************************************************
         * drawBullets called by applet update event
         *****************************************************/
        public void drawBullets() {
            for (int n = 0; n < BULLETS; n++) {
                if (bullet[n].isAlive()) {
                    //draw the bullet
                    g2d.setTransform(identity);
                    g2d.translate(bullet[n].getX(), bullet[n].getY());
                    g2d.setColor(Color.MAGENTA);
                    g2d.draw(bullet[n].getShape());
                }
            }
        }

        /*****************************************************
         * drawAsteroids called by applet update event
         *****************************************************/
        public void drawAsteroids() {
            for (int n = 0; n < ASTEROIDS; n++) {
                if (ast[n].isAlive()) {
                    //draw the asteroid
                    g2d.setTransform(identity);
                    g2d.translate(ast[n].getX(), ast[n].getY());
                    g2d.rotate(Math.toRadians(ast[n].getMoveAngle()));
                    g2d.setColor(Color.DARK_GRAY);
                    g2d.fill(ast[n].getShape());

                    //draw bounding rectangle
                    if (showBounds) {
                        g2d.setTransform(identity);
                        g2d.setColor(Color.BLUE);
                        g2d.draw(ast[n].getBounds());
                    }
                }
            }
        }

        /*****************************************************
         * applet window repaint event--draw the back buffer
         *****************************************************/
        public void paint(Graphics g) {
            g.drawImage(backbuffer, 0, 0, this);
        }

        /*****************************************************
         * thread start event - start the game loop running
         *****************************************************/
        public void start() {
            gameloop = new Thread(this);
            gameloop.start();
        }
        /*****************************************************
         * thread run event (game loop)
         *****************************************************/
        public void run() {
            //acquire the current thread
            Thread t = Thread.currentThread();
            //keep going as long as the thread is alive
            while (t == gameloop) {
                try {
                    Thread.sleep(20);
                }
                catch(InterruptedException e) {
                    e.printStackTrace();
                }
                //update the game loop
                gameUpdate();
                repaint();
            }
        }
        /*****************************************************
         * thread stop event
         *****************************************************/
        public void stop() {
            gameloop = null;
        }

        /*****************************************************
         * move and animate the objects in the game
         *****************************************************/
        private void gameUpdate() {
            updateShip();
            updateBullets();
            updateAsteroids();
            checkCollisions();
        }

        /*****************************************************
         * Update the ship position based on velocity
         *****************************************************/
        public void updateShip() {
            //update ship's X position, wrap around left/right
            ship.incX(ship.getVelX());
            if (ship.getX() < -10)
                ship.setX(getSize().width + 10);
            else if (ship.getX() > getSize().width + 10)
                ship.setX(-10);
            //update ship's Y position, wrap around top/bottom
            ship.incY(ship.getVelY());
            if (ship.getY() < -10)
                ship.setY(getSize().height + 10);
            else if (ship.getY() > getSize().height + 10)
                ship.setY(-10);
        }

        /*****************************************************
         * Update the bullets based on velocity
         *****************************************************/
        public void updateBullets() {
            //move the bullets
            for (int n = 0; n < BULLETS; n++) {
                if (bullet[n].isAlive()) {
                    //update bullet's x position
                    bullet[n].incX(bullet[n].getVelX());
                    //bullet disappears at left/right edge
                    if (bullet[n].getX() < 0 ||
                        bullet[n].getX() > getSize().width)
                    {
                        bullet[n].setAlive(false);
                    }
                    //update bullet's y position
                    bullet[n].incY(bullet[n].getVelY());
                    //bullet disappears at top/bottom edge
                    if (bullet[n].getY() < 0 ||
                        bullet[n].getY() > getSize().height)
                    {
                        bullet[n].setAlive(false);
                    }
                }
            }
        }

        /*****************************************************
         * Update the asteroids based on velocity
         *****************************************************/
        public void updateAsteroids() {
            //move and rotate the asteroids
            for (int n = 0; n < ASTEROIDS; n++) {
                if (ast[n].isAlive()) {
                    //update the asteroid's X value
                    ast[n].incX(ast[n].getVelX());
                    if (ast[n].getX() < -20)
                        ast[n].setX(getSize().width + 20);
                    else if (ast[n].getX() > getSize().width + 20)
                        ast[n].setX(-20);

                    //update the asteroid's Y value
                    ast[n].incY(ast[n].getVelY());
                    if (ast[n].getY() < -20)
                        ast[n].setY(getSize().height + 20);
                    else if (ast[n].getY() > getSize().height + 20)
                        ast[n].setY(-20);

                    //update the asteroid's rotation
                    ast[n].incMoveAngle(ast[n].getRotationVelocity());
                    if (ast[n].getMoveAngle() < 0)
                        ast[n].setMoveAngle(360 - ast[n].getRotationVelocity());
                    else if (ast[n].getMoveAngle() > 360)
                        ast[n].setMoveAngle(ast[n].getRotationVelocity());
                }
            }
        }

        /*****************************************************
         * Test asteroids for collisions with ship or bullets
         *****************************************************/
        public void checkCollisions() {
            //check for ship and bullet collisions with asteroids
            for (int m = 0; m<ASTEROIDS; m++) {
                if (ast[m].isAlive()) {
                    //check for bullet collisions
                    for (int n = 0; n < BULLETS; n++) {
                        if (bullet[n].isAlive()) {
                            //perform the collision test
                            if (ast[m].getBounds().contains(
                                    bullet[n].getX(), bullet[n].getY()))
                            {
                                bullet[n].setAlive(false);
                                ast[m].setAlive(false);
                                continue;
                            }
                        }
                    }

                    //check for ship collision
                    if (ast[m].getBounds().intersects(ship.getBounds())) {
                        ast[m].setAlive(false);
                        ship.setX(320);
                        ship.setY(240);
                        ship.setFaceAngle(0);
                        ship.setVelX(0);
                        ship.setVelY(0);
                        continue;
                    }
                }
            }

        }

        /*****************************************************
         * key listener events
         *****************************************************/
        public void keyReleased(KeyEvent k) { }
        public void keyTyped(KeyEvent k) { }
        public void keyPressed(KeyEvent k) {
            int keyCode = k.getKeyCode();

            switch (keyCode) {

            case KeyEvent.VK_LEFT:
                //left arrow rotates ship left 5 degrees
                ship.incFaceAngle(-5);
                if (ship.getFaceAngle() < 0) ship.setFaceAngle(360-5);
                break;

            case KeyEvent.VK_RIGHT:
                //right arrow rotates ship right 5 degrees
                ship.incFaceAngle(5);
                if (ship.getFaceAngle() > 360) ship.setFaceAngle(5);
                break;

            case KeyEvent.VK_UP:
                //up arrow adds thrust to ship (1/10 normal speed)
                ship.setMoveAngle(ship.getFaceAngle() - 90);
                ship.incVelX(calcAngleMoveX(ship.getMoveAngle()) * 0.1);
                ship.incVelY(calcAngleMoveY(ship.getMoveAngle()) * 0.1);
//*********                if (!thrust.getClip().isActive())
//****                    thrust.play();
                break;

            //Ctrl, Enter, or Space can be used to fire weapon
            case KeyEvent.VK_CONTROL:
            case KeyEvent.VK_ENTER:
            case KeyEvent.VK_SPACE:
                //fire a bullet
                currentBullet++;
                if (currentBullet > BULLETS - 1) currentBullet = 0;
                bullet[currentBullet].setAlive(true);
                //point bullet in same direction ship is facing
                bullet[currentBullet].setX(ship.getCenterX());
                bullet[currentBullet].setY(ship.getCenterY());
                bullet[currentBullet].setMoveAngle(ship.getFaceAngle() - 90);
                //fire bullet at angle of the ship
                double angle = bullet[currentBullet].getMoveAngle();
                double svx = ship.getVelX();
                double svy = ship.getVelY();
                bullet[currentBullet].setVelX(svx + calcAngleMoveX(angle) * 2);
                bullet[currentBullet].setVelY(svy + calcAngleMoveY(angle) * 2);
                break;

            case KeyEvent.VK_B:
                //toggle bounding rectangles
                showBounds = !showBounds;
                break;
            }
        }

        /*****************************************************
         * calculate X movement value based on direction angle
         *****************************************************/
        public double calcAngleMoveX(double angle) {
            double movex = Math.cos(angle * Math.PI / 180);
            return movex;
        }

        /*****************************************************
         * calculate Y movement value based on direction angle
         *****************************************************/
        public double calcAngleMoveY(double angle) {
            double movey = Math.sin(angle * Math.PI / 180);
            return movey;
        }

}




ImageEntity.java

/*********************************************************
 * Base game image class for bitmapped game entities
 **********************************************************/
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.*;
import java.applet.*;
import java.net.*;

public class ImageEntity extends BaseGameEntity {
    //variables
    private Image image;
    private Applet applet;
    private AffineTransform at;
    private Graphics2D g2d;

    //default constructor
    ImageEntity(Applet a) {
        applet = a;
        setImage(null);
        setAlive(true);
    }

    //sets and returns the entity's image object
    public Image getImage() { return image; }
    public void setImage(Image image) { this.image = image; }

    //returns the width and height of the entity
    public int width() {
        return getImage().getWidth(applet);
    }
    public int height() {
        return getImage().getHeight(applet);
    }

    //returns the center of the entity in pixels
    public double getCenterX() {
        return getX() + width() / 2;
    }
    public double getCenterY() {
        return getY() + height() / 2;
    }

    //set reference to the drawing object
    public void setGraphics(Graphics2D g) {
        g2d = g;
    }

     private URL getURL(String filename) {
         URL url = null;
         try {
             url = this.getClass().getResource(filename);
         }
         catch (Exception e) { }
         return url;
     }

    //load an image file
    public void load(String filename) {
        setImage(applet.getImage(getURL(filename)));
        while(getImage().getWidth(applet) <= 0);
        double x = applet.getSize().width/2  - width()/2;
        double y = applet.getSize().height/2 - height()/2;
        at = AffineTransform.getTranslateInstance(x, y);
    }

    //move and rotate the entity
    public void transform() {
        at.setToIdentity();
        at.translate((int)getX() + width()/2, (int)getY() + height()/2);
        at.rotate(Math.toRadians(getFaceAngle()));
        at.translate(-width()/2, -height()/2);
    }

    //draw the entity
    public void draw() {
        g2d.drawImage(getImage(), at, applet);
    }

    //bounding rectangle
    public Rectangle getBounds() {
        return new Rectangle((int)getX(),(int)getY(),width(),height());
    }

}


我知道代码似乎找不到spaceship1.png,但我向您保证。为什么代码可以在AppletViewer中编译并完全正常工作,但是仅在浏览器中抛出此异常?

最佳答案

原来该错误是由我今天早些时候下载的Java 7_25引起的。新版本显然无法加载applet,或者至少是从本地文件加载的applet。我已向Oracle提交了错误报告,并已恢复为7_21。

那是无缘无故的麻烦...

09-05 20:55