非常高的CPU使用率,具有简单的Java游戏循环

非常高的CPU使用率,具有简单的Java游戏循环,java,cpu,Java,Cpu,我一直在学习游戏设计的原则,并在许多教程的帮助下用Java制作了这个游戏循环。它现在所做的只是在JFrame上渲染草平铺: public class Game extends JPanel implements Runnable { String title; int height; int width; boolean ps; private int ticks; private JPanel p; private BufferStrategy bs; private Graphic

我一直在学习游戏设计的原则,并在许多教程的帮助下用Java制作了这个游戏循环。它现在所做的只是在JFrame上渲染草平铺:

public class Game extends JPanel implements Runnable {

String title;
int height;
int width;

boolean ps;

private int ticks;  
private JPanel p;
private BufferStrategy bs;
private Graphics g;
private boolean running = false;
private Thread thread;  
private Frame frame;
private KeyHandler keyHandler;

public Game(String title, int width, int height){
    this.width = width;
    this.height = height;
    this.title = title;
    keyHandler = new KeyHandler();
}

private void init() {
    TileHandler.init();
    frame = new Frame(title, height, width);
    frame.getFrame().addKeyListener(keyHandler);
}

private void tick() {
    // KeyHandler.tick();

    // updates game logic       
}

private void render() {
    render(g);      
}

private void render (Graphics g) {  
    bs = frame.getCanvas().getBufferStrategy();
    if(bs == null){
        frame.getCanvas().createBufferStrategy(3);
        return;
    }
    g = bs.getDrawGraphics();
    g.clearRect(0, 0, width, height);   

    g.drawImage(TileHandler.grass, keyHandler.getPlayerX(), 
    keyHandler.getPlayerY(), null);

    bs.show();
    g.dispose();
}

@Override
public void run() {

    int x = 4;
    init();
    int fps = 60;  // target
    double tickTime = 1000000000 / fps; // time per 1 frame
    double delta = 0;   
    long timer = 0;

    long startTime = System.nanoTime();
    long endTime;

    while (x == 4) {
        endTime = System.nanoTime();
        delta += (endTime - startTime) / tickTime;
        timer += endTime - startTime;
        startTime = endTime;

        if (delta >= 1) {
            ticks++;
            render();
            delta--;
        }
        if(timer >= 1000000000){
            ticks = 0;
            timer = 0;
        }
    }
}

public int getTicks() {
    return ticks;
}

public synchronized void startThread() {
    // Start the thread
    if (!running) {             // if not already 

        running, you can begin
        running = true;
        thread = new Thread(this); //Run THIS class on a 

        new thread
        thread.start();
    }
    else {  // safety measure
        return;
    }
}

public void stopThread() {
    if (!running) {
        return;
    }
    running = false;
    try {
        thread.join(); //Method stops the thread
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}
}

它工作得很好,我可以让它以稳定的每秒60帧的速度运行,唯一的问题是它占用了太多的CPU。平均而言,它使用了大约50%的CPU,并降低了我电脑的其他部分的速度——Minecraft在我的笔记本电脑上也使用了同样的速度!我知道问题在于上面代码中的游戏循环


所以我只是想了解是什么导致了这一切。我确实尝试使用探查器,但仍然无法找出问题的原因。

请给出最简单的答案:您的循环正在以CPU能够处理的速度运行。我假设您有一个具有两个内核的CPU,因此主循环线程正在使用它可以获得的每一点计算能力,以尽可能快地运行循环,从而阻塞两个内核中的一个(50%)

一种解决方案是计算每次迭代所需的时间,并在下一次迭代开始之前睡眠一段时间。下面是一个伪代码:

while(running) {
    long startTime = getTime();

    update();
    render();

    long endTime = getTime();
    long elapsedTime = endTime - startTime;
    Thread.sleep(TARGET_FRAME_TIME - elapsedTime); //sleep to yield unneeded CPU usage
}
此外,如果您没有使用像LWJGL或JOGL这样的OpenGL库,那么swing的性能也不会很好。我不知道你的游戏会是什么,但60fps可能是swing的上限


我建议您学习JavaFX for games,因为它使用硬件加速进行渲染,并且对于相对复杂的应用程序可以处理120fps+的速度。它还为游戏循环设计提供和类。

循环不断运行,以查看是否需要调用render()。这叫做轮询,通常是个坏主意。试着用一个定时器来调用render(),我也建议你研究一下JavaFX,因为它使用硬件加速,更适合游戏开发。它还附带了像和这样的类,使gameloop管理变得非常简单。+1,但是Swing有时仍然会阻止渲染过程,因为这种情况不再发生。谢谢大家的建议,我比以前更了解现在发生的事情。看来2D游戏库是前进的方向!如果您想继续使用标准库,请查看JavaFX。它是完美的2D游戏,当你不想去第三方。(我可能是个小粉丝)