Java "Space Invaders" вызывают "исключение NULL"

Я не могу исправить свою проблему с загрузкой изображений инопланетян в мою основную программу.

Здесь код монстра:

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;
 }
}
</string,></string,>

В конце концов я получаю ошибку:

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)
</init>

Я пытаюсь использовать все, и я не знаю, что происходит. Я получил все классы в папке "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 ответа

Ошибка указывает, что где-то в Actor.setSpriteName вы пытаетесь разыменовать нулевой указатель. Единственная подозрительная строка - IMG = spriteCache.getSprite(spriteName); , что предполагает, что spriteCache является нулевым во время выполнения этой строки. Поскольку это инициализируется линией spriteCache = stage.getSpriteCache()Actor), кажется, что getSpriteCache возвращает нулевой объект. Надеюсь, что было легко следовать...


С учетом вашего stacktrace объект stage имеет значение null при вызове spriteCache.getSprite(spriteName);

Это означает, что Monster SpriteCache вами в вашем основном классе, получает нулевой экземпляр SpriteCache.

В вашем Main классе SpriteCache никогда не инстанцирован поэтому его значение равно null, что приводит к NullPointerException.

Где-то вам нужно: SpriteCache sc = new SpriteCache() и использовать этот экземпляр для создания ваших монстров. Например, в вашем Main классе вы можете захотеть изменить атрибут SpriteCache к static SpriteCache sc = new SpriteCache(); и вернуть его в метод getSpriteCache который также должен быть статичным.

licensed under cc by-sa 3.0 with attribution.