Got hit with a nasty noise allergy, making me snot and cough nonstop. Much more bearable now.
Static items can only provide so much immersion in a game environment, even if they have projected depth and scale. By giving them unique animations, we can create a more interactive Pygame environment, thereby enhancing immersion as well. Furthermore, building a class that handles different objects will provide long-term ease in creating different classes of game objects – be it prop or characters.
Subclasses enable developers to inherit the properties and behavior of another class, allowing them to build upon and extend its functionality while reusing its existing code. This promotes code reuse, reduces duplication, and simplifies file complexity.
The tutorial's animation method uses two new modules: os (operating system) and deque (double-ended queue) from the collections library. The former enables program-to-local storage interactions with our Pygame to load game resources form, while the former provides a specialized list for animating game interactables.
Underneath, the rsplit() function splits a string into a list, starting from the right. The path variable now refers to the individual images in our animation folders.
To set up our object's looping animation, we can build a double-ended queue (deque). Wait, what even is a queue in programming?
See, a queue is a linear data structure that follows the First-In-First-Out (FIFO) principle, meaning the first element added to the queue will be the first one to be removed. Imagine a literal queue to a market stall, where the first person to enter said queue will be first to leave after reaching and completing their business with the stall (assuming they do not leave early).
As for a deque, they are queues that can have their elements removed from both start and end. Think the common subway system: the trains' doors act as both entrances and exits for passengers.
In the scenario of sprite animation, a deque:
Supports efficient rotation and shifting of elements, meaning you can easily move the next sprite to the start of the queue without needing to reorder the entire collection.
Allows for fast addition or removal sprites from the queue, without (again) needing to reorder the entire collection.
Uses less memory than a list, because it only needs to store the pointers to the previous and next elements in the queue, rather than the entire list.
Return to the class initializer and add the code below. The first line builds the timer that tracks the live animation time of an animated sprite, and the second line builds the trigger that calls for the progression of one animation image to the second when True.
Upon initialization, the animation trigger should start at False. Otherwise, the program would run each animation to the end faster than a human can blink. Another governing variable for animations is time, which we will shortly elaborate upon.
If the current frame's time – deducted by the last frame's time – is greater than the frame time limit, the last frame's time becomes equal to current frame's time, the animation trigger becomes True, and swaps to the next animation frame.
Rotating a deque with a negative number moves the rightmost item to the leftmost spot in the list, and the animate() method always displays the first item in the image list, creating the illusion of animation.
Make sure the methods are chronologically ordered in dependencies.
Import the class into your main file methods… and watch your animated sprite further immerse your game environment.
The tutorial's last iteration of sprite classes rigidly fetches one image or directory's worth of sprites. To increase the program's developmental flexibility, the same tutorial proposes building a new file to handle all sprite classes at once, without needing to add clutter to the main file.
At the bottom of this class's initializer, the add_sprite method can be run multiple times – in different available parameters – to insert multiple instances of sprite objects into the sprite list.
To further demonstrate how this list works, I created a new set of animated sprites in a different directory.
To explain why the for loop below is run in a pair of list brackets, we will talk about list comprehension. By using this feature, for loops can be written in a single line rather than two lines at minimum.
Think of it like a difference in sentence structure: instead of saying "do this for each person", you could say "for each person, do this". Space is saved without loss of information.
A static world makes for a stale experience.