NullPointerException

Olá

Estou escrevendo um código e recentemente me ocorreu um erro que não consigo resolver.
É o NullPointerExeception. Bom, básicamente quando eu vou rodar o meu programa a janela fica completamente em branco e aparece a seguinte mensagem de erro :
Exception in thread “Thread-0” java.lang.NullPointerException
at com.dudu.world.World.render(World.java:48)
at com.dudu.main.Game.render(Game.java:107)
at com.dudu.main.Game.run(Game.java:131)
at java.base/java.lang.Thread.run(Thread.java:834)

Irei colocar abaixo o código para que alguém possa entender e me ajudar.

[CÓDIGO]

package com.dudu.world;

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

import javax.imageio.ImageIO;

public class World {

private Tile[] tiles;
public static int WIDTH,HEIGHT;

public World(String path) {
	try {
	BufferedImage map = ImageIO.read(getClass().getResource(path));
	int[] pixels = new int[map.getWidth()*map.getHeight()];
	WIDTH = map.getWidth();
	HEIGHT = map.getHeight();
	tiles = new Tile[map.getWidth()*map.getHeight()];
	map.getRGB(0, 0, map.getWidth(), map.getHeight(),pixels, 0, map.getWidth());
		for(int xx = 0; xx < map.getWidth(); xx++){
			for(int yy = 0; yy < map.getHeight(); yy++){
				int pixelAtual = pixels[xx + (yy*map.getWidth())];
				
				
				if(pixelAtual == 0xFF000000){
					tiles[xx + (yy * WIDTH)] = new FloorTile(xx*16,yy*16,Tile.TILE_FLOOR);
				}else if(pixelAtual == 0xFFFFFFFF) {
					tiles[yy + (xx * WIDTH)] = new WallTile(yy*16,xx*16,Tile.TILE_WALL);
				}else if(pixelAtual == 0xFFFFFF) {
					tiles[yy + (xx * WIDTH)] = new WallTile(yy*16,xx*16,Tile.TILE_FLOOR);
				}else {
					tiles[yy + (xx * WIDTH)] = new WallTile(yy*16,xx*16,Tile.TILE_FLOOR);
				}
			}
		}
		
	}catch (IOException e) {
		e.printStackTrace();
	}
}

public void render(Graphics g) {
	for(int xx = 0; xx < WIDTH; xx++ ) {
		for(int yy = 0; yy < HEIGHT; yy++) {
			Tile tile = tiles[xx + (yy*WIDTH)];
			tile.render(g);
		}
	}
}

}

[CÓDIGO]

package com.dudu.main;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import com.dudu.entities.Entity;
import com.dudu.entities.Player;
import com.dudu.graficos.Spritesheet;
import com.dudu.world.World;

public class Game extends Canvas implements Runnable,KeyListener{

/**
 * 
 */
private static final long serialVersionUID = 1L;
public static JFrame frame;
private Thread thread;
private boolean isRunning = true;
private final int  WIDTH = 240;
private final int HEIGHT = 160;
private final int  SCALE = 3;

private BufferedImage image;

public List<Entity> entities;
public static Spritesheet spritesheet;

public static World world;

private Player player;

public Game(){	
addKeyListener(this);
setPreferredSize(new Dimension(WIDTH*SCALE,HEIGHT*SCALE));
initFrame();


image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
entities = new ArrayList<Entity>();
spritesheet = new Spritesheet("/spritesheet.png");
world = new World("/map.png");
player = new Player(0,0,16,16,spritesheet.getSprite(36, 0, 16, 16));
entities.add(player);
}
public void initFrame() {
	frame = new JFrame("Teste #1");
	frame.add(this);
	frame.setResizable(false);
	frame.setLocationRelativeTo(null);
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setVisible(true);
	frame.pack();
}

public synchronized void start() {
	thread = new Thread(this);
	isRunning = true;
	thread.start();
}
public synchronized void stop() {
	isRunning = false;
	try {
		thread.join();
	}catch (InterruptedException e) {
		e.printStackTrace();
	}
	
}

public static void main(String[] args){
	Game game = new Game();
	game.start();
	
	
}
public void tick() {
	requestFocus();
	for(int i = 0; i < entities.size(); i++) {
		Entity e = entities.get(i);
		e.tick();
	}
}
public void render() {
	BufferStrategy bs = this.getBufferStrategy();
	if(bs== null) {
		this.createBufferStrategy(3);
		return;
	}
	Graphics g = image.getGraphics();
	g.setColor(new Color(0,0,0));
	g.fillRect(0, 0, WIDTH,HEIGHT);
	
	
	//Graphics2D g2 = (Graphics2D) g;
	world.render(g);
	for(int i = 0; i < entities.size(); i++) {
		Entity e = entities.get(i);
		e.render(g);
	g.dispose();
	g = bs.getDrawGraphics();
	g.drawImage(image, 0, 0, WIDTH*SCALE,HEIGHT*SCALE,null);
	bs.show();
	}
}

public void run() {
	long lastTime = System.nanoTime();
	double amountOfTicks = 60.0;
	double ns = 1000000000 / amountOfTicks;
	double delta = 0;
	int frames = 0;
	double timer = System.currentTimeMillis();
	while (isRunning) {
		long now = System.nanoTime();
		delta+= (now - lastTime) / ns;
		lastTime = now;
		if(delta >= 1) {
			tick();
			render();
		frames++;
		delta--;
		}
	if(System.currentTimeMillis() - timer >= 1000) {
		System.out.println("Fps: "+ frames);
		frames = 0;  
		timer+=1000;
	}
	
}
	
	stop();

}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub

}
@Override
public void keyPressed(KeyEvent e) {
	if(e.getKeyCode() == KeyEvent.VK_RIGHT||
			e.getKeyCode() == KeyEvent.VK_D) {
		player.right = true;
	}else if(e.getKeyCode() == KeyEvent.VK_LEFT||
			e.getKeyCode() == KeyEvent.VK_A){
	player.left = true;
		
	}
	
	if(e.getKeyCode() == KeyEvent.VK_UP||
			e.getKeyCode() == KeyEvent.VK_W) {
	player.up = true;
	}else if(e.getKeyCode() == KeyEvent.VK_DOWN||
			e.getKeyCode() == KeyEvent.VK_S) {
		player.down = true;
	}
	
}
@Override
public void keyReleased(KeyEvent e) {
	if(e.getKeyCode() == KeyEvent.VK_RIGHT||
			e.getKeyCode() == KeyEvent.VK_D) {
		player.right = false;
	}else if(e.getKeyCode() == KeyEvent.VK_LEFT||
			e.getKeyCode() == KeyEvent.VK_A){
	player.left = false;
		
	}
	
	if(e.getKeyCode() == KeyEvent.VK_UP||
			e.getKeyCode() == KeyEvent.VK_W) {
	player.up = false;
	}else if(e.getKeyCode() == KeyEvent.VK_DOWN||
			e.getKeyCode() == KeyEvent.VK_S) {
		player.down = false;
	}
	
}

}

[CÓDIGO]

package com.dudu.main;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import com.dudu.entities.Entity;
import com.dudu.entities.Player;
import com.dudu.graficos.Spritesheet;
import com.dudu.world.World;

public class Game extends Canvas implements Runnable,KeyListener{

/**
 * 
 */
private static final long serialVersionUID = 1L;
public static JFrame frame;
private Thread thread;
private boolean isRunning = true;
private final int  WIDTH = 240;
private final int HEIGHT = 160;
private final int  SCALE = 3;

private BufferedImage image;

public List<Entity> entities;
public static Spritesheet spritesheet;

public static World world;

private Player player;

public Game(){	
addKeyListener(this);
setPreferredSize(new Dimension(WIDTH*SCALE,HEIGHT*SCALE));
initFrame();


image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
entities = new ArrayList<Entity>();
spritesheet = new Spritesheet("/spritesheet.png");
world = new World("/map.png");
player = new Player(0,0,16,16,spritesheet.getSprite(36, 0, 16, 16));
entities.add(player);
}
public void initFrame() {
	frame = new JFrame("Teste #1");
	frame.add(this);
	frame.setResizable(false);
	frame.setLocationRelativeTo(null);
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setVisible(true);
	frame.pack();
}

public synchronized void start() {
	thread = new Thread(this);
	isRunning = true;
	thread.start();
}
public synchronized void stop() {
	isRunning = false;
	try {
		thread.join();
	}catch (InterruptedException e) {
		e.printStackTrace();
	}
	
}

public static void main(String[] args){
	Game game = new Game();
	game.start();
	
	
}
public void tick() {
	requestFocus();
	for(int i = 0; i < entities.size(); i++) {
		Entity e = entities.get(i);
		e.tick();
	}
}
public void render() {
	BufferStrategy bs = this.getBufferStrategy();
	if(bs== null) {
		this.createBufferStrategy(3);
		return;
	}
	Graphics g = image.getGraphics();
	g.setColor(new Color(0,0,0));
	g.fillRect(0, 0, WIDTH,HEIGHT);
	
	
	//Graphics2D g2 = (Graphics2D) g;
	world.render(g);
	for(int i = 0; i < entities.size(); i++) {
		Entity e = entities.get(i);
		e.render(g);
	g.dispose();
	g = bs.getDrawGraphics();
	g.drawImage(image, 0, 0, WIDTH*SCALE,HEIGHT*SCALE,null);
	bs.show();
	}
}

public void run() {
	long lastTime = System.nanoTime();
	double amountOfTicks = 60.0;
	double ns = 1000000000 / amountOfTicks;
	double delta = 0;
	int frames = 0;
	double timer = System.currentTimeMillis();
	while (isRunning) {
		long now = System.nanoTime();
		delta+= (now - lastTime) / ns;
		lastTime = now;
		if(delta >= 1) {
			tick();
			render();
		frames++;
		delta--;
		}
	if(System.currentTimeMillis() - timer >= 1000) {
		System.out.println("Fps: "+ frames);
		frames = 0;  
		timer+=1000;
	}
	
}
	
	stop();

}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub

}
@Override
public void keyPressed(KeyEvent e) {
	if(e.getKeyCode() == KeyEvent.VK_RIGHT||
			e.getKeyCode() == KeyEvent.VK_D) {
		player.right = true;
	}else if(e.getKeyCode() == KeyEvent.VK_LEFT||
			e.getKeyCode() == KeyEvent.VK_A){
	player.left = true;
		
	}
	
	if(e.getKeyCode() == KeyEvent.VK_UP||
			e.getKeyCode() == KeyEvent.VK_W) {
	player.up = true;
	}else if(e.getKeyCode() == KeyEvent.VK_DOWN||
			e.getKeyCode() == KeyEvent.VK_S) {
		player.down = true;
	}
	
}
@Override
public void keyReleased(KeyEvent e) {
	if(e.getKeyCode() == KeyEvent.VK_RIGHT||
			e.getKeyCode() == KeyEvent.VK_D) {
		player.right = false;
	}else if(e.getKeyCode() == KeyEvent.VK_LEFT||
			e.getKeyCode() == KeyEvent.VK_A){
	player.left = false;
		
	}
	
	if(e.getKeyCode() == KeyEvent.VK_UP||
			e.getKeyCode() == KeyEvent.VK_W) {
	player.up = false;
	}else if(e.getKeyCode() == KeyEvent.VK_DOWN||
			e.getKeyCode() == KeyEvent.VK_S) {
		player.down = false;
	}
	
}

}

Sou novo na programação e sei muito pouco, espero que possam ajudar.

Esse erro ta ocorrendo pq vc não inicializou nenhum objeto do array de Tile, dai quando vc tenta acessar o metodo render do tile que vc pegou do array, ele vai dar nullpointerException;

na classe World, no metodo render, tenta usar algo desse tipo:

public void render(Graphics g) {
	for(int xx = 0; xx < WIDTH; xx++ ) {
		for(int yy = 0; yy < HEIGHT; yy++) {
			Tile tile = new Tile();
			tiles[xx + (yy*WIDTH)] = tile;
			tile.render(g);
		}
	}
}

Acho que vai ajudar.

Bom, não aparece mais o erro, so q ao invés de aparecer os tiles fica tudo preto (por causa da cor que eu setei).