Java“Space Invaders”导致“NULL异常”

时间:2014-01-07 21:05:55

标签: java nullpointerexception

我无法解决将外星人的图像加载到主程序中的问题。

以下是 Monster 的代码:

 package classes;

public class Monster extends Actor {

    protected int enemySpeed;

    public Monster(Stage stage) 
    {
        super(stage);
        setSpriteName("0.png");
    }

    public void act() 
    {
        x+=enemySpeed;
        if (x < 0 || x > Stage.windowWidth)
            enemySpeed = -enemySpeed;
    }
    public int getVx()
    { 
        return enemySpeed; 
    }
    public void setVx(int i) 
    {
        enemySpeed = i; 
    }
}

这是Actor的代码(它是创建图像的主要类):

    package classes;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

public class Actor {
    protected int x,y;
    protected int width, height;
    protected String spriteName;
    protected Stage stage;
    protected SpriteCache spriteCache;
    private BufferedImage IMG;

    public Actor(Stage stage)
    {
        this.stage = stage;
        spriteCache = stage.getSpriteCache();
    }

    public void paint(Graphics2D g)
    {
        g.drawImage( spriteCache.getSprite(spriteName), x,y, stage );
    }

    public int getX() 
    { 
        return x;
    }
    public void setX(int i) 
    { 
        x = i; 
    }
    public int getY() 
    {
        return y; 
    }
    public void setY(int i)
    { 
        y = i; 
    }
    public String getSpriteName() 
    {
        return spriteName; 
    }
    public void setSpriteName(String string) 
    {
        spriteName = string;
        IMG = spriteCache.getSprite(spriteName);
        /*
        BufferedImage image = spriteCache.getSprite(spriteName);
        height = image.getHeight();
        width = image.getWidth();
        */
    }
    public int getHeight() 
    { 
        return height; 
    }
    public int getWidth() 
    {
        return width;
    }
    public void setHeight(int i)
    {
        height = i; 
    }
    public void setWidth(int i)
    {
        width = i; 
    }
    public void act() 
    {

    }
}

我加载图像的SpriteCache的最后但并非最不重要的代码。

package classes;

import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.HashMap;

import javax.imageio.ImageIO;

public class SpriteCache 
{
    public HashMap<String, BufferedImage> sprites;

    public SpriteCache() 
    {
        sprites = new HashMap<String, BufferedImage>();
    }


    private BufferedImage loadImage(String sciezka) 
    {
        URL url=null;
        try 
        {
            url = getClass().getClassLoader().getResource("0.png");
            return ImageIO.read(url);
        }
        catch (Exception e) 
        {
            System.out.println("Przy otwieraniu " + sciezka +" jako " + url);
            System.out.println("Wystapil blad : "+e.getClass().getName()+" "+e.getMessage());
            System.exit(0);
            return null;
        }
    }
    public BufferedImage getSprite(String sciezka) {
        BufferedImage img = (BufferedImage)sprites.get("0.png");
        if (img == null)
        {
            img = loadImage("0.png");
            sprites.put(sciezka,img);
        }
        return img;
    }
}

毕竟我得到错误:

java.lang.NullPointerException
    at classes.Actor.setSpriteName(Actor.java:48)
    at classes.Monster.<init>(Monster.java:10)
    at Main.initWorld(Main.java:116)
    at Main.game(Main.java:99)
    at Main$1.run(Main.java:50)

我尝试使用一切,但我不知道发生了什么。 我得到了'class'文件夹中的所有课程以及'img'文件夹中的所有图片。

这是MAIN课程:

import java.awt.Canvas;


public class Main extends Canvas implements Stage {

    private JFrame frame;
    //wysokosc szerokosc
    private int windowWidth = 800;
    private int windowHeight = 600;

    //Buffor stretegi - odświeżanie ekranu ( ucieczka od migania ) 
    public BufferStrategy strategy;

    private SpriteCache spriteCache;
    private ArrayList actors;
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Main window = new Main();
                    window.frame.setVisible(true);
                    window.game();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Main() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() 
    {       
        //główne okno
        frame = new JFrame("Wojna z Alienami by Dawid Raźny!");
        frame.setBounds(100, 100, windowWidth, windowHeight);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() 
        {
            public void windowClosing(WindowEvent e){
                System.exit(0);
            }
        });

        //panel w którym będą rysowane obiekty i grafiki
        JPanel panel = (JPanel)frame.getContentPane();
        setBounds(0,0,windowWidth,windowHeight);
        panel.setPreferredSize(new Dimension(windowWidth,windowHeight));
        panel.setLayout(null);
        panel.add(this);


        //potrzebne elementy BufforStrategy
        createBufferStrategy(1);
        strategy = getBufferStrategy();
        requestFocus();

    }//konstruktor 


    public void game() {
        initWorld();
        while (isVisible()) 
        {
            updateWorld();
            paintWorld();
            try 
            {
                Thread.sleep(Stage.Speed);
            } 
            catch (InterruptedException e) {}
        }
    }

    public void initWorld() {
        actors = new ArrayList();
        for (int i = 0; i < 10; i++)
        {
            Monster m = new Monster(this);
            m.setX( (int)(Math.random()*Stage.windowWidth) );
            m.setY( i*20 );
            m.setVx( (int)(Math.random()*3)+1 );
            actors.add(m);
        }
    }
    public void paintWorld() {
        Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
        g.setColor(Color.black);
        g.fillRect(0,0,getWidth(),getHeight());
        for (int i = 0; i < actors.size(); i++) 
        {
            Actor m = (Actor)actors.get(i);
            m.paint(g);
        }
        g.setColor(Color.white);
        strategy.show();
    }

    public void updateWorld() {
        for (int i = 0; i < actors.size(); i++) 
        {
            Actor m = (Actor)actors.get(i);
            m.act();
        }
    }

    @Override
    public SpriteCache getSpriteCache() {
        // TODO Auto-generated method stub
        return null;
    }

}

舞台课程:

    package classes;

import java.awt.image.ImageObserver;

public interface Stage extends ImageObserver 
{
    public static final int windowWidth = 800;
    public static final int windowHeight = 600;
    public static final int Speed = 10;
    public SpriteCache getSpriteCache();
}

2 个答案:

答案 0 :(得分:2)

给定您的stacktrace,调用spriteCache.getSprite(spriteName);

时,stage对象为null

这意味着您在主类中创建的Monster正在接收空SpriteCache实例。

Main班级中,SpriteCache永远不会被实例化,因此其值null会导致NullPointerException

您需要的某个地方:SpriteCache sc = new SpriteCache()并使用此实例创建您的怪物。例如,在您的Main课程中,您可能希望将属性SpriteCache更改为static SpriteCache sc = new SpriteCache();,并将其返回方法getSpriteCache,这也需要是静态的。

答案 1 :(得分:2)

错误指出Actor.setSpriteName中的某个地方,您试图取消引用空指针。唯一的可疑行是IMG = spriteCache.getSprite(spriteName);,这表明在此行执行时spriteCache为空。由于这是使用行spriteCache = stage.getSpriteCache()(在Actor中)初始化的,因此getSpriteCache似乎返回了一个空对象。我希望这很容易理解......