public void run() {
        long lastLoopTime = System.nanoTime();
        final int TARGET_FPS = 60;
        final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
        while (!Thread.currentThread().isInterrupted()) {
            long now = System.nanoTime();
            long updateLength = now - lastLoopTime;
            lastLoopTime = now;
            double delta = updateLength / ((double) OPTIMAL_TIME);

            update();
            repaint();
            try {
                long sleepTime = (lastLoopTime - System.nanoTime() + OPTIMAL_TIME) / 1000000;
                if (sleepTime < 0) {
                    sleepTime *= -1;
                }
                Thread.sleep(sleepTime);
            } catch (InterruptedException ex) {
                System.out.println("aaaaa");
            }
        }
    }