Dynamic Sprite
English | Português | Español | 日本語 |
A Dynamic Sprite is a Sprite that loads its own graphics into the VRAM (Video Memory of the Super Nintendo). This allows the sprite to use an unlimited amount of poses (animation frames) and to have a greater amount of enemy variety in a level.
It could also be considered a dynamic sprite if it loads other resources such as its color palette or tilemaps, in these cases it is usually differentiated using the term "Dynamic Palettes", "Dynamic Tilemaps", "Dynamic Background", etc.
Why is a dynamic sprite system necessary?
The VRAM of the SNES is very limited, allowing only 64 kb of memory to be used for both level graphics, tilemaps and sprite graphics. If we consider the space that is only destined for sprites (Sprite Pages), in general games do not use more than 16 kb of VRAM for sprites, which is equivalent to a space of 128x256 that is divided between all enemies, characters, player or any entity made with sprites.
Also considering that sprites can only use 8 color palettes, a dynamic sprite system that includes dynamic color palettes is also necessary, since, with only 8 color palettes the amount of different enemies you can use in a level is reduced a lot.
To solve these problems what is done is to have a system of dynamic sprites that allows to change in real time both graphics and color palettes and thus not to have all these limitations at the moment of working with sprites.
Practical Applications
Dynamic sprites have several applications, the most common is to use them for the player of a game, although in reality they could be used for enemies, bosses, decoration, etc.
Here is a list of utilities of a good dynamic sprite system:
- Decrease level loading time: Since each sprite loads its own graphics, it is not necessary that these are loaded during level loading.
- If you add a dynamic color palette system, you can use any dynamic sprite in any level.
- Being able to have Sprites with multiple animations and poses without worrying about video memory space.
- Be able to rotate or scale sprites without the need for mode 7.
- Make Players, most of the sprites used as player are almost impossible without using dynamic sprites.
- Being able to make huge sprites with various poses, using double buffering techniques you can load really big poses without worrying about flickering.
- Bosses: many bosses are impossible to make without dynamic sprites.
Glossary
- Sprite: It has 2 main meanings when spoken in the context of SNES:
- To refer to each of the OAM objects, which would come to be blocks of a fixed size (example 8x8 or 16x16) that are used to draw entities on screen that are not part of backgrounds.
- To refer to entities that are not part of the Backgrounds. Normalmente se utilizará la segunda definición cuando hablemos de Sprites, la primera definición será reemplazada con la palabra Tile.
- Dynamic: In the context of this guide, it refers to the ability to change in real time resources such as graphics, tilemaps or color palettes.
- Dynamic Sprite: Sprite that loads its own resources in real time.
- VRAM: Video memory of the SNES, used to store graphics and tilemaps.
- CGRAM: Color memory of the SNES, it is used to store color palettes that are used by the graphics.
- BPP: Refers to the amount of bits per pixel that a type of graphic uses, during this guide, in general we will talk about 4BPP which would be 4 bits per pixel (2 pixels per byte).
- Tile: In the context of this guide tile will be used to refer to blocks of specific size (8x8, 16x16, etc.) that are used for sprites or Backgrounds. This is similar to the first definition of Sprite and will be used in general to differentiate from the second definition of Sprite.
- DMA: Direct Memory Access refers mainly to a piece of hardware that is concerned with sending a massive amount of data as fast as possible.
- DMA overflow: refers to when the DMA sends more data than the snes can process during NMI. This causes flickering and if excessive could even cause graphical glitches.
- Frame: Refers to 1 full cycle of the SNES, the Super Nintendo uses 60 of these cycles per second (50 if PAL version). This cycle normally includes a full execution of the logic and a full execution of the NMI Handler.
- NMI: Not Masked Interruption, in the context of the SNES, an NMI is generated the moment the TV pointer moves from the lower right corner to the upper left corner, which is also known as Blanking. During this interruption a function called NMI Handler is called which allows changes to be made to the console's stored resources such as graphics, color palettes, tilemaps, etc.
- Pose: This term will be used to refer to the animation frames of a sprite, this is because animation frame when translated to English is Animation Frame, which can be confusing with SNES Frames.
- Sprite Page: Refers to the space in the VRAM that can only be used by sprites.
- Tilemap: Usually refers to the Tiles used by backgrounds, which are used both for the terrain of a level and for backgrounds or in some cases elements such as dialog boxes or HUD.
How to create a dynamic sprite system?
When creating a dynamic sprite system the following must be considered:
- VRAM space management.
- DMA overflow management.
- Uploading data to the VRAM.
- Insertion of resources in the ROM.
- Connection between resources and code.
VRAM Space management in the VRAM
Fixed Allocation
A dynamic sprite needs a place in the VRAM sprite pages where it can load its poses. There are several ways to allocate space for dynamic sprites, in this section we will discuss each of these ways. Fixed Allocation
This consists of assigning a fixed place in the VRAM for a specific dynamic sprite.
Pros:
- Easy to implement.
- Implementation is usually very fast and efficient in terms of performance.
Cons:
- In most cases, you cannot have more than one instance of the same sprite.
- The allocated space is very restrictively designed to only work with that specific sprite. This makes it very restrictive to change the skin of the sprite, since the skin must use the same allocation space as the original sprite.
- If you wanted to make multiple dynamic sprites you would have to assign each one a specific space and that would greatly limit the use of these sprites.
- The system does not scale well, as adding more dynamic sprites or more things that require VRAM can be counterproductive.
- It goes partly against the spirit of dynamic sprites, since, the idea of dynamic sprites is to increase the flexibility of using sprites and remove limitations. But this system often restricts more than it helps.
Recommendations for use
This system in general is quite bad in several senses, but it has a niche of use mainly for simple games that do not have many graphics or enemies or that these enemies do not use many poses or a big size, in this type of games, it has utility for the player or for a specific sprite that should never have more than 1 copy on screen. This niche is only if you want to have a better performance although other systems even if they are not so good in performance, I doubt you will have slowdown problems because of them.
Fixed assignment for specific tiles
This consists in that instead of using a fixed allocation for a specific sprite, this allocation is made for some specific tile animations. Tiles are usually animated continuously and allows to save some tiles in the VRAM.
Pros:
- Easy to implement.
- The implementation is usually very fast and efficient in terms of performance, although, not as fast as in the normal fixed allocation.
Cons:
- In general it has the same cons as the fixed allocation, except that it is a bit more flexible (depending on how it is done to animate the tiles) to be able to put more than one instance of the sprite on the screen.
Recommendations for use
In general, this system is also quite bad and although it can get out of trouble to someone without much knowledge of code, I do not recommend it, but it can still have a niche in the Rom Hacks hacking when you want to implement something fast without programming a complex system of dynamic sprites for a couple of specific sprites.
Dynamic Allocation with fixed size by Sprite
It consists of assigning a space in the VRAM to each instance of some dynamic sprite. The sprite takes care of uploading its graphics to its allocated space. The sprites that use this system must use a specific size in the VRAM that are predefined by the system (example that only 64x16, 128x16 or 128x32 spaces can be used).
Pros:
- Although the implementation of this system is not as simple as the fixed allocation system, it is usually quite easy to implement.
- In terms of performance, although it is not as good as the fixed allocation system, it is usually quite fast.
- It allows greater flexibility than the previous systems, since, you can put dynamic sprites with greater freedom.
- It allows to use multiple different instances of different sprites.
Cons:
- The allocated space is very restrictively designed to only work with that specific sprite. This makes it very restrictive to change the skin of the sprite, since the skin must use the same allocated space as the original sprite.
- The number of these sprites that you can use on screen is usually very low due to wasting a lot of VRAM space.
- It usually has a lot of DMA overflow management problems since each instance of a dynamic sprite must load the poses even if they were already loaded by another sprite previously.
- Certain combinations of sprites cause gaps in the VRAM that are very difficult to exploit and reduce the amount of dynamic sprites you can use at the same time. The solution to this is usually to defragment the space allocated for dynamic sprites, which can end up affecting system performance.
- In many cases there is wasted VRAM, since sprites that are smaller than the space they have been allocated still use all that space.
- Once a sprite has been allocated a space, resizing that space can be very difficult and lead to many other problems due to how the system was built. This causes that for example having a sprite that gets bigger if some specific event happens is not possible in this system or that you have to assign it a much bigger space than it really needs from the beginning.
Recommendations for use
In general, this system is much better than the previous ones, however, it has several drawbacks that make it unattractive. I would only recommend using it if you need a decent dynamic sprite system that is very fast, although in terms of performance it is almost the same as "Dynamic Allocation with variable size per Sprite". It has a niche also if you want to quickly implement a basic and functional system.
Dynamic Allocation with variable size per Sprite
It is similar to the "Dynamic Allocation with fixed size per Sprite" system, what changes, is that each sprite calculates how much space it needs in the VRAM (normally it is calculated using 16x16 blocks). To make this space calculation, the sprite considers the pose that uses the most space and based on that pose calculates how much space it should use in the VRAM.
Pros:
- In terms of performance, although it is not as good as Fixed Allocation, it is usually quite fast.
- It allows more flexibility than the previous systems, since, you can put dynamic sprites with more freedom.
- It allows to use multiple different instances of different sprites.
- Suffers less from VRAM gaps than "Dynamic Allocation with fixed size per Sprite".
- Uses space more efficiently than "Dynamic Allocation with fixed size per Sprite".
- Allows for a larger number of sprite sizes. Since, each sprite uses the size it needs.
- In general, it allows more dynamic sprites at a time than "Dynamic Allocation with fixed size per Sprite".
Cons:
- The implementation is usually more complex, since the search for free space in the VRAM is not trivial to solve efficiently.
- The allocated space is very restrictively designed to only work with that specific sprite. This makes it very restrictive to change the skin of the sprite, since the skin must use the same allocated space as the original sprite.
- It tends to have a lot of DMA overflow management problems since every instance of a dynamic sprite must load the poses even if they were already loaded by another sprite previously.
- Certain combinations of sprites cause gaps in the VRAM that are very difficult to exploit and reduce the amount of dynamic sprites you can use at the same time. The solution to this is usually to defragment the space allocated for dynamic sprites, which can end up affecting system performance. While these problems are less than those of "Dynamic Allocation with fixed size per Sprite", they still occur.
- While it does not waste as much space as "Dynamic Allocation with fixed size per Sprite", there is still a lot of waste because the sprite must always use the space used by the largest pose as its space.
- Once the sprite has a space assigned to it, changing the size of that space can be very difficult and lead to many other problems due to how the system was built. This causes that for example having a sprite that gets bigger if some specific event happens is not possible in this system or that you must assign it a much bigger space than it really needs from the beginning.
Recommendations for use
This system in general is quite good and in fact is the one used by games like Donkey Kong Country. In most cases, this would be a good option to use as a dynamic sprite system, especially if the space allotted for dynamic sprites is not that large. Although it can be somewhat difficult to implement, so, it is not recommended for developers who are not yet very skilled or if you have little time to develop it. Also, if the size for dynamic sprites that you have is large it is better to use the "Dynamic Pose Allocation" system.
Dynamic Pose Allocation
A space is allocated in the VRAM for each pose that is required, once the space allocated for dynamic sprites is full, one or more poses are replaced in order to load the new pose. The way this pose is replaced must be according to some replacement policy such as replacing the least used pose or replacing the pose that has not been used for the longest time.
Basically it could be summarized that this system treats the space allocated for dynamic sprites in a pose cache.
Pros:
- Each pose is loaded into VRAM only once and then reused by any code that requires that pose, which is not only space efficient but also performance efficient.
- It is not restricted to only be used from a sprite code, you could load the pose from any code.
- It considerably decreases the load on the VRAM, which greatly decreases the chances of a DMA overflow.
- It is easy to reskin an entity using this system, since each pose can be of any size.
- The flexibility of using dynamic sprites is greatly increased to the point that they can be used as if they were normal sprites in terms of quantity. This system feels like you are not on a console as limited as the SNES.
- There is almost no waste of VRAM, since each pose uses the smallest space it can.
Since each sprite can use any pose, there are no restrictions on the size of the dynamic space it uses as long as it fits in dynamic space.
- It allows a very flexible use of double buffering, since this system itself is like an advanced double buffer. This allows to separate the sprites in multiple sections and load them in parts. While double buffering is possible in the other systems, it must be implemented separately and is usually more limited.
If you have multiple copies of the same dynamic sprite you have 0 usage limitations for that sprite.
- With this system, using dynamic sprites is so convenient that you could replace all normal sprites and transform them into dynamic sprites and have advantages such as being able to use any entity (enemies, characters, etc.) in any level with almost no limitations.