Basic LWJGL Applet

From LWJGL
Jump to: navigation, search

LWJGL Applets are basically just the native LWJGL window stuck on top of a java canvas. Before proceeding you should already know how to use the LWJGL native Display and have a basic understanding of Java Applets.

We will start of with a basic Java Applet template with an awt canvas on it.

import java.applet.Applet;
import java.awt.Canvas;

public class ExampleApplet extends Applet {

	Canvas display_parent;
	
	public void init() {
		display_parent = new Canvas();
		display_parent.setSize(getWidth(),getHeight());
		add(display_parent);
		display_parent.setFocusable(true);
		display_parent.requestFocus();
		display_parent.setIgnoreRepaint(true);
		setVisible(true);
	}

	public void start() {
		
	}

	public void stop() {
		
	}
	
	
	public void destroy() {
		
	}
}

The keen eyed will notice that we have setIgnoreRepaint to true, this is because we don't want awt drawing anything as everything will be drawn by LWJGL.

Now that we have the basic template we need to stick the LWJGL native Display on it. To do this we simply use the Display.setParent(Canvas) method. However before we can create the Display we need to make sure that the canvas is ready to be drawn on. To ensure this we will use the addNotify() method of the awt canvas to tell us when the canvas is ready and that we can create the Display. Similarly we will use the removeNotify() to inform us that the canvas is about to be destroyed and we should clean up and close the native Display.

We should now have something like the following

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Canvas;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;

public class ExampleApplet extends Applet {
	
	Canvas display_parent;
	
	public void startLWJGL() {
		try {
			Display.setParent(display_parent);
			Display.create();
		} catch (LWJGLException e) {
				e.printStackTrace();
		}
	}
	
	private void stopLWJGL() {
		Display.destroy();
	}

	public void start() {
		
	}

	public void stop() {
		
	}
	
	public void destroy() {
		remove(display_parent);
		super.destroy();
	}
	
	public void init() {
		setLayout(new BorderLayout());
		try {
			display_parent = new Canvas() {
				public final void addNotify() {
					super.addNotify();
					startLWJGL();
				}
				public final void removeNotify() {
					stopLWJGL();
					super.removeNotify();
				}
			};
			display_parent.setSize(getWidth(),getHeight());
			add(display_parent);
			display_parent.setFocusable(true);
			display_parent.requestFocus();
			display_parent.setIgnoreRepaint(true);
			setVisible(true);
		} catch (Exception e) {
			System.err.println(e);
			throw new RuntimeException("Unable to create display");
		}
	}
}

Finally we don't want LWJGL running on or blocking the Applet EDT so we should run our main game loop on another thread. Also if something does go wrong, like a crash or hang in the game code, it won't freeze or crash the browser (although modern browsers now protect against this, its still recommended).

We should have something like this

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Canvas;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;

public class ExampleApplet extends Applet {
	
	Canvas display_parent;
	
	/** Thread which runs the main game loop */
	Thread gameThread;
	
	/** is the game loop running */
	boolean running = false;
	
	
	public void startLWJGL() {
		gameThread = new Thread() {
			public void run() {
				running = true;
				try {
					Display.setParent(display_parent);
					Display.create();
					initGL();
				} catch (LWJGLException e) {
					e.printStackTrace();
					return;
				}
				gameLoop();
			}
		};
		gameThread.start();
	}
	
	
	/**
	 * Tell game loop to stop running, after which the LWJGL Display will 
	 * be destoryed. The main thread will wait for the Display.destroy().
	 */
	private void stopLWJGL() {
		running = false;
		try {
			gameThread.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void start() {
		
	}

	public void stop() {
		
	}
	
	/**
	 * Applet Destroy method will remove the canvas, 
	 * before canvas is destroyed it will notify stopLWJGL()
	 * to stop the main game loop and to destroy the Display
	 */
	public void destroy() {
		remove(display_parent);
		super.destroy();
	}
	
	public void init() {
		setLayout(new BorderLayout());
		try {
			display_parent = new Canvas() {
				public final void addNotify() {
					super.addNotify();
					startLWJGL();
				}
				public final void removeNotify() {
					stopLWJGL();
					super.removeNotify();
				}
			};
			display_parent.setSize(getWidth(),getHeight());
			add(display_parent);
			display_parent.setFocusable(true);
			display_parent.requestFocus();
			display_parent.setIgnoreRepaint(true);
			setVisible(true);
		} catch (Exception e) {
			System.err.println(e);
			throw new RuntimeException("Unable to create display");
		}
	}

	protected void initGL() {
		
	}
	
	public void gameLoop() {
		while(running) {
			Display.sync(60);
			Display.update();
		}
		
		Display.destroy();
	}
}

You will notice that we now have a game thread with a basic game loop that contains initGL() and gameLoop() methods. Do notice how the stopLWJGL() method is now different, it will wait for the game loop to exit before calling Display.destroy() to clean up.

And that's all there is to it. You'll notice its a minimal amount of extra code on top the normal LWJGL Display code. So its fairly easy to port existing LWJGL Applications to LWJGL Applets.

Lastly i'll leave you with a full working example called the GearsApplet which can be found here and the source code of which can be found here.


Tutorial Credit - Ninja Cave

Personal tools
Namespaces

Variants
Actions
Navigation
Tools