我正在制作简单的2D游戏。我有一个游戏循环,在游戏循环中我有一个更新 方法。每当循环时,我都会通过向xPos添加1来进行移动。这意味着如果你的fps很慢,那么一切都会以慢动作进行,如果你的fps很高,一切都会移动 非常快。
这是我的代码:
long fpsTimer;
int frames;
public void run(){
running = true;
fpsTimer = System.nanoTime();
while(running){
render();
update();
try{
Thread.sleep(6);
}catch(InterruptedException e){}
frames++;
if(System.nanoTime() >= fpsTimer+1000000000){
System.out.println(frames+" fps");
frames = 0;
fpsTimer = System.nanoTime();
}
}
}
所有代码
import java.awt.*;
import java.awt.image.*;
import javax.swing.JFrame;
import java.awt.event.*;
public class Game extends Canvas implements Runnable{
public static final int WIDTH = 800;
public static final int HEIGHT = 300;
public JFrame f;
private String title = "Untitled Test";
private Image image;
private Sprite player;
public Game(){
player = new Sprite(100, 100);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setMaximumSize(new Dimension(WIDTH, HEIGHT));
setMinimumSize(new Dimension(WIDTH, HEIGHT));
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
player.keyPressed(e.getKeyCode());
}
public void keyReleased(KeyEvent e){
player.keyReleased(e.getKeyCode());
}
});
}
public static void main(String[] args){
Game g = new Game();
g.f = new JFrame(g.title);
g.f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
g.f.add(g);
g.f.setResizable(false);
g.f.pack();
g.f.setLocationRelativeTo(null);
Thread gameLoop = new Thread(g);
gameLoop.start();
g.f.setVisible(true);
}
private void render(){
BufferStrategy bs = getBufferStrategy();
if(bs==null){
createBufferStrategy(3);
return;
}
image = createImage(WIDTH, HEIGHT);
Graphics g = image.getGraphics();
player.draw(g);
g.dispose();
Graphics bsg = bs.getDrawGraphics();
bsg.drawImage(image, 0, 0, WIDTH, HEIGHT, null);
bsg.dispose();
bs.show();
}
private void update(){
player.move();
}
long fpsTime;
int frames;
public void run(){
fpsTime = System.nanoTime();
while(true){
render();
update();
try{
Thread.sleep(6);
}catch(InterruptedException e){}
frames++;
if(System.nanoTime() >= fpsTime+1000000000){
System.out.println(frames+" fps");
frames = 0;
fpsTime = System.nanoTime();
}
}
}
}
答案 0 :(得分:2)
首先你不应该有一个恒定的睡眠时间。相反,应该动态计算该值。也许它更容易使用Timer#scheduleAtFixedRate(...)
因为这已经为你解决了这个问题。
然后,每次迭代6毫秒似乎太少了。每秒60帧是理想的(如果你只有30帧,我认为也可以),所以16毫秒就足够了(或者30帧每秒30左右)。 (请注意,屏幕的刷新率是上限 - 它应该是大约60赫兹 - 更多没有意义。)
第三考虑动态计算对象的移动。您没有添加到坐标的恒定增量,而应该更好地使用某种“移动功能”。根据当前时间计算坐标。
假设您想要以每秒 pps 像素的恒定速度沿x轴移动对象。然后该对象的x坐标函数为:
x(t) := x0 + (t - t0) * pps / 1000
(t
是自ms开始以来经过的时间,x0
是对象首次出现时的初始x坐标,t0
是对象的开始时间看来,pps
是对象每秒应移动的像素数。)
这使您的物体以相同的速度移动 - 无论您有什么帧率。
请注意,如果您的对象应对用户输入或其他事件(如冲突等)做出反应,则此方法会变得更加复杂。