Reputation: 4191
I have just started learning java and I've been working on this code for a moving object with keyboard input. I am now trying to add in a background, but it keeps erroring with:
javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(Unknown Source)
at game.GameLoop.run(GameLoop.java:24)
at java.lang.Thread.run(Unknown Source)
The code I have in Game.java is:
package game;
import java.applet.*;
import java.awt.*;
public class Game extends GameLoop{
public void init(){
setSize(864,480);
Thread th = new Thread(this);
th.start();
offscreen = createImage(864,480);
d = offscreen.getGraphics();
addKeyListener(this);
}
public void paint(Graphics g){
d.clearRect(0, 0, 864, 480);
d.drawImage(background, 0, 0, this);
d.drawRect(x, y, 20, 20);
g.drawImage(offscreen, 0, 0, this);
}
public void update(Graphics g){
paint(g);
}
}
And here is my GameLoop.java:
package game;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class GameLoop extends Applet implements Runnable, KeyListener{
public int x, y;
public Image offscreen;
public Graphics d;
public boolean up, down, left, right;
public BufferedImage background;
public void run(){
x = 100;
y = 100;
try {
background = ImageIO.read(new File("background.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
while(true){
x = 100;
y = 100;
while(true){
if (left == true){
x-=4;
}
if (right == true){
x+=4;
}
if (up == true){
y-=4;
}
if (down == true){
y+=4;
}
if ( x <= 0 ){
x = 0;
}
if ( y <= 0 ){
y = 0;
}
if ( x >= 843 ){
x = 843;
}
if ( y >= 460 ){
y = 459;
}
repaint();
try{
Thread.sleep(20);
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
//@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == 37){
left = true;
}
if(e.getKeyCode() == 38){
up = true;
}
if(e.getKeyCode() == 39){
right = true;
}
if(e.getKeyCode() == 40){
down = true;
}
}
//@Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == 37){
left = false;
}
if(e.getKeyCode() == 38){
up = false;
}
if(e.getKeyCode() == 39){
right = false;
}
if(e.getKeyCode() == 40){
down = false;
}
}
//@Override
public void keyTyped(KeyEvent e) {
}
}
Sorry about the editing I can't seem to get it all in the ``, and I will also fix the messy code, but do you guys have any ideas what is causing this error, there is a file in the src dir called background.png, it is very basic and made in MS paint, if that helps.
Thanks.
Upvotes: 0
Views: 13448
Reputation: 34
@Patricia Shanahan Your comment actually helped me to solve the same problem.
I've used that code:
File here = new File(".");
try {
System.out.println(here.getCanonicalPath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
and from there you can figure out the correct path to use.
Upvotes: 1
Reputation: 168825
There are two places a simple, sand-boxed applet can obtain images.
"background.png"
strongly indicates the 2nd scenario - 'part of the app. itself'.
Both types of resources should identified by URL
(do not try to establish a File
as it will fail when the applet is deployed).
The way to obtain an URL
for the 2nd case is something along the lines of:
URL urlToBG = this.getClass().getResource("/path/to/the/background.png");
..where /path/to/the/
might simply be /resources/
or /images/
. It is the path within a Jar on the classpath, where the image can be found.
Most methods that will load a File
are overloaded to accept an URL
. This notably applies to ImageIO.read(URL)
.
While the Applet
class has inbuilt methods to load images, I recommend sticking with ImageIO
since it provides more comprehensive feed-back on failure.
Thread.sleep(20);
Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling Thread.sleep(n)
implement a Swing Timer
for repeating tasks or a SwingWorker
for long running tasks. See Concurrency in Swing for more details.
It is the third millennium, time to start using Swing instead of AWT. That would mean extending JApplet
instead of Applet
. Then you might shift the logic of painting into a JPanel
that is double-buffered by default, and could be used in either the applet or a frame (or a window or a dialog..).
setSize(864,480);
The size of an applet is set in HTML, and the applet should accept whatever size it is assigned and work within that. Taking that into account, statements like:
d.clearRect(0, 0, 864, 480);
..should read more like:
d.clearRect(0, 0, getWidth(), getHeight());
Upvotes: 4