TrickyTaco11
TrickyTaco11

Reputation: 44

Making a terminal-slide-up effect in python

I'm working on a project where i need a transition effect when needed. I'm running this python project through 'cool-retro-term' a CRT terminal emulator.

I want to make it like the old-school CRT terminal's where the screen smoothly slides up all characters to present the next line or to refresh the screen. Like this: Terminal Slide Effect

NOT THE CHARACTERS BEING PRINTED INDIVIDUALLY, BUT THE SCROLLING OF THE SCREEN.

So far the best I've done is create a function with a bunch of empty prints in a loop:

import time

def slide_up():
    for _ in range(30):
        print("")
        time.sleep(0.03)
    clear()

The clear() is a function that clears the terminal screen:

clear = lambda: os.system('clear')

If anyone knows how I could accomplish this effect I'd greatly appreciate it.

Upvotes: 1

Views: 128

Answers (4)

Hugo Schongin
Hugo Schongin

Reputation: 107

It should be enough to use flush=True as people have said, but I think you would enjoy the bext library for "cool" printing and scrolling effects.

For example you can use this snippet to print text from bottom up, giving a nice old school scrolling vibe:

    import bext
    import time

    x, y = bext.size()

    bext.clear()

    text = '''
    I'm working on a project
    where i need a transition
    effect when needed.
    I'm running this python project
    through 'cool-retro-term' a CRT terminal em
    '''

    text = text.splitlines()
    length = len(text)

    for i in range(y):
            bext.goto(0,y-i-1)
            print(text[-(i%length)])
            time.sleep(0.4)

Upvotes: 0

DeepThought42
DeepThought42

Reputation: 185

Your code is correct, except for one thing: you need to add flush=True to your print calls. Also, you don’t need to have empty strings in the print calls, print() works with no args. I have added some convenient arguments for more customisation, but they all have default values so you can call it with no arguments. I also made it smooth scroll the entire length of the display with os.get_terminal_size. Documentation here.

from time import sleep
from os import system, get_terminal_size

clear = lambda: system('clear')

def slide_up(n:int=get_terminal_size().lines, sleep_: float=0.05):
    for _ in range(n):
        print("")
        sleep(sleep_)
    clear()

If you don’t put flush=True in, on some systems (or even just sometimes) it won’t do the effect you’re talking about.

Or you could use curses, but that tends to over-complicate things.

Upvotes: 2

Markus Hirsimäki
Markus Hirsimäki

Reputation: 753

To directly control the screen scrolling, you need something like VT100 control codes. Try this demo. It uses different VT100 control codes to hide/show the cursor and scroll up/down.

import time

def smooth_scroll(lines=10, delay=0.1):
    """
    Smoothly scrolls the terminal up or down a specified number of lines with a delay using VT100 escape codes.

    Args:
    lines (int): The number of lines to scroll. Positive values scroll up, negative values scroll down.
    delay (float): The delay in seconds between each line scroll.
    """
    print("\033[?25l", end="", flush=True)  # Hide the cursor
    
    if lines > 0:
        for _ in range(lines):
            print("\033[1S", end="", flush=True)  # Scroll up one line
            time.sleep(delay)
    else:
        for _ in range(abs(lines)):
            print("\033[1T", end="", flush=True)  # Scroll down one line
            time.sleep(delay)
            
    print("\033[?25h", end="", flush=True)  # Show the cursor

# Example usage
smooth_scroll(lines=20, delay=0.2)  # Scrolls up 20 lines
smooth_scroll(lines=-10, delay=0.2)  # Scrolls down 10 lines

You have to be using a terminal that supports VT100 control codes.

Upvotes: 1

Markus Hirsimäki
Markus Hirsimäki

Reputation: 753

Terminal emulators scroll text automatically as you print newlines. Maybe try something like this?

import time

def smooth_print(text, delay=0.1):
    """Prints the given text smoothly, character by character, with a specified delay.

    Args:
        text (str): The text to print.
        delay (float): The delay in seconds between each character.
    """
    for char in text + "\n":  # Manually add newline because is set to ""
        print(char, end="", flush=True)
        time.sleep(delay)

smooth_print("Hello, world!", 0.1)  # Example

Upvotes: 1

Related Questions