This one also gets asked alot. Here is my encapsulation of
all the work necessary to do page flipping for either windowe or
full screen mode from the Scroller example program:
First, there is a generic interface called a ScreenHandler:
/*
* ScreenHandler.java
*
* Created on May 17, 2001, 9:19 AM
*/
package com.worldwizards.scroller;
import java.awt.*;
import javax.swing.*;
/**
*
* @author Jeff Kesselman
* @version
*/
public interface ScreenHandler {
public Graphics getCurrentGraphics();
public boolean swapScreens();
public Image getVolatieBuffer();
public Image getBuffer();
public void add(JComponent c);
}
The real work is done by an implementation of this called (for hsitorical reasons) FullscreenHandler. Its contructor takes a boolean. if true it goes into full screen mode, if false it creates a frame instead.
(Note that there are very few differences in the code path for each.)
/*
* FullscreenHandler.java
*
* Created on May 17, 2001, 9:24 AM
*/
package com.worldwizards.scroller;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;
import javax.swing.*;
/**
*
* @author Jeff Kesselman
* @version
*/
public class FullscreenHandler implements ScreenHandler {
BufferStrategy bufferStrategy;
Graphics lastGraphics;
GraphicsDevice device;
JFrame mainFrame;
static int screenTopLeftX;
static int screenTopLeftY;
static int screenWidth;
static int screenHeight;
private static DisplayMode[] BEST_DISPLAY_MODES = new DisplayMode[] {
new DisplayMode(640, 480, 32, 0),
new DisplayMode(640, 480, 16, 0),
new DisplayMode(640, 480, 8, 0)
};
/** Creates new FullscreenHandler */
public FullscreenHandler (boolean fullScreen) {
try {
GraphicsEnvironment env = GraphicsEnvironment.
getLocalGraphicsEnvironment();
device = env.getDefaultScreenDevice();
GraphicsConfiguration gc = device.getDefaultConfiguration();
mainFrame = new JFrame(gc);
mainFrame.getContentPane().setLayout(null);
mainFrame.getContentPane().setIgnoreRepaint(true);
mainFrame.getRootPane().setIgnoreRepaint(true);
mainFrame.getLayeredPane().setIgnoreRepaint(true);
mainFrame.setIgnoreRepaint(true);
if (fullScreen) {
mainFrame.setUndecorated(true);
device.setFullScreenWindow(mainFrame);
if (device.isDisplayChangeSupported()) {
chooseBestDisplayMode(device);
}
} else {
DisplayMode dm = device.getDisplayMode();
screenWidth = dm.getWidth();
screenHeight = dm.getHeight();
//mainFrame.setUndecorated(true);
mainFrame.setSize(new Dimension(screenWidth,screenHeight));
Insets ins = mainFrame.getInsets();
screenTopLeftX = ins.left;
screenTopLeftY = ins.top;
screenWidth -= screenTopLeftX;
screenHeight -= screenTopLeftY;
mainFrame.show();
}
mainFrame.createBufferStrategy(2);
bufferStrategy = mainFrame.getBufferStrategy();
} catch (Exception e){
device.setFullScreenWindow(null);
}
}
public void setRepaintOff(Component c){
c.setIgnoreRepaint(true);
if (c instanceof java.awt.Container) {
Component[] children = ((Container)c).getComponents();
for(int i=0;i<children.length;i++) {
setRepaintOff(children[i]);
}
}
}
public void add(JComponent c) {
setRepaintOff(c);
mainFrame.getContentPane().add(c);
}
public void addMouseMotionListener(MouseMotionListener listener) {
mainFrame.addMouseMotionListener(listener);
}
public void addMouseListener(MouseListener listener) {
mainFrame.addMouseListener(listener);
}
public void paintComponents(Graphics g) {
mainFrame.getContentPane().paintComponents(g);
}
private static DisplayMode getBestDisplayMode(GraphicsDevice device) {
for (int x = 0; x < BEST_DISPLAY_MODES.length; x++) {
DisplayMode[] modes = device.getDisplayModes();
for (int i = 0; i < modes.length; i++) {
if (modes[i].getWidth() == BEST_DISPLAY_MODES[x].getWidth()
&& modes[i].getHeight() == BEST_DISPLAY_MODES[x].getHeight()
&& modes[i].getBitDepth() == BEST_DISPLAY_MODES[x].getBitDepth()
) {
return BEST_DISPLAY_MODES[x];
}
}
}
return null;
}
private static void chooseBestDisplayMode(GraphicsDevice device) {
DisplayMode best = getBestDisplayMode(device);
if (best != null) {
device.setDisplayMode(best);
}
screenWidth = best.getWidth();
screenHeight = best.getHeight();
}
public Graphics getCurrentGraphics(){
lastGraphics = bufferStrategy.getDrawGraphics();
lastGraphics.setClip(0,0,screenWidth,screenHeight);
lastGraphics.translate(screenTopLeftX,screenTopLeftY);
return lastGraphics;
}
public boolean swapScreens(){
boolean done = false;
if (!bufferStrategy.contentsLost()){
bufferStrategy.show();
done = true;
}
lastGraphics.dispose();
return done;
}
public Frame getFrame(){
return mainFrame;
}
public int getWidth() {
return mainFrame.size().width;
}
public int getHeight() {
return mainFrame.size().height;
}
public void dispose() {
device.setFullScreenWindow(null);
}
public Image getVolatieBuffer() {
// try ot get a volatile image the size of the screen
return device.getDefaultConfiguration().createCompatibleVolatileImage(getWidth(),
getHeight());
}
public Image getBuffer() {
return mainFrame.createImage(getWidth(),getHeight());
}
}
Finally here’s an exmple main loop from Scroller showing its use:
<snip>
screen = new FullscreenHandler(false);
<snip>
long frameStartTime;
while(gameNotDone) { // game loop
frameStartTime = System.currentTimeMillis();
Graphics g = screen.getCurrentGraphics();
g.clearRect(0,0,screen.getWidth(),screen.getHeight());
bkgPainter.paintBackground(g,0,0,
screen.getWidth(),screen.getHeight());
sprites.paint(g);
screen.swapScreens();
sprites.animate();
long deltatime = System.currentTimeMillis()-frameStartTime;
while (deltatime<(1000/FPS)){
try {
Thread.sleep((1000/FPS)-deltatime);
} catch (Exception e) {
e.printStackTrace();
}
deltatime = System.currentTimeMillis()-frameStartTime;
}
}
A few notes on the above:
(1) Its simplified from whats in scroller. Scroller handles a scrolling
background, mouse clicks for sprite movement, etc.
(2) The use of System.currentTimeMillis(0 is not good and will fail on
Win95, Win98, and WinME systems which have very bad
accuracy for System.currentTimeMillis(). For a better timing
solution see the “Sleep Timer hack” posted sperately.