im following a tutorial and im coming across this is the error, i cannot seem to work out what the problem is. All im trying to do is load a Sprite image. Here is the code:
Here is the error:
Exception in thread "Thread-0" java.lang.NullPointerException
at com.mainpkg.game.Handler.gg(Handler.java:27)
at com.mainpkg.game.Game.render(Game.java:107)
at com.mainpkg.game.Game.run(Game.java:83)
at java.base/java.lang.Thread.run(Thread.java:844)
Main Game Class:
public class Game extends Canvas implements Runnable {
public static final int WIDTH = 800, HEIGHT = WIDTH / 12 * 9;
private Thread thread;
private boolean running = false;
private Handler handler;
private BufferedImage grassTile;
public Game() {
new Window(WIDTH, HEIGHT, "MOON EXPOLATION", this);
handler = new Handler(getWidth(), getHeight());
testImage = loadImage("Resources/GrassTile.png");
}
private BufferedImage loadImage(String path) {
try {
BufferedImage loadedImage = ImageIO.read(new FileInputStream(path));
BufferedImage formattedImage = new BufferedImage(loadedImage.getWidth(), loadedImage.getHeight(),
BufferedImage.TYPE_INT_RGB);
formattedImage.getGraphics().drawImage(loadedImage, 0, 0, null);
return formattedImage;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public synchronized void start() {
thread = new Thread(this);
thread.start();
running = true;
}
public synchronized void stop() {
try {
thread.join();
running = false;
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
int FRAMES = 0;
int TICKS = 0;
long lastTime = System.nanoTime();
double unprocessed = 0;
double nsPerSecs = 1000000000 / 60.0;
long Timer = System.currentTimeMillis();
while (running) {
long now = System.nanoTime();
unprocessed += (now - lastTime) / nsPerSecs;
lastTime = now;
if (unprocessed >= 1) {
TICKS++;
ticks();
unprocessed -= 1;
}
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
FRAMES++;
render();
if (System.currentTimeMillis() - Timer > 1000) {
System.out.println("Ticks: " + TICKS + " FPS: " + FRAMES);
TICKS = 0;
FRAMES = 0;
Timer += 1000;
}
}
stop();
}
private void ticks() {
}
void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
super.paint(getGraphics());
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
handler.renderImage(testImage, 0, 0);
handler.render(g);
// g.setColor(Color.BLACK);
// g.fillRect(0,0,WIDTH,HEIGHT);
g.dispose();
bs.show();
}
public static void main(String[] args) {
new Game();
}
Handler Class:
public class Handler {
private BufferedImage view;
private int pixels[];
public Handler(int width, int height) {
view = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt) view.getRaster().getDataBuffer()).getData();
}
public void render(Graphics g) {
g.drawImage(view, 0, 0, view.getWidth(), view.getHeight(), null);
}
public void renderImage(BufferedImage image, int xPosition,int yPosition) {
int[] imagepixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
for(int y = 0; y < image.getHeight(); y++) {
for(int x = 0; x < image.getWidth(); x++) {
pixels[(x + xPosition) + (y + yPosition ) * view.getWidth()] = imagepixels[x + y * image.getWidth()];
}
}
}
The problem is here:
BufferedImage loadedImage = ImageIO.read(Game.class.getResource(path));
getResource(path) is returning null and that is causing the exception.
Try changing the image path to "Assets/GrassTile.png"
One tip:
You should avoid using absolute paths to locate your resources. This is a really bad idea because if you change the location of your project it will stop working, try using relative paths.
Related
Here is the code that I tried to execute, but failed:
public class Game extends Canvas implements Runnable,KeyListener {
private static final long serialVersionUID = 1L;
private static Thread thread ;
private int width = 240;
private int height = 120;
private int scale = 3;
private boolean isRunning = true;
private BufferedImage image;
public static Spritesheet spritesheet;
private Player player;
Game(){
Dimension dimension = new Dimension(width*scale,height*scale);
this.setPreferredSize(dimension);
image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
}
void initframe() {
JFrame f = new JFrame("Game");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
f.setLocationRelativeTo(null);
f.setResizable(false);
}
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();
}
void tick() {
}
void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = image.getGraphics();
g.setColor(Color.GREEN);
g.fillRect(0, 0, width, height);
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 = (10^9)/amountOfTicks ;
int frames = 0;
double delta;
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(" A taxa de fps e: "+frames);
frames = 0;
timer+=1000;
}
}
stop();
}
And the error that appears to me is:
Exception in thread "Thread-0" java.lang.IllegalStateException: Component must have a valid peer
at java.desktop/java.awt.Component$FlipBufferStrategy.createBuffers(Component.java:4105)
at java.desktop/java.awt.Component$FlipBufferStrategy.<init>(Component.java:4079)
at java.desktop/java.awt.Component$FlipSubRegionBufferStrategy.<init>(Component.java:4611)
at java.desktop/java.awt.Component.createBufferStrategy(Component.java:3942)
at java.desktop/java.awt.Canvas.createBufferStrategy(Canvas.java:195)
at java.desktop/java.awt.Component.createBufferStrategy(Component.java:3866)
at java.desktop/java.awt.Canvas.createBufferStrategy(Canvas.java:170)
at com.main.Game.render(Game.java:83)
at com.main.Game.run(Game.java:115)
at java.base/java.lang.Thread.run(Thread.java:834)
I checked out every line of this code and I don't know why show that the problem is with thread or bufferStrategy, the method render or method run that I used.
Is there any way to efficiently move an object from point A to point B without having to use an inefficient While(true) loop? I tried to repaint Draw class, but it did not help with the performance issues. I am unable to trace the root of the huge performance issue. I tried to research moving entities on Google, GitHub, and others and found nothing useful. Any help is appreciated!
Code:
class Draw extends JPanel {
public static int x;
public static int y;
public static int randx;
public static int randy;
public void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage image = null;
BufferedImage image1 = null;
try {
image = ImageIO.read(new File("Small Sheep Icon.png"));
image1 = ImageIO.read(new File("Small Sheep Icon.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
g.drawImage(image, x, y, null);
g.drawImage(image1, randx, randy, null);
// g.drawString("Hello, World", x, y);
}
}
public static void sheepmove() {
double starttime = System.nanoTime();
double previoustime = 0;
double waittime = 0;
boolean xright = true;
boolean waitswitch = false;
int counter = 0;
while(true) {
double elapsedtime = (System.nanoTime() - starttime)/(1000000000);
if (elapsedtime-waittime >= 1 || waitswitch == false) {
if (waitswitch == true) {
waitswitch = false;
}
waittime = elapsedtime;
if (elapsedtime >= previoustime + 0.1) {
previoustime = elapsedtime;
if (xright == true) {
Draw.randx += 1;
}
if (Draw.randx - 200 >= 50) {
if (counter == 0) {
waitswitch = true;
xright = false;
}
// System.out.println("Moving south...");
Draw.randy += 1;
if (Draw.randy >= 300) {
Draw.randy -= 1;
break;
}
counter++;
}
frame.repaint();
// System.out.print("=");
// System.out.println("Previous Time: " + previoustime);
}
}
// System.out.println(elapsedtime);
// Thread.sleep(1000);
}
}
public static void main(String[] args) {
new Demo();
}
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent e) {
// System.out.println("Mouse Moved!");
Draw.x = e.getX();
Draw.y = e.getY();
frame.repaint();
}
I am rendering a model on canvas with opengl, therefore using a while loop and I run it under a thread not to disturb the main thread. I also have a text Field where I want to write some text. The text field focuses to my action and takes input but when hovering through the canvas, the text field focuses but I am not able to write something on it. This may be because of the the while loop but I do not know how to overcome this. I want the ui to remain responsive.
Here is my code:
import java.awt.Canvas;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextField;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.PixelFormat;
public final class Loader extends JFrame {
public final int FPS = 120; // better cause of animations
public static Loader loader;
public Canvas canvas;
private Viewport viewport;
private JTextField textField;
private Loader() {
setTitle("Test");
setResizable(true);
setSize(320, 285);
setLocationRelativeTo(null);
getContentPane().setLayout(null);
setVisible(true);
canvas = new Canvas();
getContentPane().add(canvas);
canvas.setBounds(10, 24, 280, 163);
textField = new JTextField();
textField.setColumns(10);
textField.setBounds(91, 193, 116, 22);
getContentPane().add(textField);
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
// Initialize the frame
loader = new Loader();
new Thread(new Runnable() {
#Override
public void run() {
try {
// render the model
loader.render();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private static void init(Canvas canvas) throws Exception {
Display.setParent(canvas);
try {
Display.create(new PixelFormat(8, 24, 8, 8));
} catch (Exception ex) {
Display.create(new PixelFormat(8, 24, 8, 0));
}
Display.makeCurrent();
Display.setVSyncEnabled(false);
Display.setSwapInterval(0);
}
private void render() throws Exception {
init(canvas);
loader.viewport = new Viewport(canvas);
long[] timerCache = new long[10];
long timerCur = 0L;
long timerDst = 0L;
long timerLast = 0L;
long timerRate = 1000000L * 1000L / FPS;
int timerCacheIndex = 0;
int timerCacheSize = 0;
boolean minSleep = Runtime.getRuntime().availableProcessors() <= 1;
long[] clockCache = new long[32];
int clockIndex = 0;
int fps = 0;
while (isVisible()) {
long clock = System.nanoTime();
long lastClock = clockCache[clockIndex];
clockCache[clockIndex] = clock;
if (++clockIndex == 32)
clockIndex = 0;
if (lastClock != 0L && clock > lastClock) {
fps = (int) (1000000L * 1000L * 32L / (clock - lastClock));
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(.5f, .6f, .9f, 1f);
loader.viewport.render();
if (minSleep)
try {
Thread.sleep(1L);
} catch (Exception ex) {
}
timerCache[timerCacheIndex++] = System.nanoTime();
if (timerCacheSize < timerCacheIndex)
timerCacheSize = timerCacheIndex;
if (timerCacheIndex == 10)
timerCacheIndex = 0;
long time = 0L;
for (int i = 0; i != timerCacheSize; time += timerCache[i++])
;
time /= (long) timerCacheSize;
if (timerCacheSize == 1)
timerLast = time;
timerCur += time - timerLast;
timerLast = time;
timerDst += timerRate;
if (timerDst > timerCur) {
long sleep = timerDst - timerCur;
try {
Thread.sleep(sleep / 1000000L, (int) (sleep % 1000000L));
} catch (Exception ex) {
}
timerCur = timerDst;
for (int i = 0; i != timerCacheSize; ++i)
timerCache[i] += sleep;
timerLast += sleep;
}
}
}
}
This gif may help know how it currently looks.
https://gyazo.com/e6950fd8dd01306c704857e94f214f93.gif
I don't see where is the mistake in here, I already use a thread for the render method.
Edit:
Viewport.java
public Viewport(Canvas canvas) throws LWJGLException {
this.canvas = canvas;
this.scale = 1.0F;
this.pitch = 180.0F;
this.yaw = 0.0F;
this.roll = 0.0F;
}
public void render() {
try {
Dimension size = canvas.getSize();
if (models != null && size.width > 0 && size.height > 0) {
if (width != size.width || height != size.height) {
width = size.width;
height = size.height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float c = (float) Math.sqrt((double) (width * width) + (double) (height * height));
glOrtho(0.0F, (float) width, 0.0F, (float) height, -c, c);
glMatrixMode(GL_MODELVIEW);
}
if (Mouse.isButtonDown(0) && !Mouse.isButtonDown(1)) {
yaw -= (float) Mouse.getDX() / 2;
pitch -= (float) Mouse.getDY() / 2;
}
if (Mouse.isButtonDown(0) && Mouse.isButtonDown(1)) {
offset_z += (float) Mouse.getDY();
}
float wheel = (float) Mouse.getDWheel() / 1800.0F;
if (wheel > 1.0F)
wheel = 1.0F;
else if (wheel < -1.0F)
wheel = -1.0F;
scale += scale * wheel;
if (scale < 0.01F)
scale = 0.01F;
for (Model3D model : models) {
float x = (float) width / 2.0F;
float y = ((float) -((100.0F * (scale))) + offset_z) + (float) (height - model.height()) / 2.0F;
float z = 0.0F;
model.render(model, x, y, z, pitch, yaw, roll, scale, scale, scale);
}
Display.update();
}
} catch (Throwable t) {
}
}
Instead of:
new Thread(new Runnable() {
#Override
public void run() {
try {
// render the model
loader.render();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
maybe:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
// render the model
loader.render();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
It will run at AWT dispatching thread, maybe the issue will fade. Swing not being thread safe sometimes makes life hard.
Can you try adding requestFocus() to the end of your render() method of your Loader class and report back what happens?
I am creating a MouseEvent and it seems to be cancelling a few ticks after it starts as I can sometimes get a small response before it stops responding. Does anyone see why?
Here is where I initialize in init()
public class Game implements Runnable {
private Display display;
private int width, height;
public String title;
private boolean running = false;
private Thread thread;
private BufferStrategy bs;
private Graphics g;
//Input
Mouse mouse;
//Handler
private Handler handler;
public Game(String title, int width, int height){
this.title = title;
this.width = width;
this.height = height;
mouse = new Mouse();
}
public synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop(){
if(!running)
return;
running = false;
try {
thread.join();
}
catch (InterruptedException e){ e.printStackTrace(); }
}
public void run() {
init();
int fps = 60;
double timePerTick = 1000000000 / fps;
double delta = 0;
long now;
long lastTime = System.nanoTime();
long timer = 0;
int ticks = 0;
while(running){
now = System.nanoTime();
delta += (now - lastTime) / timePerTick;
timer += now - lastTime;
lastTime = now;
if(delta >= 1){
tick();
render();
ticks++;
delta--;
}
if(timer >= 1000000000){
ticks = 0;
timer = 0;
}
}
stop();
}
private void init() {
display = new Display(title, width, height);
display.getFrame().addMouseListener(mouse);
Assets.init();
handler = new Handler(this);
}
private void tick() {
Tile tile = new Tile();
tile.tick();
}
private void render() {
bs = display.getCanvas().getBufferStrategy();
if(bs == null){
display.getCanvas().createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
g.clearRect(0, 0, width, height); //Clears the Screen
//Start of Drawing
ChessBoard cb = new ChessBoard(64);
cb.render(g);
cb.tick();
//End of Drawing
bs.show();
g.dispose();
}
}
And here is the MouseEvent
public class Mouse implements MouseListener {
public void mousePressed(MouseEvent e) {
System.out.println("1");
}
public void mouseReleased(MouseEvent e) {
System.out.println("2");
}
public void mouseEntered(MouseEvent e) {
System.out.println("3");
}
public void mouseExited(MouseEvent e) {
System.out.println("4");
}
public void mouseClicked(MouseEvent e) {
System.out.println("5");
}
}
I'm trying to make a 2D game that should draw a character to the screen. But when I run it, I just get a black screen.
The important bits:
public class StartingClass extends Applet implements Runnable, KeyListener {
private static final long serialVersionUID = 1L;
private Walrus walrus;
private Image image, character;
private Graphics second;
private URL base;
#Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Applet");
try {
base = getDocumentBase();
} catch (Exception e) {
// TODO: handle exception
}
// Image Setups
character = getImage(base, "src/data/walrus_right.png");
}
#Override
public void start() {
walrus = new Walrus();
Thread thread = new Thread(this);
thread.start();
}
#Override
public void stop() {
// TODO Auto-generated method stub
}
#Override
public void destroy() {
// TODO Auto-generated method stub
}
#Override
public void run() {
while (true) {
walrus.update();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
second = image.getGraphics();
}
second.setColor(getBackground());
second.fillRect(0, 0, getWidth(), getHeight());
second.setColor(getForeground());
paint(second);
g.drawImage(image, 0, 0, this);
}
#Override
public void paint(Graphics g) {
g.drawImage(character, walrus.getCenterX() - 61, walrus.getCenterY() - 63, this);
}
}
Also, here's my other class:
public class Walrus {
private int centerX = 100;
private int centerY = 382;
private boolean jumped = false;
private int speedX = 0;
private int speedY = 1;
public void update() {
// Moves Character or Scrolls Background accordingly.
if (speedX < 0) {
centerX += speedX;
} else if (speedX == 0) {
System.out.println("Do not scroll the background.");
} else {
if (centerX <= 150) {
centerX += speedX;
} else {
System.out.println("Scroll Background Here");
}
}
// Updates Y Position
if (centerY + speedY >= 382) {
centerY = 382;
}else{
centerY += speedY;
}
// Handles Jumping
if (jumped == true) {
speedY += 1;
if (centerY + speedY >= 382) {
centerY = 382;
speedY = 0;
jumped = false;
}
}
// Prevents going beyond X coordinate of 0
if (centerX + speedX <= 60) {
centerX = 61;
}
}
public void moveRight() {
speedX = 6;
}
public void moveLeft() {
speedX = -6;
}
public void stop() {
speedX = 0;
}
public void jump() {
if (jumped == false) {
speedY = -15;
jumped = true;
}
}
public int getCenterX() {
return centerX;
}
public int getCenterY() {
return centerY;
}
public boolean isJumped() {
return jumped;
}
public int getSpeedX() {
return speedX;
}
public int getSpeedY() {
return speedY;
}
public void setCenterX(int centerX) {
this.centerX = centerX;
}
public void setCenterY(int centerY) {
this.centerY = centerY;
}
public void setJumped(boolean jumped) {
this.jumped = jumped;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setSpeedY(int speedY) {
this.speedY = speedY;
}
}
I haven't gotten any errors at this point, but it's not working right.
The problem is that your image is not loaded. The line
getImage(base, "src/data/walrus_right.png");
tries to read the image for a deployed applet and will fail quietly (not throw errors), which is what caused the confusion. Try to replace it with
ImageIO.read(new File(getClass().getResource("relative/path.png").getPath()));
where you should replace the path as specified under getResource API.
Edit:
Break the call into several calls:
Class<? extends StartingClass> clas = getClass();
URL url = clas.getResource("relative/path.png");
String path = url.getPath();
File file = new File(path);
try {
Image image = ImageIO.read(file);
} catch (IOException e) {
e.printStackTrace();
}
and move with the debugger step by step to see which line throws the error. My guess is that the file is not located in the right place, which causes getResource to return null, which causes new File(path) to throw NullPointerException.