[OPTIMIZED] 🐍🎞️🎬 Python Animation! 🐍🎞️🎬
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
Nice job! Much better actually! ;)
cool. suggestion: in future repls you can make them into pictures instead of lines. very cool tho.
@Brendan23 I just made them lines for demonstrational purposes (they can be animated and fill up the entire space to prove the optimization works)
@Pankak oh ok cool. did you create this or did you see it somewhere else?
@Brendan23 I created this from scratch
@Pankak oh nice! btw: I upvoted.