从ArrayList在屏幕上渲染图像会导致不稳定的NullPointerExceptions

时间:2019-07-19 01:09:46

标签: java game-development

(我知道NullPointerException是什么,在这种情况下我只是无法弄清楚是什么原因引起的。)

我正在尝试用Java做一个小型平台器,但是我似乎无法解决这个问题。运行此代码时,屏幕上的图像开始闪烁,并且在控制台中收到此错误:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at main.EntityManager.render(EntityManager.java:16)
at main.Level.render(Level.java:48)
at main.Game.paintComponent(Game.java:27)
at javax.swing.JComponent.paint(Unknown Source)

我已将问题缩小到Block类中的“ g.drawImage()”方法。如果我将g.drawImage()替换为g.drawRect(),则不会发生闪烁,也不会出错,因此Java尝试绘制图像似乎存在问题。另外,如果我将level [] []数组从[20] [20]减少到[5] [5],则不会出现闪烁,也不会发生错误。

似乎有一些导致闪烁的根本原因:

1)屏幕上显示太多纹理 2)显示纹理而不是g.drawRect()

我也不认为这是我的计算机的问题,因为我有另一个程序,该程序具有类似的处理带有纹理的渲染的方法,并且当我用与我拥有的纹理大小相同的纹理填充屏幕时在这里,它工作得非常好,所以我不确定是什么引起了这里的差异。

以下是相关的课程:

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import entities.Block;
import entities.FloorBlock;

public class Level 
{

    public Block[][] level;
    int blockDim;
    private Component component;
    private EntityManager em;

    public Level(String path, Component component)
    {
        this.component = component;
        blockDim = component.width/30;
        em = new EntityManager();

        loadLevelFromImage(ImageLoader.loadImage(path));
    }

    public void loadLevelFromImage(BufferedImage image)
    {
        //level = new Block[image.getWidth()][(component.getHeight()-image.getHeight())/blockDim + 1]; //The +1 is just to avoid any rounding errors.
        level = new Block[5][5];

        for(int x = 0; x < level.length; x++)
            for(int y = 0; y < level[x].length; y++)
                level[x][y] = new FloorBlock(x * blockDim, y * blockDim, blockDim, blockDim);

    }

    public void update()
    {
        em.clear();
        for(int x = 0; x < level.length; x++)
            for(int y = 0; y < level[x].length; y++)
                if(level[x][y] != null)
                    em.add(level[x][y]);
    }

    public void render(Graphics g)
    {
        em.render(g);
    }

}

import java.awt.image.BufferedImage;

public class Frames 
{

    public static BufferedImage floorBlock,qBlock,brickBlock,wallBlock, coin;
    public static BufferedImage unloaded;

    public static void init()
    {
        SpriteSheet sheet = new SpriteSheet("yh.png", 16, 16);
        floorBlock = sheet.crop(0, 0); 
        qBlock = sheet.crop(0, 1);
        brickBlock = sheet.crop(0, 2);
        wallBlock = sheet.crop(0, 3);
        coin = sheet.crop(1, 0);

        unloaded = ImageLoader.loadImage("unloaded.png");
    }

}

import java.awt.Graphics;
import java.util.ArrayList;

import entities.Entity;

public class EntityManager 
{

    public ArrayList<Entity> entities = new ArrayList<Entity>();

    public void render(Graphics g)
    {
        for(int i = 0; i < entities.size(); i++)
            entities.get(i).render(g);
    }

    public void add(Entity e)
    {
        entities.add(e);
    }

    public void clear()
    {
        entities.clear();
    }

}

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Game extends JPanel
{

    public Component component;

    private Input input;
    Level level;

    public Game(Component component)
    {
        setBackground(Color.CYAN);
        this.component = component;

        input = new Input(component);
        level = new Level("testLevel.png", component);
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        level.render(g);
    }

    public void update()
    {
        level.update();
    }

}

import java.awt.Graphics;

abstract public class Entity 
{
    public int x, y, width, height;

    public Entity(int x, int y, int width, int height)
    {
        this.x = x; this.y = y; this.width = width; this.height = height;
    }

    abstract public void render(Graphics g);

}

```package entities;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import main.Frames;

public class Block extends Entity
{

    public BufferedImage texture;
    public int id;

    public static final int FLOORBLOCK_ID = 1, QBLOCK_ID = 2, BRICKBLOCK_ID = 3, WALLBLOCK_ID = 4, COIN_ID = 5;

    public Block(int x, int y, int width, int height, int id) 
    {
        super(x, y, width, height);
        this.id = id;

        switch(id)
        {
        case FLOORBLOCK_ID:
            texture = Frames.floorBlock;
            break;
        case QBLOCK_ID:
            texture = Frames.qBlock;
            break;
        case BRICKBLOCK_ID:
            texture = Frames.brickBlock;
            break;
        case WALLBLOCK_ID:
            texture = Frames.wallBlock;
            break;
        case COIN_ID:
            texture = Frames.coin;
            break;
        default:
            texture = Frames.unloaded;
            break;
        }
    }

    @Override
    public void render(Graphics g)
    {
        if(texture != null)
            g.drawImage(texture, x, y, width, height, null);
        else
            g.drawImage(Frames.unloaded, x, y, width, height, null);
    }

}

public class FloorBlock extends Block
{

    public FloorBlock(int x, int y, int width, int height)
    {
        super(x, y, width, height, Block.FLOORBLOCK_ID);
    }

}

import java.awt.image.BufferedImage;

public class Frames 
{

    public static BufferedImage floorBlock,qBlock,brickBlock,wallBlock, coin;
    public static BufferedImage unloaded;

    public static void init()
    {
        SpriteSheet sheet = new SpriteSheet("yh.png", 16, 16);
        floorBlock = sheet.crop(0, 0); 
        qBlock = sheet.crop(0, 1);
        brickBlock = sheet.crop(0, 2);
        wallBlock = sheet.crop(0, 3);
        coin = sheet.crop(1, 0);

        unloaded = ImageLoader.loadImage("unloaded.png");
    }

}

0 个答案:

没有答案