Search code examples
javatextconsolelag

(Java) Printing text letter by letter in console- ft. Lag


so I'm making a game that uses nothing but the console in my java IDE, but I have a problem using delays. My goal is to create a method that when taken a text passed though the parameters, it prints it letter by letter with a delay of 50. (Kind of like the text in the Pokemon series, how it scrolls though each letter).

The problem I have is lag. I'm running an amd fx-8350 cpu (4GHz, 4 cores+4 virtual cores). Whenever I change the delay amount to anything around and under 100 milliseconds, the console prints half a word, then a little bit of the other half, then half the sentence, then maybe a character, etc.

I've tried this code here (it works, but with lag):

public void scroll(String text){
    int delay = 50;
    ActionListener action = new ActionListener()
    {
        int counter = text.length();
        @Override
        public void actionPerformed(ActionEvent event)
        {
            if(counter == 0)
            {
                timer.stop();
            }
            else
            {
                System.out.print(text.substring(text.length() - counter, ((text.length() - counter) + 1)));
                counter--;
            }
        }
    };
    timer = new Timer(delay, action);
    timer.start();

}//end scroll

And this code as well (also works, with same amount of lag):

public void scroll(String text){
    for(int i = 0; i <= text.length(); i++){
       try {
               Thread.sleep(1000);
            }catch(InterruptedException ex){
               Thread.currentThread().interrupt();
            }
       System.out.print(text.substring(i, i + 1));
    }
}//end scroll

In conclusion, I'm guessing that the computer is doing more than "delaying" when I try to delay the thread. Any idea's?

-Thanks, Eric


Solution

  • Firstly, some random notes about your code. This is wrong:

    for(int i = 0; i <= text.length(); i++){
    

    Whether you are iterating through a string, array, list, or whatever, the usual pattern is always

    i = 0; i < length; i++
    

    i.e. by using <= you are getting an exception. This is unneeded:

    text.substring(i, i + 1)
    

    and it looks even worse in the first example. You can use text.charAr(i).


    I tried this code as an alternative:

    for(int i = 0; i < text.length(); i++) {
        long start = System.currentTimeMillis();
        while (System.currentTimeMillis() - start < 50) {
    
        }
        System.out.print(text.charAt(i));
    }
    

    It still didn't work in IntelliJ. However it and your code work fine in the terminal, so I think IntelliJ just doesn't like printing immediately. flush makes no difference but its documentation in OutputStream hints at what might be happening:

    If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive.

    So again, I think the IDE is the problem and it's out of the control of your code.