@Override
    public void run() {
        double unprocessedTicks = 0.0;
        double nsPerTick = 1000000000.0/tps;
        
        double unrenderedFrames = 0.0;
        double nsPerFrame = 1000000000.0/fps;

        long lastTime = System.nanoTime();
        
        long lastFpsTime = System.currentTimeMillis();
        int frameCount = 0;
        int tickCount = 0;
        
        while(running){
            long now = System.nanoTime();
            unprocessedTicks += (now - lastTime) / nsPerTick;
            unrenderedFrames += (now - lastTime) / nsPerFrame;
            lastTime = now;
            
            if(unprocessedTicks >= 1.0 || !limitTPS){
                tick();
                unprocessedTicks -= 1.0;
                tickCount++;
            }
            
            if(unrenderedFrames >= 1.0 || !limitFPS){
                render();
                unrenderedFrames -= 1.0;
                frameCount++;
            }
            
            if(printFPS && System.currentTimeMillis() - lastFpsTime > 1000){
                System.out.println(frameCount + " fps; " + tickCount + " tps");
                frameCount = 0;
                tickCount = 0;
                lastFpsTime = System.currentTimeMillis();
            }
        }
    }