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.