@Override
    @SuppressWarnings({"SleepWhileInLoop", "CallToThreadYield"})
    public void run() {
        long b, a, beforeTime, afterTime, timeDiff, sleepTime;
        long overSleepTime = 0L;
        int noDelays = 0;
        long excess = 0L;

        beforeTime = System.nanoTime();

        isRunning = true;

        while (isRunning) {
            //b = System.nanoTime();
            gameUpdate();
            //a = System.nanoTime();
            //System.out.println("Update: " + ((a - b) / 1000000));
            //b = System.nanoTime();
            //if (((a - b) / 1000000) > 100) {
            //    System.exit(0);
            //}
            gameRender();
            paintScreen();
            // a = System.nanoTime();
            //System.out.println("Draw: " + ((a - b) / 1000000));
            //System.out.println("----------");

            afterTime = System.nanoTime();
            timeDiff = afterTime - beforeTime;
            sleepTime = (period - timeDiff) - overSleepTime;

            if (sleepTime > 0) {
                try {
                    Thread.sleep(sleepTime / 1000000L);  // nano -> ms
                } catch (InterruptedException ex) {
                }
                overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
            } else {    // sleepTime <= 0; the frame took longer than the period
                excess -= sleepTime;
                overSleepTime = 0L;

                if (++noDelays >= NO_DELAYS_PER_YIELD) {
                    Thread.yield();   // give another thread a chance to run
                    noDelays = 0;
                }
            }

            beforeTime = System.nanoTime();

            int skips = 0;
            while ((excess > period) && (skips < MAX_FRAME_SKIPS)) {
                excess -= period;
                gameUpdate();
                skips++;
            }
        }
        System.exit(0);
    }