A detailed look at implementing graphically demanding games in OpenGL with Java, using the JOGL library

Wednesday, December 17, 2008

Fullscreen or windowed?

Quick answer - both! I think that Java provides the most transparent way of handling fullscreen graphics that I've come across. Whether we're fullscreen or windowed, we need to set up an application window (JFrame) and put an OpenGL canvas (GLCanvas) in it. To go fullscreen, we use the GraphicsDevice class, which can be used with OpenGL or without (just in case you want a fullscreen accounting package?)

There are a few steps to turn your app into a fullscreen one:
  1. Remove decorations from your window. If you don't do this, you'll still see a title bar, and users will be able to move the window about on a black background. Not very pro.
  2. Set the full screen window to your JFrame.
  3. Choose a display mode - ideally you'll provide a way for the user to choose this, but to start with there's nothing wrong with hard-coding a resolution you know your machine can handle. Note - you can't change the display mode before setting the full screen window.
  4. Provide a way to get of of fullscreen mode! This should really be zero on the list. As a last resort, you should be able to Alt-F4 or ⌘-Q out of it, but debugging in fullscreen mode can be a pain unless you have a second computer. Fortunately you can debug in windowed mode, and just switch to fullscreen for serious playing.
Lets implement it. The full code can be found at
svn checkout "http://javagamedev.googlecode.com/svn/trunk/Tutorial 2"
and we'll end up with this: More exciting than a grey screen, no? Lets look at the important details. There are two classes this time - TutorialFrame and TutorialCanvas. The Frame class is the top level window. It controls whether the application runs full screen or not -
private void init(boolean bFullScreen) {
fullscreen = bFullScreen;
setUndecorated(bFullScreen);
setSize(800, 600);
setVisible(true);
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(bFullScreen ? this : null);
canvas.requestFocus();
}
By default the frame starts up windowed, but a quick call to
public void setFullscreen(boolean bFullscreen) {
if (fullscreen != bFullscreen) {
this.dispose();
init(bFullscreen);
}
}

switches between windowed or fullscreen. Note the call to dispose() - without this, the frame is "displayable", and any call to setUndecorated() will fail.

The Canvas class actually performs the rendering, and apart from reacting to a reshape, carries on blissfully ignorant of whether it's full screen or windowed. The Canvas implements KeyListener so that it can call the Frame's setFullscreen method:
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_F:
tFrame.setFullscreen(!tFrame.fullscreen);
break;
case KeyEvent.VK_ESCAPE:
tFrame.setFullscreen(false);
}
}
Nice and easy. Practise checking it out, and try to change the spinning shape being rendered - maybe a cube? Hint: you might need a depth buffer!

2 comments:

  1. when i switch between display modes i loose all textures and lists i have previously created, disposing the frame where the glcanvas is.

    ReplyDelete
  2. On mode changes, the GLDrawable's init method will be called, and you can reload your textures there. I have a texture manager class instead that get re-initialised from the main init method, and then the textures are reloaded on demand.

    The init method (or a method called from there) is also a great place to manage display lists.

    ReplyDelete