2013-09-08 5 views
0

Я продолжаю получать ошибку в своем коде, но я не могу найти ее где угодно, она началась, когда я добавил Spritesheet и мой класс Screen, вот стек:Я продолжаю получать (Suspended (NullPointerException)), когда я пытаюсь запустить свою игру, но я не могу найти ошибку где-нибудь

Thread [Thread-2] (Suspended (exception NullPointerException)) 
Screen.render(int[], int, int) line: 51 
Game.render() line: 128 
Game.run() line: 101  
Thread.run() line: not available  

`

И линия 51 эта линия:

int colour = tileIndex * 4 + sheet.pixels[sheetPixel++]; 

И это класс экрана:

package ca.vanzeben.game.gfx; 

public class Screen { 

    public static final int MAP_WIDTH = 64; 
    public static final int MAP_WIDTH_MASK = MAP_WIDTH - 1 ; 

    public int[] tiles = new int[MAP_WIDTH*MAP_WIDTH]; 
    public int[] colours = new int[MAP_WIDTH*MAP_WIDTH*4]; 

    public int xOffset = 0; 
    public int yOffset = 0; 

    public int width; 
    public int height; 

    public SpriteSheet sheet; 

    public Screen(int width, int height, SpriteSheet sheet) { 
     this.width = width; 
     this.height = height; 
     this.sheet = sheet; 

     for (int i = 0; i<MAP_WIDTH*MAP_WIDTH; i++) { 
      colours [i*4+0] = 0xff00ff; 
      colours [i*4+1] = 0x00ffff; 
      colours [i*4+2] = 0xffff00; 
      colours [i*4+3] = 0xffffff; 
     } 
    } 

    public void render(int[] pixels, int offset, int row) { 
     for (int yTile = yOffset >>3;yTile <= (yOffset+height)>>3;yTile++) { 
      int yMin = yTile * 8 - yOffset; 
      int yMax = yMin + 8; 
      if (yMin < 0) yMin = 0; 
      if (yMax > height) yMax = height; 

      for (int xTile = xOffset >>3;xTile <= (xOffset+width)>>3;xTile++) { 
       int xMin = xTile * 8 - xOffset; 
       int xMax = xMin + 8; 
       if (xMin < 0) xMin = 0; 
       if (xMax > width) xMax = width; 

       int tileIndex = (xTile & (MAP_WIDTH_MASK))+ (yTile &(MAP_WIDTH_MASK))*MAP_WIDTH; 

       for (int y = yMin; y <yMax; y++) { 
        int sheetPixel = ((y + yOffset)& 7)* sheet.width + ((xMin + xOffset) & 7); 
        int tilePixel = offset + xMin + y*row; 
        for (int x = xMin; x<xMax; x++) { 
         int colour = tileIndex * 4 + sheet.pixels[sheetPixel++]; 
         pixels [tilePixel++] = colours [colour]; 
        } 
       } 
      } 
     } 
    } 
} 

Вот класс игры:

package ca.vanzeben.game; 

import java.awt.BorderLayout; 
import java.awt.Canvas; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.image.BufferStrategy; 
import java.awt.image.BufferedImage; 
import java.awt.image.DataBufferInt; 

import javax.swing.JFrame; 


public class Game extends Canvas implements Runnable { 


    private static final long serialVersionUID = 1L; 

    public static final int WIDTH = 160; 
    public static final int HEIGHT = WIDTH /12*9; 
    public static final int SCALE =3; 
    public static final String NAME = "Wake Me Up"; 

    private JFrame frame; 

    public boolean running = false; 
    public int tickCount = 0; 

    private BufferedImage image = new BufferedImage  (WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB); 
    private int[] pixels =((DataBufferInt)image.getRaster().getDataBuffer()).getData(); 

    private Screen screen; 

    public Game() { 
     setMinimumSize(new Dimension (WIDTH*SCALE,HEIGHT*SCALE)); 
     setMaximumSize(new Dimension (WIDTH*SCALE,HEIGHT*SCALE)); 
     setPreferredSize(new Dimension (WIDTH*SCALE,HEIGHT*SCALE)); 

     frame = new JFrame(NAME); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLayout(new BorderLayout()); 

     frame.add(this,BorderLayout.CENTER); 
     frame.pack(); 

     frame.setResizable(false); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public void init() { 
     screen = new Screen (WIDTH,HEIGHT, new SpriteSheet("/sprite_sheet.xcf")); 
    } 


    public synchronized void start() { 
     running = true; 
     new Thread(this).start(); 

    } 

    public synchronized void stop() { 

    } 

    public void run() { 
     long lastTime = System.nanoTime(); 
     double nsPerTick = 1000000000D/60D; 

     int frames = 0; 
     int ticks = 0; 

     long lastTimer = System.currentTimeMillis(); 
     double delta = 0; 

     init(); 

     while (running) { 
      long now = System.nanoTime(); 
      delta += (now-lastTime)/nsPerTick; 
      lastTime = now; 
      boolean shouldRender = true; 

      while (delta >=1) { 
       ticks++; 
       tick(); 
       delta -= 1; 
       shouldRender = true; 
      } 
      try { 
       Thread.sleep(2); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      if (shouldRender) { 
       frames++; 
       render(); 
      } 

      if (System.currentTimeMillis()-lastTimer>=1000) { 
       lastTimer += 1000; 
       System.out.println(ticks+ "," +frames); 
       frames = 0; 
       ticks = 0; 
      } 
     } 
    } 

    public void tick() { 
     tickCount++;  

     for (int i=0; i < pixels.length;i++) { 
      pixels[i] = i+tickCount; 
     } 
    } 

    public void render() { 
     BufferStrategy bs = getBufferStrategy(); 
     if (bs == null) { 
      createBufferStrategy(3); 
      return; 
     } 

     screen.render(pixels, 0, WIDTH); 

     Graphics g = bs.getDrawGraphics(); 

     g.setColor(Color.BLACK); 
     g.fillRect(0, 0, getWidth(), getHeight()); 

     g.drawImage(image, 0, 0, getWidth(), getHeight(), null); 

     g.dispose(); 
     bs.show(); 
    } 

    public static void main(String[]args) { 
     new Game().start(); 
    } 

} 

А вот класс SpriteSheet:

package ca.vanzeben.game.gfx; 

import java.awt.image.BufferedImage; 
import java.io.IOException; 
import javax.imageio.ImageIO; 

public class SpriteSheet { 

    public String path; 
    public int width; 
    public int height; 

    public int [] pixels; 

    public SpriteSheet(String path) { 
     BufferedImage image = null; 
     try { 

      image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     if (image == null) { 
      return; 
     } 

     this.path = path; 
     this.width = image.getWidth(); 
     this.height = image.getHeight(); 

     pixels = image.getRGB(0, 0, width, height, null, 0, width); 

     for(int i = 0; i< pixels.length;i++) { 
      pixels[i] = (pixels[i] & 0xff)/64; 
     } 

     for(int i = 0; i<8;i++) { 
      System.out.println(pixels[i]); 
     } 
    } 
} 

Обычно я не прошу о помощи, но я просто не могу найти ошибку в любом месте. Спасибо!

+1

Вы получите гораздо больше внимания на свой вопрос, если пометить его языком, который вы используете, и любыми соответствующими библиотеками. –

+0

Используйте ваш отладчик, чтобы разбить NPE и узнать, что у данной строки имеет значение «null». – millimoose

+0

Без (предпочтительно короткой) автономной программы (см. Http://sscce.org/) трудно сказать, что именно неправильно (как говорит NPE) лист является «неправильным», когда его передают конструктору, в частности, лист. пиксели равны нулю. Почему его нуль потребует остальную часть программы –

ответ

2

Наиболее вероятным объяснением является то, что sheet.pixels является null (если sheet сам был null, вы получите NPE на ранней линии).

+0

Как это исправить? (довольно новичок в программировании, знаю основы, но все еще новы) – user2757088

+0

@ user2757088, что зависит от того, как работает SpriteSheet, но в идеале его конструктор должен устанавливать пиксели на что-то (потому что в настоящее время он остается как ничто иное). В качестве альтернативы он может быть активно установлен в значение null. В этом случае вам нужно будет узнать, откуда приходит нуль. Пробег в отладчике поможет выяснить, откуда приходит нуль от –

+0

Да, я не могу найти что-нибудь ... Я не знаю, где его найти или как ... – user2757088

0

Единственное объяснение, которое я могу найти для sheet.pixels равным null в указанной строке, состоит в том, что ImageIO.read(...) в конструкторе SpriteSheet исключил исключение IOException и поэтому оставил изображение как null.

public SpriteSheet(String path) { 
    BufferedImage image = null; 
    try { 
     image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path)); //<-- has an IOException problem 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    if (image == null) { //<--image remains null 
     return; //<--- rest of constructor is skipped 
    } 
    this.path = path; 
    this.width = image.getWidth(); 
    this.height = image.getHeight(); 

    pixels = image.getRGB(0, 0, width, height, null, 0, width); 
    .... rest of constructor 

Вот если image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path)); обнаружил IOException и изображение остается нулевым, то следующим, если оператор просто завершает конструктор SpriteSheet неспособности инициализировать ряд переменных, включая пиксели; оставляя его нулевым.

Если конструктор возвращает ужасный, неправильно инициализированный объект, если он сталкивается с проблемой, это очень плохая идея, если у вас нет конкретных причин для этого; распространять ошибку, если это необходимо, или (если вы не хотите иметь дело с ней должным образом, возможно, потому, что вы считаете, что она никогда не появится), по крайней мере, выпустить исключение во время выполнения, поэтому, если все остальное не сработает, вы, по крайней мере, знаете, что пошло не так. Оставляя не полностью инициализированный объект, как это, намного хуже, чем исключение, потому что оно все равно вызовет проблемы (и, вероятно, исключение позже), но исключение будет далеким от фактической причины проблемы, как вы нашли; или, что еще хуже, это может не вызвать исключения позже, а просто дать «сумасшедший» результат, который еще сложнее диагностировать.

+1

так (если я это правильно понимаю) imge = ImageIO.read столкнулась с проблемой, называемой ioexception, и, следовательно, она прекратила следующий, если statemen, оставив пиксели нуль? это имеет смысл ... Желаю, чтобы я нашел решение для этого – user2757088

+0

@ user2757088 Проблема в том, что наиболее вероятная причина этого заключается в том, что (а) файл не существует или (б) он не «понравился» файлу , Ни один из которых я не могу диагностировать с моей стороны. Посмотрите, что сказал e.printStackTrace, и посмотрите, есть ли у него какие-либо подсказки. –

+0

P.s. независимо от того, что напечатанное e.printStackTrace было «настоящим» исключением, тот, который вы видели, является лишь побочным ущербом. Добавьте все, что e.printStackTrace напечатано на ваш вопрос, а также –