0

コードでエラーが発生し続けますが、どこにも見つかりません。Spritesheet と Screen クラスを追加したときにエラーが発生しました。スタックは次のとおりです。

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++];

これが Screen クラスです。

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]);
        }
    }  
}

通常、私は助けを求めませんが、どこでもエラーを見つけることができます。ありがとうございました!

4

2 に答える 2

2

最も可能性の高い説明は、sheet.pixels(nullそれsheet自体がnullの場合、前の行で NPE を取得する) です。

于 2013-09-08T17:24:33.033 に答える
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 が発生し、image が null のままの場合、次の if ステートメントは単に SpriteSheet コンストラクターを終了し、ピクセルを含む多数の変数の初期化に失敗します。null のままにします。

問題が発生した場合に、コンストラクターが適切に初期化されていない恐ろしいオブジェクトを返すようにすることは、特別な理由がない限り、非常に悪い考えです。必要に応じてエラーを伝播するか、(適切に処理したくない場合。おそらくエラーが発生しないと考えているため)少なくとも実行時例外をスローして、他のすべてが失敗した場合に少なくとも何が悪かったのかを知る. このように完全に初期化されていないオブジェクトを残すことは、例外よりもはるかに悪いことです。なぜなら、それはまだ問題を引き起こすからです (おそらく後で例外が発生します)。さらに悪いことに、後で例外が発生しない可能性がありますが、診断がさらに難しい「クレイジー」な結果が得られるだけです。

于 2013-09-08T19:03:48.697 に答える