[JAVA2D] Thread Freezing like ice

So in my basic game, I have a thread in another class with a different name. Instead of freezing the class, the whole game loop freezes. I’m not sure why since this seems the way to multithread.

JFrame class:

package main;

import javax.swing.JFrame;

public class Game {

	public static void main(String[] args) {
		JFrame f = new JFrame();
		f.setTitle("OMG I MADE A GAME");
		f.setResizable(true);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setContentPane(new Panel());
		f.pack();
		
		f.setVisible(true);
	}

}

JPanel class:

package main;


import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import javax.swing.JPanel;
import objects.Enemy;
import objects.Player;


public class Panel extends JPanel implements Runnable, KeyListener{	
	private static final long serialVersionUID = -5122190028751177848L;

	
	// dimensions
	public static final int WIDTH = 320;
	public static final int HEIGHT = 240;
	public static final int SCALE = 2;
	
	// game thread
	private Thread thread;
	private boolean running;
	
	// image
	private BufferedImage image;
	private Graphics2D g;
	
	private Player p;
	private Enemy e;
	
	public Panel() {
		super();
		setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
		setFocusable(true);
		requestFocus();
	}
	// DRAWS PANEL TO FRAME
	public void addNotify() {
		super.addNotify();
		if(thread == null) {
			thread = new Thread(this);
			addKeyListener(this);
			thread.start();
		}
	}
	
	private void init() {
		
		image = new BufferedImage(
					WIDTH, HEIGHT,
					BufferedImage.TYPE_INT_RGB
				);
		g = (Graphics2D) image.getGraphics();
		p = new Player(100, 100);
		
		e = new Enemy(40, 50);
				
		running = true;
	}
	
	public void run() {
		
		init();
		
		
		// game loop
		while(running) {
			
			update();
			draw();
			drawToScreen();	 
			System.out.println("ELAPSED :" + System.nanoTime()/ 1000000 + " Seconds");
			
			try {
				Thread.sleep(10);
			}
			catch(Exception e) {
				e.printStackTrace();
			}
		
		}
		
	}
	
	private void update() {
		p.update();
		e.update();
	}
	private void draw(){
		//// Clear Screen /////
		 g.setColor(Color.BLACK);
		 g.fillRect(0, 0, WIDTH, HEIGHT);
		
		
		// NAME (remember it loops) 
		String name = "2014 Jay H.";
		g.setFont(new Font("Name", 0, 12)); 
		g.setColor(Color.WHITE);
		g.drawString(name, 0, 10);
		g.setColor(Color.BLUE);
		
		
		//DRAW PLAYER
		p.draw(g);
		
		//DRAW ENEMY
		e.draw(g);
		
		
		}
	// SCREEN IMAGE (dont have to use. Just use this^)
	private void drawToScreen() {  
		Graphics g2 = getGraphics();
		g2.drawImage(image, 0, 0,
				WIDTH * SCALE, HEIGHT * SCALE,null);
		g2.dispose(); 
	}
	
	public void keyTyped(KeyEvent key) {}
	
	// PUBLIC KEYRELEASES
	public void keyPressed(KeyEvent key) {
		int KeyCode = key.getKeyCode();
		
		//EXIT SYSTEM
		if(KeyCode == KeyEvent.VK_Q) {System.exit(0);}
		
		
		//UP
		if(KeyCode == KeyEvent.VK_W){p.setDY(-2);}	
		if(KeyCode == KeyEvent.VK_A){p.setDX(-2);}
		if(KeyCode == KeyEvent.VK_S){p.setDY(2);}
		if(KeyCode == KeyEvent.VK_D){p.setDX(2);}

	}
	
	
	// PUBLIC KEYRELEASES
	public void keyReleased(KeyEvent key) {
		int KeyCode = key.getKeyCode();
		
		//UP
		if(KeyCode == KeyEvent.VK_W) {p.setDY(0);}
		if(KeyCode == KeyEvent.VK_A){p.setDX(0);}
		if(KeyCode == KeyEvent.VK_S){p.setDY(0);}
		if(KeyCode == KeyEvent.VK_D){p.setDX(0);}

		

	}

}

Player class:

package objects;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;

//FOR NOW THE PLAYER IS A RECTANGLE
public class Player {
	
	// PLAYER CORDINATES AND VELOCITY
	int x,y,dx,dy;
	Image img;
	

	public Player(int x, int y) {
		
		//NEEDED TO USE THE X AND Y
		this.x =x;
		this.y = y;
	} 
	
	public void update() {
		x += dx;
		y += dy;
		
	}
	
	// DRAW TO PANEL CLASS
	public void draw(Graphics2D g) {
		//BODY
		g.setColor(Color.PINK);
		g.fillRect(x, y, 20, 20);
		//EYES
		g.setColor(Color.BLACK);
		g.fillRect(x+3, y+2, 5, 10);
		g.fillRect(x+ 12, y+2, 5, 10);
		//EYERIS
		g.setColor(Color.WHITE);
		g.fillRect(x+3, y+2, 2, 10);
		g.fillRect(x+15, y+2, 2, 10);
		//NOSE
		g.setColor(Color.MAGENTA);
		g.fillRect(x+5, y+13, 10, 5);
		//NOSTRILLS
		g.setColor(Color.red);
		g.fillRect(x+6, y+15, 2, 2);
		g.fillRect(x+12, y+15, 2, 2);
		
	}
	
	//GET METHODS FOR CORDINATES AND VELOCITY  (Unused for now... i think)
	public int getX() {return x;}
	public int getY() {return y;}
	public int getDX() {return dx;}
	public int getDY() {return dy;}
	
	//SET METHODS TO CHANGE
	public void setX(int x) {this.x = x;}
	public void setY(int y) {this.y = y;}
	public void setDX(int dx) {this.dx = dx;}
	public void setDY(int dy) {this.dy = dy;}


}

Enemy class:

package objects;

import java.awt.Graphics;

public class Enemy implements Runnable {
	private int x, y, dx, dy;
	
	Thread anim;
	boolean e;
	
	public Enemy(int x, int y) {
		
		this.x = x;
		this.y = y;
		
		dx = 0;
		dy = 1;
		
		
	}
	
	public void update() {
		x += dx;
		y += dy;
		
		System.out.println("E Y" + y);
		
		if (y == 204) {
			try {
				anim.wait(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			y = 194;
			dy = -1;
		}
		
		if (y == 0) {
			try {
				anim.wait(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			y = 10;
			dy = 2;
		}
		
	}
	
	public void draw(Graphics g) {
		g.drawRect(x, y, 20, 30);
	}
	
	public int getX() {return x;}
	public int getY() {return y;}
	public int getDX() {return dx;}
	public int getDY() {return dy;}
	
	public void setX(int x) {this.x = x;}
	public void setY(int y) {this.y = y;}
	public void setDX(int dx) {this.dx = dx;}
	public void setDY(int dy) {this.dy = dy;}

	public void start() {
		if (anim == null) {
			anim = new Thread(this);
			anim.start();
		}
	}
	
	@Override
	public void run() {
		while(e) {
			update();
			try {
				anim.wait(10);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			
		}
	}
	

}

The error:

Exception in thread "Thread-2" java.lang.NullPointerException
	at objects.Enemy.update(Enemy.java:30)
	at main.Panel.update(Panel.java:91)
	at main.Panel.run(Panel.java:73)
	at java.lang.Thread.run(Thread.java:745)

If you compile it It looks nice, besides the exception. I changed some things in the enemy class, so that’s why it crashes instead of freezing the game and changing direction.

Have you not learned anything from the other thread?!

at objects.Enemy.update(Enemy.java:30)


anim.wait(1000);

[icode]anim[/icode] is null. You never initialized it.

I’m going to bed.

It’s initialized in the start method

You’re lucky, I decided not to go to bed, need to reset the cycle anyway.

You never call the start method, at least not in the posted classes. I ctrl-f’d the page.

And why are you using a separate thread to update the Enemies? Just call update() on each of them in your main game loop, just like draw(). That’s how EVERYONE does it, and threading is only begging for problems.

In my Panel class I did call update. Wouldn’t using the Hamilton’s thread still freeze it

Just.,. Stop… Using… Threads…

You don’t need them, thread.sleep will ALWAYS lock the current thread the block of code is running on.

Computers can increase an integer value from 0 to 1 billion in < 1 second, that is FAST. For most games you don’t need to touch multi threading.

Java2D doesn’t need multiple threads to make a game. This should clear it up a little.

Game Threading

I’m curious to what tutorials you have been reading. The problem is [icode]addNotify()[/icode]. Check out the code example below for an example on how to implement it.

The Example