Here's a simple FPS counter written in pure Java (Swing). This example demonstrates the core idea behind FPS counting without using any game engine.
import javax.swing.*;
import java.awt.*;
public class FPSCounter extends JPanel implements Runnable {
private Thread gameThread;
private boolean running = true;
// FPS Variables
private int frames = 0;
private int fps = 0;
private long lastTime = System.currentTimeMillis();
public FPSCounter() {
setPreferredSize(new Dimension(800, 600));
setBackground(Color.BLACK);
gameThread = new Thread(this);
gameThread.start();
}
@Override
public void run() {
while (running) {
// Update Game Logic
update();
// Draw Screen
repaint();
// Count FPS
frames++;
if (System.currentTimeMillis() - lastTime >= 1000) {
fps = frames;
frames = 0;
lastTime = System.currentTimeMillis();
}
try {
Thread.sleep(2); // Simulate game workload
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void update() {
// Game logic goes here
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.setFont(new Font("Arial", Font.BOLD, 24));
g.drawString("FPS : " + fps, 20, 40);
}
public static void main(String[] args) {
JFrame frame = new JFrame("FPS Counter");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FPSCounter());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
How It Works
Step 1: Create a Frame Counter
This counts how many frames have been rendered.
Step 2: Store the Start Time
private long lastTime = System.currentTimeMillis();
This records when we started counting.
Step 3: Every Loop Counts One Frame
Every time the game loop runs and draws the screen, one frame has been rendered.
Step 4: Check if One Second Has Passed
if (System.currentTimeMillis() - lastTime >= 1000)
If at least 1000 milliseconds (1 second) have elapsed, it's time to calculate the FPS.
Step 5: Save the FPS
The number of frames rendered during the last second becomes the current FPS.
Step 6: Reset for the Next Second
frames = 0;
lastTime = System.currentTimeMillis();
Reset the counter and start measuring the next second.
Visual Explanation
Time = 0 sec
Frames = 0
↓
Frame 1
Frames = 1
↓
Frame 2
Frames = 2
↓
Frame 3
Frames = 3
↓
...
↓
Frame 250
↓
1 Second Passed
FPS = 250
↓
Reset
Frames = 0
↓
Start Counting Again
Better Version (Professional Game Loop)
Professional game engines use System.nanoTime() because it provides much higher precision than System.currentTimeMillis().
long lastTime = System.nanoTime();
double timer = System.currentTimeMillis();
int frames = 0;
while (running) {
update();
render();
frames++;
if (System.currentTimeMillis() - timer >= 1000) {
System.out.println("FPS : " + frames);
frames = 0;
timer += 1000;
}
}
This approach is closer to what you'll see in custom Java game engines and tutorials. If you're planning a Game Engine from Scratch series on Bit by Bit Dev, this is the style of game loop you'll eventually want to build on.