Collision Detection problem

Here’s the main code I have for my java space invaders clone:


import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.*;

public class Game extends JPanel implements Runnable, KeyListener{

	public static void main (String args[])
	{
		Game game = new Game();
		game.construirJanela();
		game.inicializarInimigos();
	}
	
	public void construirJanela()
	{
		JFrame janela = new JFrame ("Game");
		setBackground(Color.black);
		setFocusable(true);
		setDoubleBuffered(true);
		addKeyListener(this);
		janela.setSize(800, 600);
		janela.setResizable(false);
		janela.setLocationRelativeTo(null);
		janela.add(this);
		janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		janela.setVisible(true);		
	}

	private Thread animador;
	private final int VELOCIDADE = 5;
	private final int ESPACO = 50;
	private int velInimigo;
	private Jogador jogador;
	private Inimigo[] inimigos;
	private Tiro[] tiros;
	private boolean inGame;
	
	public Game()
	{
		jogador = new Jogador(385, 500);
		tiros = new Tiro[5];
		inimigos = new Inimigo[12];
		
		inGame = true;
	}
	
	public void inicializarInimigos()
	{	
		for (int i = 0; i < inimigos.length; i++)
		{
			inimigos[i] = new Inimigo(ESPACO * i, 20);
		}
	}
	
	public void addNotify()
	{
		super.addNotify();
		animador = new Thread(this);
		animador.start();
	}
	
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D)g;
		
		if (inGame == true)
		{
			if (jogador.getJVisivel() == true)
				{
				jogador.desenharJogador(g2d);
				}
			
			for(int t = 0; t< tiros.length; t++)
			{
				if(tiros[t] != null)
				{
					tiros[t].desenharTiro(g2d);
				}
			}
		
			for (int i = 0; i < inimigos.length; i++)
			{
				if (inimigos[i].getIVisivel() == true)
				{
				inimigos[i].desenharInimigo(g2d);
				}
			}
		}
		else
		{
			Font fonte = new Font("Tahoma", Font.BOLD, 35);
			g2d.setFont(fonte);
			g2d.setColor(Color.white);
			g2d.drawString("Game Over", 320, 300);
		}
	}

	public void keyPressed(KeyEvent e) 
	{
		if (e.getKeyCode() == KeyEvent.VK_LEFT)
		{
			jogador.moverJogadorX(-VELOCIDADE);
		}
		
		if (e.getKeyCode() == KeyEvent.VK_RIGHT)
		{
			jogador.moverJogadorX(VELOCIDADE);
		}
		
		if (e.getKeyCode() == KeyEvent.VK_SPACE)
		{
			for(int i = 0; i < tiros.length; i++)
			{
				if(tiros[i] == null)
				{
					tiros[i] = jogador.atirar();
					break;
				}
			}
		}
		
		if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
		{
			inGame = false;
		}
	}

	public void keyReleased(KeyEvent e)
	{
	
	}

	public void keyTyped(KeyEvent e)
	{
		
	}
	
	public void checarColisao()
	{
		Rectangle rJ = jogador.getLimites();

		for (int a = 0; a < inimigos.length; a++)
		{
			Rectangle rI = inimigos[a].getLimites();

			if (rJ.intersects(rI))
			{
				jogador = null;
				inimigos[a] = null;
				inGame = false;
			}
		}

		for (int b = 0; b < tiros.length; b++)
		{
			Rectangle rT= tiros[b].getLimites();
			
			for (int c = 0; c < inimigos.length; c++)
			{
				Rectangle rI = inimigos[c].getLimites();
				
				if (rT.intersects(rI))
				{
					tiros[b] = null;
					inimigos[c] = null;
				}
			}
		}
	}
	
	public void run()
	{
		while (true)
		{			
			for(int d = 0; d < tiros.length; d++)
			{
				if(tiros[d] != null)
				{
					tiros[d].moverTiro(-VELOCIDADE);
					if(tiros[d].getTiroY() < 0)
					{
						tiros[d] = null;
					}
				}
			}
			
			for (int e = 0; e < inimigos.length; e++)
			{
				if (inimigos[e] != null)
				{	
					inimigos[e].moverInimigo(velInimigo);
									
					if (inimigos[e].getInimigoX() + 20 == 800)
					{
						velInimigo = - VELOCIDADE;
					}
					
					if (inimigos[e].getInimigoX() == 0)
					{
						velInimigo = VELOCIDADE;
					}
				}
			}
			
			checarColisao();
			repaint();
			
			try
			{
				Thread.sleep(25);
			}
			catch (InterruptedException e)
			{
				
			}
		}
	}
}

Here’s the problem:

Exception in thread “Thread-3” java.lang.NullPointerException
at Game.checarColisao(Game.java:150)
at Game.run(Game.java:211)
at java.lang.Thread.run(Thread.java:619)

“checarColisao()” is a method that retrieves a Rectangle from every entity in the game and then checks if they intersect each other. When they do, the method should get rid of the entity.

There’s also a bug at the enemy’s movement that I’ll try to fix later, never mind.

I would be glad if someone could help me here. Thanks in advance.

Text formatting doesn’t show in code brackets. I pasted your code into a text editor and line 150 is:

Rectangle rI = inimigos[a].getLimites();

It’s a NullPointerException, which means that you’re referencing a variable that hasn’t been instantiated with new. The only variable you’re referencing is inimigos[a], so that’s what’s null.

I’m guessing that run() is getting called before inicializarInimigos(), although run() never appears to be called anywhere in your code. Either way, this is just a simple matter of tracing through to find out what’s getting called when. If you want this code path order, you can always put in a:

if (inimigos[a] != null)

Which you appear to already have done elsewhere in your code. Actually because you’re calling

inimigos[a] = null

every time a collision occurs, I’m sure that’s your problem. You’re calling that, which sets a value to null, and then trying to reference it again next timestep when you call checarColisao() again. Why not use an ArrayList instead of an array so that you don’t leave null “holes” laying around? Otherwise I guess just add in a null check like I mentioned above.

Thanks a lot!

The reason why I don’t use ArrayList is because I want to make the game as simple as possible, but still functional (and I don’t have time to learn how to use it properly).

The new code:


public void checarColisao()
	{
		Rectangle rJ = jogador.getLimites();

		for (int a = 0; a < inimigos.length; a++)
		{
			if (inimigos[a] != null)
			{
				Rectangle rI = inimigos[a].getLimites();
				if (rJ.intersects(rI))
				{
					jogador = null;
					inimigos[a] = null;
					inGame = false;
				}
			}
		}

		for (int b = 0; b < tiros.length; b++)
		{
			if (tiros[b] != null)
			{
				Rectangle rT = tiros[b].getLimites();
			
				for (int c = 0; c < inimigos.length; c++)
				{
					if (inimigos[c] != null)
					{
						Rectangle rI = inimigos[c].getLimites();
						
						if (rT.intersects(rI))
						{
							tiros[b] = null;
							inimigos[c] = null;
							inimigosMortos++;
						}
					}
				}
			}
		}
	}

public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D)g;
		
		if (inGame == true)
		{
			if (jogador.getJVisivel() == true)
				{
					jogador.desenharJogador(g2d);
				}
			
			for(int t = 0; t< tiros.length; t++)
			{
				if(tiros[t] != null)
				{
					tiros[t].desenharTiro(g2d);
				}
			}
		
			for (int i = 0; i < inimigos.length; i++)
			{
				if (inimigos [i] != null)
				{
					inimigos[i].desenharInimigo(g2d);
				}
			}
			g2d.setColor(Color.white);
			g2d.drawString("Inimigos restantes: " + 
							(12 - inimigosMortos), 10, 10);
		}

Now that’s just silly. You’ve already wasted all the time it would take to learn ArrayList by posting your null pointer question on JGO.

Array:


//Creation.
int[] arr = new int[50];

//Assignment.
arr[0] = 124;

//Value reference.
int i = arr[12];

//Getting length.
int l = arr.length;

//Iterating through.
for (int i = 0; i < arr.length; i++)
    System.out.println(arr[i]);

ArrayList:


//Creation.
ArrayList<Integer> arr = new ArrayList<Integer>();

//Assignment (add at the end).
arr.add(124);

//Assignment (overwrite a value at an index).
arr.set(0, 124);

//Value reference.
int i = arr.get(12);

//Getting length.
int l = arr.size();

//Iterating through.
for (int i = 0; i < arr.size(); i++)
    System.out.println(arr.get(i));

For further reference,
http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html