[RESOLVIDO]Problema com thread

Estava brincando de fazer um “joguinho” aqui e tive um problema que nao consigo entender.

Comecei com isso:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class GameNave extends JFrame implements Runnable, KeyListener{
	
	public static void main (String args[])
	{
		GameNave game = new GameNave();
		game.construirJanela();
	}
	
	public void construirJanela()
	{
		Container container = getContentPane();
		container.setBackground(Color.black);
		setTitle("Game: Nave");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(800, 600);
		setLocationRelativeTo(null);
		setVisible(true);
		setResizable(false);
		addKeyListener(this);
		setFocusable(true);
		
		x = 400;
		y = 500;
	}
	
	private Thread animador;
	private int x, y, x2, y2;
	private Image nave;
	
	public void paint (Graphics g)
	{
		super.paint(g);
		nave = new ImageIcon("nave.png").getImage();
		Graphics2D g2d = (Graphics2D)g;
		g2d.drawImage(nave, x, y, this);
	}

	public void addNotify()
	{
		super.addNotify();
		animador = new Thread(this);
		animador.start();		
	}
	
	public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            x2 = -5;
        }

        if (key == KeyEvent.VK_RIGHT) {
            x2 = 5;
        }

        if (key == KeyEvent.VK_UP) {
            y2 = -5;
        }

        if (key == KeyEvent.VK_DOWN) {
            y2 = 5;
        }
    }

    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            x2 = 0;
        }

        if (key == KeyEvent.VK_RIGHT) {
            x2 = 0;
        }

        if (key == KeyEvent.VK_UP) {
            y2 = 0;
        }

        if (key == KeyEvent.VK_DOWN) {
            y2 = 0;
        }
    }
    
    public void keyTyped (KeyEvent e)
    {
    	
    }
    
    public void movimento()
    {
    	x += x2;
    	y += y2;
    }
	public void run()
	{
		while (true)
			{
			movimento();
			repaint();
			
			try
			{
				Thread.sleep(25);
			}
			catch (InterruptedException e)
			{
			}
			
			}
	}
}

Até aqui tudo bem. Depois disso quis adicionar a possibilidade de atirar com a nave, entao fiz isso:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

public class GameNave2 extends JFrame implements Runnable, KeyListener{
	
	public static void main (String args[])
	{
		GameNave2 game = new GameNave2();
		game.construirJanela();
	}
	
	public void construirJanela()
	{
		Container container = getContentPane();
		container.setBackground(Color.black);
		setTitle("Game: Nave");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(800, 600);
		setLocationRelativeTo(null);
		setVisible(true);
		setResizable(false);
		addKeyListener(this);
		setFocusable(true);
		
		x = 400;
		y = 500;
	}
	
	private Thread animador;
	private int x, y, x2, y2;
	private Image nave;
	private ArrayList tiros;
	
	public void paint (Graphics g)
	{
		super.paint(g);
		
		nave = new ImageIcon("nave.png").getImage();
		tiros = new ArrayList();
		
		Graphics2D g2d = (Graphics2D)g;
		g2d.drawImage(nave, x, y, this);
		
		ArrayList ms = tiros;
		for (int i = 0; i < ms.size(); i++)
		{
			Tiro t = (Tiro) ms.get(i);
			g2d.drawImage(t.tiro, t.x, t.y, this);
		}
	}

	public void atirar()
	{
		tiros.add(new Tiro(x + 32, y + 16));
	}
	
	public void addNotify()
	{
		super.addNotify();
		animador = new Thread(this);
		animador.start();		
	}
	
	public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_SPACE){
        	atirar();
        }
        
        if (key == KeyEvent.VK_LEFT) {
            x2 = -5;
        }

        if (key == KeyEvent.VK_RIGHT) {
            x2 = 5;
        }

        if (key == KeyEvent.VK_UP) {
            y2 = -5;
        }

        if (key == KeyEvent.VK_DOWN) {
            y2 = 5;
        }
    }

    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            x2 = 0;
        }

        if (key == KeyEvent.VK_RIGHT) {
            x2 = 0;
        }

        if (key == KeyEvent.VK_UP) {
            y2 = 0;
        }

        if (key == KeyEvent.VK_DOWN) {
            y2 = 0;
        }
    }
    
    public void keyTyped (KeyEvent e)
    {
    	
    }
    
    public void movimento()
    {
    	x += x2;
    	y += y2;
    }
	public void run()
	{
		while (true)
			{
			ArrayList ts = tiros;
			for (int i = 0; i < ts.size(); i++)
			{
				Tiro m = (Tiro) ts.get(i);
				if (m.visivel = true)
				{
					m.movimentoTiro();
				}
				else
				{
					ts.remove(i);
				}
			}
			
			movimento();
			repaint();
			
			try
			{
				Thread.sleep(25);
			}
			catch (InterruptedException e)
			{
			}
			
			}
	}
}
import java.awt.Image;
import javax.swing.ImageIcon;

public class Tiro {
	
	int x, y;
	Image tiro;
	boolean visivel;
	
	private final int ALTURA_JANELA = 600;
	private final int VELOCIDADE_TIRO = 2;
	
	public Tiro(int x, int y)
	{
		tiro = new ImageIcon("tiro.png").getImage();
		visivel = true;
		this.x = x;
		this.y = y;
	}
	
	public void movimentoTiro()
	{
		x += VELOCIDADE_TIRO;
		if (x < ALTURA_JANELA)
		{
			visivel = false;
		}
	}
}

Como resultado eu tenho uma janela com a nave desenhada mas sem a capacidade de se movimentar nem nada.

O Eclipse me manda este erro:
“Exception in thread “Thread-3” java.lang.NullPointerException
at tutorial.pack.GameNave2.run(GameNave2.java:128)
at java.lang.Thread.run(Unknown Source)”

Não sei como resolver e vim pedir ajuda de alguem que entenda melhor de thread, etc.
Obrigado desde já.

Normalmente os jogos tem uma thread só, chamada loop de animação. Apesar de ter vários objetos na tela, todos são atualizados durante a fase de update() do jogo, ou seja, vc percorre uma lista desses objetos chamando seus respectivos métodos de atualização de lógica.

Sempre que postar um erro, também faça o favor de indicar em que linha do seu código o seu erro está. Nullpointer exception geralmente quer dizer que você tentou chamar um método de um objeto, mas a sua variável continha valor nulo.

Problema resolvido. ;D

Qual era o problema?
Como resolveu?

Assim ajuda os outros que tiverem a msma dúvida…

E se foi resolvido, clique editar no primeiro post e acrescente depois do título [RESOLVIDO]

Quem quiser saber a solução do(s) problema(s), pode conferir o que foi discutido aqui:

http://www.java-forums.org/threads-synchronization/25652-problem-thread.html

[quote=dotabyss]Quem quiser saber a solução do(s) problema(s), pode conferir o que foi discutido aqui:

http://www.java-forums.org/threads-synchronization/25652-problem-thread.html[/quote]
Quanto ao que o cara que te ajudou disse nesse tópico eu discordo dos dois primeiros itens. Isso porque o mais correto para um jogo fazer a pintura usando direct rendering (porém note que se você não for usar direct rendering, aí sim siga o que ele disse - sobreescreva paintComponent de um JComponent e depois adicione esse componente ao JFrame).

Porém os dois últimos pontos estão certos: não leia arquivos nem execute lógica dentro do método de pintura. Cada método exerce uma função específica. Leia a imagem em um método de inicialização e faça atualizações da lógica em um método específico para isso.