package snake;

import javax.swing.JFrame;

public class Game extends JFrame implements Runnable {
  private Thread thread;
  private Screen screen;
  private boolean running = false;
  public static final int UPS = 120;
  private InputHandler inputHandler;

  public Game() {
    super("Snake");

    screen = new Screen();
    add(screen);

    inputHandler = new InputHandler(this);
    addKeyListener(inputHandler);
    addFocusListener(inputHandler);

    pack();
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
  }

  public synchronized void start() {
    if (running) return;
    running = true;
    thread = new Thread(this);
    thread.start();
  }

  public synchronized void stop() {
    if (!running) return;
    running = false;
    try {
      thread.join();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  @Override
  public void run() {
    double secondsPerTick = 1.0 / UPS;

    double nextTime = System.nanoTime() / 1000000000.0;
    double maxTimeDiff = 0.5;
    int skippedFrames = 1;
    int maxSkippedFrames = 5;

    while (running) {
      double curTime = System.nanoTime() / 1000000000.0;
      if ((curTime - nextTime) > maxTimeDiff) nextTime = curTime;
      if (curTime >= nextTime) {
        // do update code, this will get run UPS times a second
        screen.tick(inputHandler.keys);
        // if (screen.gameOver) {
        //   // show a gameover screen and allow restarting
        //   running = false;
        //   break;
        // }
        nextTime += secondsPerTick;
        if ((curTime < nextTime) || (skippedFrames > maxSkippedFrames)) {
          // do rendering code
          screen.render();
          skippedFrames = 1;
        } else {
          ++skippedFrames;
        }
      } else {
        int sleepTime = (int) (1000.0 * (nextTime - curTime));
        if (sleepTime > 0) {
          try {
            Thread.sleep(sleepTime);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  public synchronized void restart() {
    if (running) stop();
    remove(screen);
    screen = new Screen();
    add(screen);
    repaint();
    revalidate();
    start();
  }
}

@@ -213,10 +213,9 @@
 S = 
-12
+6
 0;%0A 
@@ -249,16 +249,41 @@
 Handler;
+%0A  private int tickCount;
 %0A%0A  publ
@@ -652,32 +652,51 @@
 unning) return;%0A
+    tickCount = 0;%0A
     running = tr
@@ -976,24 +976,45 @@
 oid run() %7B%0A
+    int frames = 0;%0A%0A
     double s
@@ -1660,16 +1660,150 @@
 erTick;%0A
+        tickCount++;%0A        if(tickCount %25 UPS == 0) %7B%0A          System.out.println(frames + %22FPS%22);%0A          frames = 0;%0A        %7D%0A
         
@@ -1899,16 +1899,16 @@
 ng code%0A
-
         
@@ -1922,24 +1922,44 @@
 n.render();%0A
+          frames++;%0A
           sk

Print fps in console and half update rate