I’ve tried to find some information on building a full screen game but what I’ve found isn’t as comprehensive as I wanted. What should I draw on? A Frame, JFrame, Canvas, JCanvas or a Window? I don’t plan to use any other GUI controlls (all is rendered by the game itself). I want a clean and easy way to draw onto the screen basically.
Window & Canvas are the 2 classes that reveal the calls necessary to create a BufferStrategy.
You should realy use a Canvas, so you can add it to whatever Container you are using (e.g. an Applet, Frame, JFrame etc etc)
Some (old!) code of mine for making a fullscreen display. (cation: probably not very robust :S )
private void createFullscreenWindow()
{
fullscreenWindow = new Window(mainFrame);
graphicsDev.setFullScreenWindow(fullscreenWindow);
// Check if possible to switch display modes
if (graphicsDev.isDisplayChangeSupported() )
{
// Changes supported, all good :)
}
else
{
// Cannot change, must run in window.
JOptionPane.showMessageDialog(null,
"Display mode cannot be changed, running in a window.",
"Cannot change display mode",
JOptionPane.ERROR_MESSAGE);
fullscreenWindow = null;
graphicsDev.setFullScreenWindow(null);
useFullscreen = false;
return;
}
currentDisplayMode = new DisplayMode(xResolution, yResolution, colourDepth, DisplayMode.REFRESH_RATE_UNKNOWN);
graphicsDev.setDisplayMode(currentDisplayMode);
fullscreenWindow.createBufferStrategy(2);
bufferStrategy = fullscreenWindow.getBufferStrategy();
graphicsConfig = fullscreenWindow.getGraphicsConfiguration();
mainFrame.setIgnoreRepaint(true);
fullscreenWindow.setIgnoreRepaint(true);
}
Worked for me Of course you need to restore the old display mode on exit and a couple of other housekeeping things as well.
What do you guys think of this GameCanvas i wrote:
/*
* Created on 2004-mar-15
*/
package tests;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
/**
* The GameCanvas class provides the basis for a game user interface.
*
* @author Johan Tibell
* @version 1.0
*/
public class GameCanvas extends Canvas
{
/** Decides if we are drawing on the back buffer or not. */
private boolean drawOnBuffer = true;
/** The buffer strategy currently used. */
private BufferStrategy strategy;
/**
* Creates a new instance of a GameCanvas.
*/
GameCanvas()
{
super();
}
/**
* Flushes the off-screen buffer to the display.
*/
public void flushGraphics()
{
// If the back buffers haven't yet been initialized do nothing.
if (strategy != null)
{
// If the buffer is intact draw it on the screen.
if (!strategy.contentsLost())
{
// The buffer strategy needs to draw its buffer on the
// screen not on its own buffer.
drawOnBuffer = false;
strategy.show();
// Any other drawing should be done on the buffer.
drawOnBuffer = true;
}
}
}
/**
* Obtains the Graphics object for rendering a GameCanvas.
*
* @return the Graphics object that renders to this GameCanvas' off-screen buffer
*/
public Graphics getGraphics()
{
if (drawOnBuffer)
{
if (strategy == null)
{
createBufferStrategy(2);
strategy = getBufferStrategy();
}
return strategy.getDrawGraphics();
}
// When drawing the buffer onto the screen we need to use the
// real Graphics object.
else
return super.getGraphics();
}
/**
* Paints this GameCanvas.
*
* @param g the Graphics object with which to render the screen
*/
public void paint(Graphics g)
{
// There's no need to call the super class paint method since
// it only clears the canvas to its background color. Instead
// we try to paint the last frame again if it hasn't been
// destroyed.
flushGraphics();
}
}
The drawOnBuffer is used since I wanted to use the getGraphics() as my method name (and the dubble buffering thing uses it for other purposes).
Could I just add this to a Frame and then set full screen? Or should I set full screen first and add it later?
Could someone please help me write a minimal code that attaches this canvas to a frame in fullscreen mode. Note that a call to setSize() of the canvas must be done before using it!
This is my test program for the windowed version and it works fine:
/*
* Created on Apr 27, 2003
*/
package tests;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
/**
* @author Johan Tibell
*/
public class GameCanvasTest
{
public static void main(String[] args)
{
testGraphics();
}
public static void testGraphics()
{
JFrame mainFrame = new JFrame("GameCanvas Test");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GameCanvas game = new GameCanvas();
game.setSize(640, 480);
mainFrame.getContentPane().add(game);
mainFrame.pack();
mainFrame.setVisible(true);
while (true)
{
Graphics g = game.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, 640, 480);
game.flushGraphics();
g.dispose();
try { Thread.sleep(20); } catch (InterruptedException e) {}
}
}
}
One piece of advice: do not use Window as a full screen window, use Frame instead.
I won’t go into details, but it really screws DDraw/D3D if you go fullscreen with a window and not a frame. We fixed some of the problems caused by this in 1.5 (and updated the javadoc for setFullScreenWindow to advise not to use window), but you never know.
[quote]One piece of advice: do not use Window as a full screen window, use Frame instead.
I won’t go into details, but it really screws DDraw/D3D if you go fullscreen with a window and not a frame. We fixed some of the problems caused by this in 1.5 (and updated the javadoc for setFullScreenWindow to advise not to use window), but you never know.
http://java.sun.com/j2se/1.5.0/docs/api/java/awt/GraphicsDevice.html#setFullScreenWindow(java.awt.Window)
[/quote]
So my best bet would be to make a Frame my fullscreen “window” and add a Canvas on it to draw on. Should I add the canvas before or after I go into fullscreen mode?
[quote]One piece of advice: do not use Window as a full screen window, use Frame instead.
[/quote]
Thats… odd. I never had a problem doing this ages ago (just after the first proper 1.4.0 release). Is this something thats got worse or is it only really a problem on crappy chips or obscure configurations?
It has always been the case, you just got lucky.
Usually the problems show up when you try to alt+tab back and forth from/to the full screen app (which is using bufferstrategy) or change the display modes, in other words, stress tests.