[java] graphics in applets

Started by
15 comments, last by GameDev.net 17 years, 10 months ago
Hey, I am trying to make a game that runs on applets. I need to know if and how to put graphics on an applet thru other Containers such as Canvases and JPanels. I know the usual way is thru paint(), but I have states that handle the graphics themselves (as well as WHEN to do the graphics, so I can't just call their methods from the applet's method). I know this is possible in JFrames by adding the Container to the JFrame, and the Container's graphics will show up in the JFrame. I tried adding the Container to the Applet, and the state's functions are all performed correctly, just the graphics are not showing up. Also, I tried making it a JApplet, which has a getContentPane() just like a JFrame. I add the Containers to it the same way, however I get the same result as with the Applet. Thanks! [Edited by - deej21 on May 21, 2006 6:30:19 PM]
Advertisement
Make sure that whenever you change containers after the initial container you have a call to Component.validate(); so whenever you add a Component or swap components on a JFrame.getContentPane() you need to also call JFrame.getContentPane().validate();

Thanks for the reply.

Hm, I thought that was only when having multiple components. I control it so there is always only one component in the pane. Regardless, I tried it and it didn't work. In my applications, I use JFrames, and I don't use validate() and it works fine.

Although, I also just tried doing a simple paint() with a fillBox() and some random stuff, and none of that showed up either... my experience with applets is, well, this, so perhaps I'm missing one of the most simple things.

Also, where is it best to call my game loop? If I don't call the game loop, the applet gets fully initialized, and my state system recieves event calls from the keylistener (which is how I know it's functioning still). However, if I call the game loop in the Applet.start(), the while(true) in the game loop takes up the whole thread. The states don't get any event calls, and the AppletViewer shows "Applet Initialized" rather than "Applet Started". I tried SwingUtilities.invokeLater(), and still got the same results.
Try this simple example.
import java.awt.*;import javax.swing.*;public class Test extends JApplet {    public void init() {        getContentPane().add(new MyPanel());    }}class MyPanel extends JPanel {    public void paintComponent(Graphics g) {        g.fillRect(10, 10, 100, 100);    }}

Also you are supposed to override paintComponent, not paint.
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]
Ok... I've been working on this for a bit.
I figured out that, yes, adding the state like that does work. The reason it didn't work for me before is because I called the game loop in Applet.start(), which means start() doesn't return, so the applet isn't officially "started", thus only initialized, and nothing is shown. I tried calling state.update() only once at the end of start(), and it drew the proper screen. Of course, it didn't draw anything else since I didn't call update() anymore.

What is the best way to have the game loop be called on a separate thread so it can work properly? Like I said, I tried SwingUtilities.invokeLater(), but I got the same results as calling the loop at the end of start().

(off subject) I was taught to use paint()... it works properly that way. What is the difference between using paint and paintComponent. Obviously different definitions in the super class, but what am I overriding?
Under AWT it was paint. Under Swing, it is recommended that you use paintComponent. I can't remember the reasons, I just remember that that is what was recommended. Check it out in "The Java Tutorial", I am sure they explain it there.

Also, you shouldn't have a game loop in start. start is meant to return to the web browser. If you need a game loop in an applet, you need to start a new thread.
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]
Right... that's what I said. Would the most efficient way be to merely call

new Thread(new Runnable(){
public void run(){ loop(); }}).start();
The way I have been calling my "render loop" has been with java.util.Timer and java.util.TimerTask which I think is much quicker and less code you have to write yourself.

You don't have to bother with Thread.wait() calls or calculating the timing. And you can add any number of Tasks to be run as you want.

java.util.Timer tasker = new java.util.Timer();tasker.schedule(     new TimerTask() {           public void run() {                screen.paint();           }     }     1,      15 /* this is the length of time between calls */);
The only thing to note when using threaded tasks is that you must account for concurrency issues making sure that two threads won't modify the same data.

That's an interesting way to do it... I used to use Timers, but I don't like them that much. I prefer to use System.currentTimeMillis() and use delta / 1000 * pixelsPerSecond for movement.
Also, the code is very simple. In the update() method, just have
if(System.currentTimeMillis() - timeLastUpdate > waitTime){    genericUpdateEverythingMethod();        timeLastUpdate += waitTime;}


Regardless, I got it to work, but am having problems in running the applet in a browser. I could have made a new thread, but figured it is appropriate here also.
Since browsers don't let applets read or write any files, I can't read in the images I need. I tried archiving everything into a .jar file, but still got the same problem. I would think a .jar file would work, since I thought that was kinda the point of a .jar file. One possibility I thought of was making a server-side application to load the images and send them to the game, although I'm really not wanting to do that. Is there an easier way?
There are a couple different ways to read files in an applet. You can read property files in an applet and also get audio and images.

I pack everything into a .jar file and load the images using the Applet.getImage()

if you put everything in a .jar then all you need to do is

this.getImage( this.getCodeBase(), <image> );

and that will load the image.

The only problem I've come across is that the images don't load right away so you need to make a call to the boolean prepareImage( Image, ImageObserver ) function which will return true when the image is fully loaded.

to load property files in an applet you need to use the URLClassLoader.

URL uProp = new URL(this.getCodeBase(), jarFile);URL arr[] = new URL[1];arr[0] = uProp;URLClassLoader urlLoader = URLClassLoader.newInstance(arr);System.out.println( this.getCodeBase() );properties.load( urlLoader.findResource(propertyFile).openStream() );

where the jarFile is just the name of your jar file
and propertyFile is just the name of the property file.

I personally like the java.util.Timer class since I don't have to worry about the timing piece of it which is especially useful for animations. But I guess if you make your own API then you only have to do it once but I still find that when making a game from scratch I don't have to bother making with that part of the game and can move on to bigger and better things. But to each his own.

This topic is closed to new replies.

Advertisement