Java Main Game Loop

安稳与你 提交于 2019-11-26 10:59:20

问题


I am writing a game loop, I found the code in the example below here. I have also looked at other ways to do a game loop, such as from this article. I couldn\'t get any of those ones working though. So I kept with the one from the first link.

What I would like to know:

  • Is the way I wrote my game loop a good way to do this?
    • Any suggestions?
  • Should I be using Thread.sleep(); in my game loop?

Here is my current code:

public void run(){
    long lastLoopTime = System.nanoTime();
    final int TARGET_FPS = 60;
    final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
    long lastFpsTime = 0;
    while(true){
        long now = System.nanoTime();
        long updateLength = now - lastLoopTime;
        lastLoopTime = now;
        double delta = updateLength / ((double)OPTIMAL_TIME);

        lastFpsTime += updateLength;
        if(lastFpsTime >= 1000000000){
            lastFpsTime = 0;
        }

        this.updateGame(delta);

        this.repaint();

        try{
            Room.gameTime = (lastLoopTime - System.nanoTime() + OPTIMAL_TIME) / 1000000;
            System.out.println(Room.gameTime);
            Thread.sleep(Room.gameTime);
        }catch(Exception e){
        }
    }

回答1:


Eventually you'll want to move to something like LWJGL, but let me stress, keep doing what you're doing here for now. It will teach you fundamentals.

Good job on your loop. Looks nice, let me offer a few pointers:

  • Repaint will not render the screen immediately. It tells the RepaintManager to render when its ready. Use invalidate paintImmediately instead. paintImmediately will block execution until the component has been redrawn so you can measure rendering time.

  • Thread.sleep typically has a few milliseconds drift. You should be using it to keep your loop from using too much CPU, but make sure you understand if you sleep 10 milliseconds you might sleep 5 milliseconds or you might sleep 20.

  • Lastly:

    double delta = updateLength / ((double)OPTIMAL_TIME);
    

    If updateLength is less than OPTIMAL_TIME, don't call update. In other words, if delta is less than one, don't update. This tutorial explains why better than I ever could.




回答2:


Overall, it is a good loop, but there are a few missing aspects to what I have found in experience to be the best loop.

You will eventually want to move to LWJGL or some other java game API, but for now, learn the basics of how game-loops work, and what best suits your needs.

  • Firstly, in answer to one of your points, no. You will do better staying away from

    Thread.sleep()

    this can stray from the real amount of time you set it to sleep.
    e.g. if you set it to sleep for 10 milliseconds, it could sleep the program for 5 to 20 milliseconds.

  • The second problem I cam immediately see is that you do not have any way to stop the game-loop for a custom stop() method. Try

    boolean running = true;
    while (running) {
    // Your Code Here //
    }

  • Thirdly, you may want to consider changing how you use your delta variable. The way in the code below may be a better use and construction for you.

    This is an example of my game-loop that I use in my programs:

    @Override
    public void run() {
    
    long initialTime = System.nanoTime();
    final double timeU = 1000000000 / UPS;
    final double timeF = 1000000000 / FPS;
    double deltaU = 0, deltaF = 0;
    int frames = 0, ticks = 0;
    long timer = System.currentTimeMillis();
    
        while (running) {
    
            long currentTime = System.nanoTime();
            deltaU += (currentTime - initialTime) / timeU;
            deltaF += (currentTime - initialTime) / timeF;
            initialTime = currentTime;
    
            if (deltaU >= 1) {
                getInput();
                update();
                ticks++;
                deltaU--;
            }
    
            if (deltaF >= 1) {
                render();
                frames++;
                deltaF--;
            }
    
            if (System.currentTimeMillis() - timer > 1000) {
                if (RENDER_TIME) {
                    System.out.println(String.format("UPS: %s, FPS: %s", ticks, frames));
                }
                frames = 0;
                ticks = 0;
                timer += 1000;
            }
        }
    }
    


来源:https://stackoverflow.com/questions/18283199/java-main-game-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!