Image won't paint to animation
Question
Having problems loading/showing an image in a java applet. Not sure if I'm loading the image incorrectly or if I'm accessing it incorrectly. Here's the code that draws the ship and the background(it's an asteroid-like game). The background draws correctly but the ship doesn't. This is the main class method that I'm dealing with:
public void paintFrame(Graphics g) {
Dimension d = size();
g.fillRect(0, 0, d.width, d.height);
g.drawImage(ship.getImage(), d.width/2, d.height/2, null);
}
I create an instance of the ship class at the beginning of the class. However, if I try to instantiate the ship class in a method (such as "Ship ship = new Ship();), it says the variable "ship" is never used.
Here's the entire ship class:
public class Ship {
private int dx;
private int dy;
private int x;
private int y;
private Image image;
public Ship() {
ImageIcon ii = new ImageIcon("ship1.png");
image = ii.getImage();
}
public Image getImage() {
return image;
}
}
If I run it as is, it runs without errors, but it doesn't display the ship. If I try to create the instance of the ship anywhere else except at the top, it gives me a NullPointerException.
Update
Here's my entire main class:
import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
public class RunGame extends Applet implements Runnable {
int frame;
int delay;
Thread animator;
Ship ship = new Ship();
Level level;
Dimension offDimension;
Image offImage;
Graphics offGraphics;
/**
* Initialize the applet and compute the delay between frames.
*/
public void init() {
String str = getParameter("fps");
int fps = (str != null) ? Integer.parseInt(str) : 10;
delay = (fps > 0) ? (1000 / fps) : 100;
}
/**
* Method is called when the applet becomes visible on
* the screen.
*/
public void start() {
animator = new Thread(this);
animator.start();
}
/**
* This method is called by the thread that was created in
* the start method. It does the main animation.
*/
public void run() {
// Remember the starting time
long tm = System.currentTimeMillis();
while (Thread.currentThread() == animator) {
// Display the next frame of animation.
repaint();
// Delay depending on how far we are behind.
try {
tm += delay;
Thread.sleep(Math.max(0, tm - System.currentTimeMillis()));
} catch (InterruptedException e) {
break;
}
// Advance the frame
frame++;
}
}
/**
* This method is called when the applet is no longer
* visible. Set the animator variable to null so that the
* thread will exit before displaying the next frame.
*/
public void stop() {
animator = null;
offImage = null;
offGraphics = null;
}
/**
* Update a frame of animation.
*/
public void update(Graphics g) {
Dimension d = size();
// Create the offscreen graphics context
if ((offGraphics == null) || (d.width != offDimension.width) || (d.height != offDimension.height)) {
offDimension = d;
offImage = createImage(d.width, d.height);
offGraphics = offImage.getGraphics();
}
// Erase the previous image
offGraphics.setColor(getBackground());
offGraphics.fillRect(0, 0, d.width, d.height);
offGraphics.setColor(Color.black);
// Paint the frame into the image
paintFrame(offGraphics);
// Paint the image onto the screen
g.drawImage(offImage, 0, 0, null);
}
/**
* Paint the previous frame (if any).
*/
public void paint(Graphics g) {
if (offImage != null) {
g.drawImage(offImage, 0, 0, null);
}
}
/**
* Paint a frame of animation.
*/
public void paintFrame(Graphics g) {
Dimension d = size();
g.fillRect(0, 0, d.width, d.height);
//g.drawImage(level.getImage(), 0, 0, null);
g.drawImage(ship.getImage(), 400, 300, null);
}
}
Solution
ImageIcon ii = new ImageIcon("ship1.png");
The ImageIcon
constructor that accepts a String
presumes the string represents ..
..a file name or a file path.
'Applets and files do not mix.' Only a trusted applet can load a File
object, and even then, only from the file system of the end user. The File
objects cannot point back to the server.
Applets would more typically work with paths formed from an URL. The Applet
class provides a number of methods to help form that URL, and the ImageIcon
constructor is overloaded to accept an URL.
..Not sure if I'm loading the image incorrectly or if I'm accessing it incorrectly.
Debugging 101 is to display the image immediately after loading it. Drop the image icon into a label and use a JOptionPane
to show the label.
OTHER TIPS
Without seeing your full code we can't really tell what's going on with the exception, but in your call to drawImage() specify 'this' as the last parameter instead of null. Images are loaded asynchronously and so they need something that implements ImageObserver (such as your frame) to tell when they have managed to load a bit more (or all of it) - so that they can repaint.