Hi!
I’m trying to write a simple game using Java2D and fullscreen exclusive mode api. I have followed the tutorials and examples, but I am not able to get
this little demo working smoothly on Vista. Mac OS X runs without problems! I have attached the source. A prebuilt JAR is available from http://gambitchess.org/moin.py/StutterDemo
Using the vsync hack as described in http://www.java-gaming.org/forums/index.php?topic=14696.0 does help a bit (framerate is locked to 60 Hz then), but
it stutters anyways. For running with vsync hack, please make sure, that pxsync.dll is in your working directory.
Thank you!
Specs: JDK 1.6, Intel Core 2 Duo, Windows Vista 32-bit, ATI Radeon X1600, DirectX Games work fine…
Source of Main.java:
/** send comments and ideas to sebastian.urban@gmx.de */
package stutterdemo;
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferStrategy;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
// uncomment this and other lines below to enable vsync hack
//import de.pxlab.pxl.VideoSync;
/** This demo shows stuttering of simple graphics in fullscreen-mode using Java2D
* on MS Windows.
*
* NOTE: This demo runs fine on Mac OS X!
*/
public class Main extends Frame implements Runnable {
/** set to true to enable logging of frame delays */
final boolean writeLog = false;
/** path to logfile (make sure you have write permissions, especially on Vista!) */
final String logPath = "C:\\users\\public\\StutterDemoLog.csv";
/** set to true to change display mode at startup */
final boolean changeDisplayMode = false;
/** list of preferred display modes */
private static DisplayMode[] BEST_DISPLAY_MODES = new DisplayMode[] {
//new DisplayMode(1680, 1050, 32, 0),
new DisplayMode(1024, 768, 32, 0),
new DisplayMode(1024, 768, -1, 0), // for Linux
};
/** graphics device for fullscreen mode */
GraphicsDevice device;
/** used to stop the game thread on key press */
boolean gameShouldRun = true;
/** x coordinate of the box in the simulation */
double boxX = 10;
/** Creates a new instance of Main */
public Main(GraphicsConfiguration gc, GraphicsDevice device) {
super(gc);
this.device = device;
addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
gameShouldRun = false;
}
});
setResizable(false);
setUndecorated(true);
setIgnoreRepaint(true);
device.setFullScreenWindow(this);
setVisible(true);
if (!device.isFullScreenSupported()) {
JOptionPane.showMessageDialog(null, "Fullscreen mode not supported!");
System.exit(1);
}
if (changeDisplayMode) {
if (!device.isDisplayChangeSupported()) {
JOptionPane.showMessageDialog(null, "Display mode change not supported!");
System.exit(2);
}
chooseBestDisplayMode(device);
}
createBufferStrategy(2);
new Thread(this).start();
}
/** gets best display mode */
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 modes[i];
}
}
}
return null;
}
/** sets the display mode to the preferred mode */
protected static void chooseBestDisplayMode(GraphicsDevice device) {
DisplayMode best = getBestDisplayMode(device);
if (best != null) {
device.setDisplayMode(best);
}
}
/** game loop thread */
public void run() {
BufferStrategy bufferStrategy = getBufferStrategy();
BufferedWriter logWriter = null;
long startTime = System.nanoTime();
long lastTickStartTime = System.nanoTime();
long frameCount = 0;
long lastFrameCountStartTime = lastTickStartTime;
long frameRateCalcInterval = 40000 * 1000 * 1000;
double frameRate = 0;
long totalFrames = 0;
if (writeLog) {
try {
logWriter = new BufferedWriter(new FileWriter(logPath));
logWriter.write("Frame; lastTickDuration (mSec); Time since start (mSec); boxX\n");
} catch (IOException ex) {
ex.printStackTrace();
}
}
// GameLoop
while (gameShouldRun) {
long lastTickDuration = System.nanoTime() - lastTickStartTime;
lastTickStartTime = System.nanoTime();
if (logWriter != null) {
try {
logWriter.write(String.format("%d; %d; %f; %f\n", totalFrames, lastTickDuration / (1000 * 1000),
(float) (lastTickStartTime - startTime) / (1000f * 1000f),
boxX));
} catch (IOException ex) {
ex.printStackTrace();
}
totalFrames++;
}
// calc framerate
frameCount++;
if (lastFrameCountStartTime + frameRateCalcInterval < lastTickStartTime) {
frameRate = (double) frameCount / (double) (lastTickStartTime - lastFrameCountStartTime) * 1000 * 1000 * 1000;
frameCount = 0;
lastFrameCountStartTime = lastTickStartTime;
}
// run simulation step
simulation(lastTickDuration);
// redraw
Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
if (!bufferStrategy.contentsLost()) {
drawScene(g);
g.setColor(Color.WHITE);
g.drawString(String.format("%.0f", frameRate), getWidth() - 50, getHeight());
g.dispose();
// UNCOMMENT the following to enable vsync hack
// does help, but with it, it stutters every 3-4 seconds
//if (VideoSync.isEmulated()) // make sure it's not emulated
// System.exit(3);
//VideoSync.waitForBeginOfVerticalBlank();
bufferStrategy.show();
}
// run event thread, otherwise key events get stuck
Thread.yield();
}
// clean up
try {
if (logWriter != null)
logWriter.close();
} catch (IOException ex) {
ex.printStackTrace();
}
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
device.setFullScreenWindow(null);
dispose();
}
});
}
/** game animation */
protected void simulation(double t) {
boxX += t / (1000 * 1000) * 11/15;
if (boxX > getWidth())
boxX = 0;
}
/** scene drawer */
protected void drawScene(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.WHITE);
g.fillRect((int)boxX, getHeight()/2, 20, 20);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Thread() {
public void run() {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
GraphicsConfiguration gc = device.getDefaultConfiguration();
new Main(gc, device);
}
});
}
}
Seriously, just spend the time and stress out over getting it installed: You’ll have alot of trouble getting it to work, but when you do, you will be happy.