Well, I’m working on a small Java2D-AWT-based breakout clone and I have a few problems, maybe you can help me with them.
I designed the game engine with fullscreen or windowed mode in mind, but developed mainly in windowed. When I try to switch to fullscreen now, keyboard-input does not work, and my performance goes from somewhere in the 40-60FPS range to 5-15FPS. It’s very puzzling, as I thought fullscreen exclusive was supposedly faster than windowed, and there doesn’t seem to be any cause of the keyboard-input problem.
ScreenCanvas.java
/*
* ScreenCanvas Class
*
* Used to encapsulate the process of setting up and showing frame renders,
* multi-buffering, and everything related to graphics.
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
public class ScreenCanvas extends Frame
{
protected static int width;
protected static int height;
protected static int fps;
protected static boolean instance = false;
public static int getScreenWidth()
{
return width;
}
public static int getScreenHeight()
{
return height;
}
public static int getFPS()
{
return fps;
}
public static ScreenCanvas getInstance()
{
if( !instance )
return new ScreenCanvas();
return null;
}
public static ScreenCanvas getInstance( String title )
{
if( !instance )
return new ScreenCanvas( title );
return null;
}
private GraphicsEnvironment env;
private GraphicsDevice device;
private GraphicsConfiguration gc;
private BufferStrategy bufferStrategy;
private DisplayMode fullscreenMode;
private DisplayMode windowedMode;
private DisplayMode displayMode;
private int fps_max;
//private double fps_avg = 0;
private long startTime;
private long endTime;
private long wantedEndTime;
private Canvas canvas;
private Component raster;
private boolean debug;
protected ScreenCanvas()
{
this( "" );
}
protected ScreenCanvas( String title )
{
ScreenCanvas.instance = true;
debug = Configuration.getBoolean("debug", false);
ScreenCanvas.fps = 0;
fps_max = Utility.clamp( Configuration.getInteger( "fps_max", 0 ), 0, 1000 );
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
cleanup();
}
});
setBackground( Color.black );
setIgnoreRepaint( true );
setResizable( false );
setFocusable( false );
env = GraphicsEnvironment.getLocalGraphicsEnvironment();
device = env.getDefaultScreenDevice();
gc = device.getDefaultConfiguration();
int bitDepth = device.getDisplayMode().getBitDepth();
int refreshRate = device.getDisplayMode().getRefreshRate();
fullscreenMode = new DisplayMode( Configuration.getInteger("fs_res_w", 1024), Configuration.getInteger("fs_res_h", 768), bitDepth, refreshRate );
windowedMode = new DisplayMode( Configuration.getInteger("wnd_res_w", 1024), Configuration.getInteger("wnd_res_h", 768), bitDepth, refreshRate );
if( Configuration.getBoolean("fakefullscreen", false) )
{
//Setup fake-fullscreen
setupFakeFullscreen();
}
else if( Configuration.getBoolean("fullscreen", false) && device.isFullScreenSupported() )
{
//Setup fullscreen
setupFullscreen();
}
else
{
//Setup windowed
setupWindowed();
}
if( !isVisible() )
setVisible( true );
if( canvas == null )
{
createBufferStrategy( Configuration.getInteger("buffers", 2) );
bufferStrategy = getBufferStrategy();
}
else
{
canvas.createBufferStrategy( Configuration.getInteger("buffers", 2) );
bufferStrategy = canvas.getBufferStrategy();
}
ScreenCanvas.width = raster.getWidth();
ScreenCanvas.height = raster.getHeight();
raster.addKeyListener( new Input() );
raster.addMouseListener( new Input() );
raster.addMouseMotionListener( new Input() );
raster.addMouseWheelListener( new Input() );
requestFocus();
try{
Thread.sleep(375);
} catch(Exception e) {}
Console.echo( Console.VERBOSE, "ScreenCanvas Initialized" );
setTitle( title );
}
public void cleanup()
{
if( device.getFullScreenWindow() != null )
device.setFullScreenWindow(null);
bufferStrategy = null;
ScreenCanvas.instance = false;
setVisible(false);
dispose();
}
private void setupWindowed()
{
Console.echo( Console.NORMAL, "Using Windowed Mode" );
Insets windowInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc ); //Use these insets to correct the 'odd' space left around borders...
setSize( windowedMode.getWidth() + windowInsets.left + windowInsets.right, windowedMode.getHeight() + windowInsets.top + windowInsets.bottom );
canvas = new Canvas();
canvas.setBackground( Color.black );
canvas.setIgnoreRepaint( true );
canvas.setFocusable( true );
canvas.setSize( windowedMode.getWidth(), windowedMode.getHeight() );
canvas.setLocation( 0, 0 );
add( canvas );
raster = canvas;
displayMode = windowedMode;
}
private void setupFullscreen()
{
Console.echo( Console.NORMAL, "Using Fullscreen Mode" );
setUndecorated(true);
if( device.isFullScreenSupported() )
device.setFullScreenWindow(this);
if( device.isDisplayChangeSupported() )
{
if( isDisplayModeSupported( fullscreenMode ) )
device.setDisplayMode( fullscreenMode );
}
setSize( fullscreenMode.getWidth(), fullscreenMode.getHeight() );
raster = this;
canvas = null;
displayMode = fullscreenMode;
}
private void setupFakeFullscreen()
{
Console.echo( Console.NORMAL, "Using Fake Fullscreen Mode" );
setUndecorated( true );
if( device.isDisplayChangeSupported() ) // Well, if we can change it without going into the
{ // Fullscreen exclusive mode, do it. (Probably not though)
if( isDisplayModeSupported( fullscreenMode ) )
device.setDisplayMode( fullscreenMode );
}
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setSize( (int)screenSize.getWidth(), (int)screenSize.getHeight() );
canvas = new Canvas();
canvas.setBackground( Color.black );
canvas.setIgnoreRepaint( true );
canvas.setFocusable( true );
canvas.setSize( getSize() );
canvas.setLocation( 0, 0 );
add( canvas );
raster = canvas;
displayMode = new DisplayMode( (int)screenSize.getWidth(), (int)screenSize.getHeight(), fullscreenMode.getBitDepth(), fullscreenMode.getRefreshRate() );
}
private boolean isDisplayModeSupported( DisplayMode dm )
{
DisplayMode[] modes = device.getDisplayModes();
for (int i = 0; i < modes.length; i++)
{
if (dm.getWidth() == modes[i].getWidth() && dm.getHeight() == modes[i].getHeight() && dm.getBitDepth() == modes[i].getBitDepth() && dm.getRefreshRate() == modes[i].getRefreshRate())
return true;
}
return false;
}
public void setCursorVisible( boolean b )
{
if( b )
{
setCursor( Cursor.getDefaultCursor() );
}
else
{
int[] pixels = new int[16 * 16];
Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
Cursor transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "");
setCursor( transparentCursor );
}
}
public void setCustomCursor( ARGBImage img )
{
int[] pixels = img.toIntArray();
Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
Cursor cur = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "");
setCursor( cur );
}
public Graphics2D getGraphics()
{
if( bufferStrategy != null )
{
Graphics2D g = (Graphics2D)bufferStrategy.getDrawGraphics();
g.setClip( new Rectangle( 0, 0, raster.getWidth(), raster.getHeight() ) );
return g;
}
return null;
}
public void StartFrame()
{
if( bufferStrategy == null )
return;
startTime = Utility.currentTimeMillis();
Graphics2D g = getGraphics();
if(g == null)
return;
g.setColor( getBackground() );
g.fillRect( 0, 0, raster.getWidth(), raster.getHeight() );
}
public void EndFrame()
{
if( bufferStrategy == null || bufferStrategy.contentsLost() )
return;
Graphics2D g = getGraphics();
if(g == null)
return;
if( debug )
{
Console.render( g );
DynamicGrid.render( g );
}
if( bufferStrategy != null && !bufferStrategy.contentsLost() && isVisible() )
bufferStrategy.show();
endTime = Utility.currentTimeMillis();
if( fps_max > 0 )
{
wantedEndTime = ( 1000 / fps_max ) + startTime;
while( wantedEndTime > endTime )
{
endTime = Utility.currentTimeMillis();
}
}
if( endTime != startTime )
ScreenCanvas.fps = Utility.clamp( (int)( 1000 / (endTime - startTime) ), 1, Integer.MAX_VALUE );
else
ScreenCanvas.fps = 1000;
TimerSystem.update();
/*if( fps_avg != 0)
{
fps_avg += ScreenCanvas.fps;
fps_avg /= 2;
}
else
{
fps_avg = ScreenCanvas.fps;
}*/
}
public void setDebug( boolean b )
{
debug = b;
}
public boolean getDebug()
{
return debug;
}
public void update( Graphics g ) {}
public void paint( Graphics g ) {}
}