因此,我正在为我的游戏测试不同的屏幕尺寸。我测试的最佳屏幕尺寸是java API中的排他性全屏模式。但是,我想在我的游戏中实现SFS(模拟全屏)和窗口模式,以防客户端不支持独占全屏模式。问题是,当我使用窗口式或SFS格式时,在屏幕上移动时图像会抖动。在窗口和SFS中,我将游戏的fps(每秒帧数)设置为60,在独占全屏模式下,我只运行了update和draw方法而没有设置fps的设置,因为从我观察到的情况来看,看起来Java会自动为游戏设置上限fps到60。当我的游戏在独占全屏模式下运行时,图像像丝绸一样平滑移动。但是,在其他屏幕模式下,图像在移动时会抖动。
问题#1:如何使我的游戏在窗口和SFS模式下流畅运行?我尝试了各种尝试,例如将游戏循环放入edt(Event Dispatch Thread),但问题仍然存在。
问题2:为什么在使用独家全屏模式时,我的fps设置为60 fps?我认为这是因为我的显示器速率为60hertz或图形卡显示模式设置为60hertz(1360 x 768,真彩色(32位),60 Hz)。我试图将768 True True Color(32位),75 Hz的显卡显示模式更改为1024,而fps仍然限制为60。
问题3:当我在其他计算机上运行游戏时,例如比我的计算机快的计算机。一台具有144hz刷新率的显示器和一个显示模式高于我的图形卡的图形卡,java在那台机器上是否仍将我的游戏fps限制为60?
我希望有人可以帮助我。
以下是我在“独占全屏”模式下使用的参考:https://docs.oracle.com/javase/tutorial/extra/fullscreen/index.html
这是我的测试代码
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.BufferStrategy;
import java.awt.geom.AffineTransform;
import javax.swing.*;
import javax.imageio.*;
import java.io.File;
public class ScreenTest extends JFrame
{
private static ScreenTest st;
private Graphics2D g2dbf;
//
private Graphics g;
private BufferedImage bgImage;
private Canvas frameCanvas;
//JFrame size
private int frameWidth,frameHeight;
//Identity transform
private AffineTransform identityTrans;
//Object transform
private AffineTransform objTrans;
//
private BufferStrategy bufferS;
//platform's graphics attributes...
GraphicsEnvironment ge;
GraphicsDevice gd;
GraphicsConfiguration gc;
private double posX, posY;
private double velX, velY;
private BufferedImage myImg;
ScreenTest()
{
//JFrame properties
setTitle("Screen Test");
setIgnoreRepaint(true);
setResizable(false);
//setUndecorated(true);
// Get platform's graphics attributes...
ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
gd = ge.getDefaultScreenDevice();
gc = gd.getDefaultConfiguration();
//Set transform to identity transform
identityTrans = new AffineTransform();
//object transform
objTrans = new AffineTransform();
//Exclusive Full Screen Mode
/*
gd.setFullScreenWindow( this );
if( gd.isDisplayChangeSupported() ) {
DisplayMode dm = gd.getDisplayMode();
frameWidth = dm.getWidth();
frameHeight = dm.getHeight();
gd.setDisplayMode( new DisplayMode( frameWidth, frameHeight, dm.getBitDepth(), DisplayMode.REFRESH_RATE_UNKNOWN ));
}
*/
//Simulated full screen mode
//Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//frameWidth = (int)screenSize.getWidth();
//frameHeight = (int)screenSize.getHeight();
//Windowed Mode
frameWidth = 640;
frameHeight = 480;
try { myImg = ImageIO.read(new File("img.png")); }
catch(IOException e){ System.err.println(e); }
posX = frameWidth/2;
posY = frameHeight/2;
velX = 0;
velY = -4;
frameCanvas = new Canvas();
frameCanvas.setIgnoreRepaint( true );
frameCanvas.setSize( frameWidth, frameHeight );
add(frameCanvas);
pack();
setVisible(true);
frameCanvas.createBufferStrategy( 2 );
bufferS = frameCanvas.getBufferStrategy();
//back buffer image
bgImage = gc.createCompatibleImage(frameWidth,frameHeight);
}
void update_Game()
{
updateImg();
}
void drawGraphics()
{
try
{
String str1 = String.format("Velocity X: %.2f",velX);
String str2 = String.format("Velocity Y: %.2f",velY);
g2dbf = bgImage.createGraphics();
g2dbf.setTransform(identityTrans);
//set background
g2dbf.setPaint(Color.BLACK);
g2dbf.fillRect(0,0,frameWidth,frameHeight);
drawImg();
//print some status information
g2dbf.setColor(Color.WHITE);
g2dbf.drawString("Image: " + Math.round(posX) + "," +
Math.round(posY) , 5, 40);
g2dbf.drawString(str1, 5, 60);
g2dbf.drawString(str2, 5, 80);
g = bufferS.getDrawGraphics();
g.drawImage(bgImage,0,0,null);
if( !bufferS.contentsLost() ) bufferS.show();
}
finally
{
if(g != null) g.dispose();
if(g2dbf != null) g2dbf.dispose();
}
}
void drawImg()
{
g2dbf.setTransform(identityTrans);
objTrans.setToIdentity();
objTrans.translate(posX, posY);
g2dbf.drawImage(myImg,objTrans,null);
}
void updateImg()
{
posX += velX;
posY += velY;
if (posX < -70) posX = frameWidth + 10;
else if (posX > frameWidth + 10) posX = -10;
if (posY < -10) posY = frameHeight + 10;
else if (posY > frameHeight + 10) posY = -10;
}
public static void main(String[]args) throws InterruptedException,InvocationTargetException
{
SwingUtilities.invokeAndWait(new Runnable(){
@Override
public void run()
{
st = new ScreenTest();
}
});
int fps = 0;
int frames = 0;
long totalTime = 0,t2 = 0;
long startTime = 0;
long endTime = 0;
final short FRAMES_PER_SECOND = 60;
final int NANOS_PER_SECOND = 1_000_000_000;
final float FRAMES_PER_NANO = NANOS_PER_SECOND / FRAMES_PER_SECOND;
while(true)
{
startTime = System.nanoTime();
if( totalTime > NANOS_PER_SECOND ) {
System.out.println("FPS: " + frames);
totalTime -= NANOS_PER_SECOND;
fps = frames;
frames = 0;
}
//For Simulated Full Screen and Windowed Mode
if(t2 > FRAMES_PER_NANO)
{
st.drawGraphics();
st.update_Game();
frames += 1;
t2 -= FRAMES_PER_NANO;
}
//For Full Screen Exclusive Mode
//st.drawGraphics();
//st.update_Game();
//frames += 1;
Thread.yield();
endTime = System.nanoTime();
totalTime += endTime - startTime;
t2 += endTime - startTime;
}
}
}