@Override
    public void run() {
        // Set up the graphics stuff, double-buffering.
        MediaTracker tracker = new MediaTracker(this);
        BufferedImage image = new BufferedImage(SIZE.width, SIZE.height, BufferedImage.TYPE_INT_RGB);
        tracker.addImage(image, 0);
        Graphics g = image.getGraphics();
        Graphics appletGraphics = screen.getGraphics();

        requestFocus();

        long delta = 0l;
        long timeToSleep = 0l;
        long frameRate = 0l;

        // Game loop.
        while (true) {
            long lastTime = System.nanoTime();

            g.setColor(Color.black);
            g.fillRect(0, 0, SIZE.width, SIZE.height);

            // Update the state (convert to seconds)
            engine.update((float)(delta / 1000000000.0));
            // Render the world
            engine.render(g);

            if (debugFrameRate) {
                g.setColor(Color.red);
                g.drawString("frameRate = " + frameRate, 5, appletGraphics.getFontMetrics().getHeight());
            }

            // Draw the entire results on the screen.
            appletGraphics.drawImage(image, 0, 0, null);

            try {
                tracker.waitForID(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // Lock the frame rate
            delta = System.nanoTime() - lastTime;
            if (delta < 20000000l) {
                try {
                    timeToSleep = (20000000l - delta) / 1000000l;
                    Thread.sleep(timeToSleep);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            else {
                System.out.println("Frame rate too slow");
            }

            if (debugFrameRate) {
                long newFrameRate = 1000000000l / (System.nanoTime() - lastTime);
                frameRate = Math.abs(frameRate - newFrameRate) > 0.5 ? newFrameRate : frameRate;
            }
        }
    }