Search code examples
javaswingwhile-loopgame-loop

Java Game Loop With editable frame cap


I'm trying to create a game loop in java which has a frame cap which can be set while the game is running. The problem im having is I have a render() function and a update() function. Just setting frame cap for both render() and update() means that the speed of the game logic will change when you change the frame cap. Any idea how to have a frame cap which can be set in game while not affecting the speed of the game logic (update())?


Solution

  • As stated in the comments: You can create two threads one of which is responsible for updating and the other is responsible for rendering.

    Try to think of an architecture that suits your needs and your game. You can try something like:

    import java.awt.Dimension;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class Runner extends JPanel {
    
        private static final long serialVersionUID = -5029528072437981456L;
    
        private JFrame window;
        
        private Renderer renderer;
    
        public Runner() {
            setPreferredSize(new Dimension(WindowData.WIDTH, WindowData.HEIGHT));
            setFocusable(true);
            requestFocus();
            
            window = new JFrame(WindowData.TITLE);
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.add(this);
            window.setResizable(false);
            window.pack();
            window.setLocationRelativeTo(null);
            window.setVisible(true);
            
            renderer = new Renderer(getGraphics());
            renderer.start();
        }
        
        public static void main(String[] args) {
            new Runner();
        }
    }
    
    import java.awt.Graphics;
    
    public class Renderer implements Runnable {
        
        private Graphics context;
    
        private Thread thread;
        private boolean running;
    
        public Renderer(Graphics context) {
            this.context = context;
    
            thread = new Thread(this, "Renderer");
            running = false;
        }
    
        public void start() {
            if (running)
                return;
            running = true;
            thread.start();
        }
    
        public void render() {
            context.clearRect(0, 0, WindowData.WIDTH, WindowData.HEIGHT);
            context.fillRect(50, 50, 100, 100);
        }
    
        public void run() {
            while (running) {
                render();
    
                // ** DO YOUR TIME CONTROL HERE ** \\
            }
        }
    }
    

    This code will actually lead to serious performance issues because you are not in control over the rendering ( repaint() ) time.

    But this is just a demo to show you how you can use different threads. Do your own architecture.