Share your repls and programming experiences

← Back to all posts
[OPTIMIZED] 🐍🎞️🎬 Python Animation! 🐍🎞️🎬
h
Pankak (49)

Python Animation But Optimized

TL;DR

Added buffering to @JBYT27's Python Animation Tutorial

Comparsion between the two:

Mine:
https://repl.it/@Pankak/ConsoleAnimationOptimized#main.py

Original: https://repl.it/@Pankak/AnimationMakingFork#main.py


I came across this post today, and the tutorial was quite nice, but the flickering bothered me, so I decided to attempt to optimize it.

DISCLAIMER: I am not hating on other users, I'm doing this purely for a fun challenge


I'm not going to use additional libraries in the spirit of the challenge, so in order to approach this, I will need to use escape sequences.

import time

def buff_append(buffer, data):
	buffer = buffer + data

def buff_fflush(buffer):
	print(buffer)
	buffer = ""

def render():
	buffer = ""

We will append everythig into our buffer. We can use escape sequences to clear the screen, move the cursor, etc.

import time

def buff_append(buffer, data):
	buffer = buffer + data
	return buffer

def buff_clear(buffer):
	buffer = buffer + "\x1b[2J" + "\x1b[H"
	return buffer

def buff_fflush(buffer):
	print(buffer)
	buffer = ""
	return buffer

def render():
	buffer = ""

\x1b[2J clears the screen and \x1b[H positions the cursor to the beginning.

frames = [
	"o/",
	"o\\"
]

I'll add in some very simple frames for now which we can use to test our program.

We can initiate a simple loop which will loop through each frame and display it using our current rendering engine.

def next_frame(frame):
	frame = (frame + 1) % len(frames)
	return frame

def render():
	buffer = ""
	frame = 0
	while True:
		buffer = buff_clear(buffer)
		buffer = buff_append(buffer, frames[frame])
		buffer = buff_fflush(buffer)

		time.sleep(0.1)

		frame = next_frame(frame)

render()

Let's try a larger animation:

frames = [
	"", "", "", ""
]

def init_frames():
	for i in range(0, 4):
		for j in range(0, 30):
			if i == 0 or i == 2:
				frames[i] = frames[i] + "||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n"
			if i == 1:
				frames[i] = frames[i] + "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n"
			if i == 3:
				frames[i] = frames[i] + "////////////////////////////////////////////////////////\n"

Now the console should run pretty smoothly, but I'll implement a final optimization

def buff_fflush(buffer):
	buffer = "\x1b[?25l" + buffer + "\x1b[?25h"
	
	temp = buffer.split("\n")
	buffer = ""
	for s in temp:
		s = "\x1b[K" + s + "\n"
		buffer = buffer + s
	
	sys.stdout.write(buffer)
	return ""

def render():
	buffer = ""
	frame = 0
	while True:
		buffer = buff_append(buffer, frames[frame])
		buffer = buff_fflush(buffer)

		time.sleep(0.1)

		frame = next_frame(frame)

init_frames()
render()

\x1b[?25l and \x1b[?25h will show and hide the cursor so that we don't see the cursor flying around the screen in case printing gets slow. I know I'm using sys.stdout.write but technically it's not an external library so I'm going to allow it.

Now essentially with \x1b[K I'm clearing each line while I draw it.


Closing

What I did here was essentially very basic I/O buffering. I've never really written Python before this so it was quite a new experience.

Final Program: https://repl.it/@Pankak/ConsoleAnimationOptimized#main.py

Now for good measure, I forked @JBYT27's exact code and ran the same animation, the difference is quite apparent:

https://repl.it/@Pankak/AnimationMakingFork#main.py


Credit to @JBYT27 for the original post

Comments
hotnewtop
Brendan23 (166)

cool. suggestion: in future repls you can make them into pictures instead of lines. very cool tho.

Pankak (49)

@Brendan23 I just made them lines for demonstrational purposes (they can be animated and fill up the entire space to prove the optimization works)

Brendan23 (166)

@Pankak oh ok cool. did you create this or did you see it somewhere else?

Pankak (49)

@Brendan23 I created this from scratch

Brendan23 (166)

@Pankak oh nice! btw: I upvoted.

JBloves27 (1903)

Nice job! Much better actually! ;)