我正在开发一款小游戏时遇到一些问题。虽然我使用双缓冲并且能够摆脱闪烁,但运动仍然看起来有点紧张而且不流畅。 我知道这可能是由于增加了大步和/或低帧速率的运动造成的,但我仍然使用1和50+ fps的增量来解决同样的问题。这有点难以解释,但精灵奇怪地移动(正确,但不是流动)
如果有人能指出我正确的方向,我将不胜感激。
public class Gameplay extends javax.swing.JPanel {
GUI gui;
Canvas canvas = new Canvas();
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
BufferedImage bi;
BufferStrategy buffer;
public Gameplay(GUI gui) {
this.gui = gui;
initComponents();
}
// Used to start the gameplay. Called by GUI
public void start() {
new RefreshScreen().start();
}
// ==============================================================================================
// DOUBLE BUFFER AND PAINTING ===================================================================
// ==============================================================================================
Date date = new Date(); // time
int lastSecond = 0; // seconds controll - for FPS calculation
int fpsCount = 0; // Count frames rendered
int showFps = 0; // The total FPS text that will appear on screen
int MAX_FPS = 30; // targeted Max FPS
int MIN_FPS = 24; // targeted Min FPS
int sleepTimeBetweenRefresh = 20; // Delay before new refresh
Color fpsColor = Color.yellow; // color of the FPS information on screen
String fpsInfo = ""; // Aditional info on FPS (increasing, decreasing, etc)
class RefreshScreen extends Thread {
public void run() {
Graphics graphics = null;
Graphics2D bufferGraphics = null;
add(canvas, BorderLayout.CENTER);
canvas.setIgnoreRepaint(true);
canvas.setVisible(true);
canvas.setSize(gui.getWidth(), gui.getHeight());
canvas.createBufferStrategy(2);
buffer = canvas.getBufferStrategy();
bi = gc.createCompatibleImage(gui.getWidth(), gui.getHeight());
bufferGraphics = bi.createGraphics();
while (true) {
try {
//FrameRate count
date = null;
date = new Date();
if (lastSecond != date.getSeconds()) {
lastSecond = date.getSeconds();
showFps = fpsCount;
fpsCount = 0;
if (showFps > MAX_FPS) {
sleepTimeBetweenRefresh++;
fpsInfo = "(--)";
fpsColor = Color.blue;
}
if ((showFps < MIN_FPS) && (sleepTimeBetweenRefresh > 5)) {
sleepTimeBetweenRefresh--;
fpsInfo = "(++)";
}
if (showFps < MIN_FPS) {
fpsColor = Color.red;
}
if ((showFps > MIN_FPS) && (showFps <= MAX_FPS)) {
fpsColor = Color.green;
fpsInfo = "(ok)";
}
}
fpsCount++;
//Clear canvas =============================
bufferGraphics.setColor(Color.black);
bufferGraphics.clearRect(0, 0, gui.getWidth(), gui.getHeight());
//FPS =============================
bufferGraphics.setColor(fpsColor);
bufferGraphics.drawString("FPS: " + showFps, 3, 15);
bufferGraphics.setColor(Color.black);
//SPRITES =============================
try {
for (int count = 0; count < Sprites.getSprites().size(); count++) {
bufferGraphics.drawImage(Sprites.getSprite(count).getImage(), Sprites.getSprite(count).getX(), Sprites.getSprite(count).getY(), null);
}
} catch (Exception e) { }
//HERO =============================
try {
bufferGraphics.drawImage(Sprites.getHero().getImage(), Sprites.getHero().getX(), Sprites.getHero().getY(), null);
} catch (Exception e) { }
// PAINT BUFFER =================================
try {
graphics = buffer.getDrawGraphics();
graphics.drawImage(bi, 0, 0, null);
if (!buffer.contentsLost()) {
buffer.show();
}
} catch (Exception e) { }
// SLEEP =================================
sleep(sleepTimeBetweenRefresh);
} catch (Exception e) { }
}//while
}//run
}//inner class
我还想指出精灵的X和Y正在被处理,以便它不会正确然后向下 - 例如 - 当它应该是对角线时。我不认为这是问题,因为即使在直线上也会出现问题。
答案 0 :(得分:0)
您可以尝试计算绘制所有内容所需的时间,然后从睡眠时间中减去它。
long beforeTime = System.currentTimeMillis();
// do all drawing
sleepTimeBetweenRefresh -= System.currentTimeMillis() - beforeTime;
if(sleepTimeBetweenRefresh < 0) sleepTimeBetweenRefresh = 0;
这有助于确保您的线程每50毫秒(或任何sleepTimeBetweenRefresh)发射。假设你想要它发射50ms,你的绘图需要10ms。在代码运行一次之后没有上面的代码,你实际上会在最后一次绘制后绘制60ms,因为你画了10并且睡了50个。通过减去绘制组件所花费的时间,你可以保持你的FPS稳定。