Search code examples
javaanimationappletflickerjapplet

FPS Cap Still Causes Flicker


I'm using an FPS cap which to set to 60 fps. I've tested it, and it's working. The problem is that it still causes screen flicker. My monitor is set to 60 fps. I don't know how it's still causing flicker. Here is my code:

package com.bgp.chucknorris;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.net.URL;

public class ChuckNorrisApplet extends Applet implements Runnable {
    private static final long serialVersionUID = 1L;
    Thread thread = null;
    Image title;
    URL base;
    MediaTracker mt;
    String fps = "";

    public void init() {
        thread = new Thread(this);
        thread.start();

        mt = new MediaTracker(this);
        base = getDocumentBase();
        title = getImage(base, "title.png");
        mt.addImage(title, 1);
        try {
            mt.waitForAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public void paint(Graphics g) {
        g.drawImage(title, 0, 0, null);
    }

    public void start() {
        if (thread == null) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void stop() {
        thread = null;
    }

    public void run() {
        int frames = 0;

        double unprocessedSeconds = 0;
        long lastTime = System.nanoTime();
        double secondsPerTick = 1 / 60.0;
        int tickCount = 0;

        requestFocus();

        while (true) {
            long now = System.nanoTime();
            long passedTime = now - lastTime;
            lastTime = now;
            if (passedTime < 0)
                passedTime = 0;
            if (passedTime > 100000000)
                passedTime = 100000000;

            unprocessedSeconds += passedTime / 1000000000.0;

            boolean ticked = false;
            while (unprocessedSeconds > secondsPerTick) {
                unprocessedSeconds -= secondsPerTick;
                ticked = true;

                tickCount++;
                if (tickCount % 60 == 0) {
                    System.out.println(frames + " fps");
                    fps = Integer.toString(frames);
                    lastTime += 1000;
                    frames = 0;
                }
            }

            if (ticked) {
                repaint();
                frames++;
            } else {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

}

Solution

  • Why an Applet (as opposed to a JApplet)? Note that Swing components are double buffered.