Question about sprite cycling

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
JonnyManjiro
Posts: 16
Joined: Thu Jan 27, 2022 3:22 am

Question about sprite cycling

Post by JonnyManjiro »

I'm at a point in my next project where I'd like to add sprite cycling, but I've never done it before.

Right now, all my sprite variables are hard-coded into the range of $200-$2FF (ex: Enemy 1 always uses $240-$24F), which I've recently learned is bad practice.

Am I supposed to use 256 kb to assign individual variables to all of these values, and then shift them over each frame?

For example, in theory, could I change all my code for $240 into 240variable, $241 into 241variable etc., and then have a routine that assigns 240variable-24Fvariable to $200-$20F the first frame, $210-$21F the next frame, etc., all the way up to $2F0-$2FF before looping back, and then do the same for the other 15 sprites?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Question about sprite cycling

Post by tokumaru »

No, that would be very wasteful of both memory and CPU time. What you're supposed to do (i.e. what the vast majority of games do) is to completely separate game objects and sprites. A game object is NOT a sprite, it's only drawn with sprites. Objects should have a position, a direction, and whatever other attributes they need in order to move around and interact with their world. In addition to that, they need a pointer to a meta sprite entry. A meta sprite is just a group of sprites, but instead of using absolute screen coordinates, their coordinates are relative to the coordinates of the object they represent.

For example, if a meta sprite is 16x16 pixels, formed by 4 8x8 sprites, the sprites could be arranged around the object like this:

Code: Select all

+----------------+----------------+
|(-8, -8)        |(0, -8)         |
|                |                |
|                |                |
|                |                |
|                |                |
|                |                |
|                |                |
|                |                |
+----------------O----------------+
|(-8, 0)         |(0, 0)          |
|                |                |
|                |                |
|                |                |
|                |                |
|                |                |
|                |                |
|                |                |
+----------------+----------------+
"O" is where the object's coordinates are, and each sprite has a pair of coordinates relative to that point. Games normally have a subroutine that will take an object, translate its coordinates into screen space (if they aren't already), then run through the meta sprite definition adding each sprite's coordinates to the object's, and writing the results to OAM. if any sprite falls outside of the screen (the coordinates are < 0 or > 255), it's skipped. Otherwise, the remaining OAM bytes (attribute and tile index) are filled out as well, and the subroutine jumps to the next OAM position.

The sprite cycling itself is achieved when you vary the order in which the sprites are output over time. You can select the objects to draw in pseudo random order and fill the OAM linearly (this is a way to preserve sprite priorities within meta sprites), or you can select objects in any way you want and select a random position of OAM to start outputting sprites, and advance a number of slots that's relatively prime to 64 (e.g. 17) after each sprite, to really scatter them all around OAM.

Hardcoding objects to specific OAM positions is a bad practice not only because of the lack of sprite cycling, but also because it limits the use of the sprites for different purposes. This is not much of a problem in games with a fixed number of objects (e.g. Pac Man always has 1 player, 4 ghosts, etc.), but in games where different types of enemies of different sizes are spawning and dying, power ups are appearing and being collected, environmental animations are starting and stopping, you really don't want to limit which sprites can be used for what purpose... You use whatever is available for whatever objects are active at any given time.
JonnyManjiro
Posts: 16
Joined: Thu Jan 27, 2022 3:22 am

Re: Question about sprite cycling

Post by JonnyManjiro »

Thank you for the reply tokumaru. It's a lot of info to absorb, but it's all stuff I'll need to learn eventually, so the detailed response is much appreciated :beer:

FWIW, my current project is a top-down strategy RPG like Fire Emblem or Shining Force, so having 5 or more sprites in a single row is something that will be inevitable. I'm starting to wonder if I should have made the individual units animated background tiles that become sprites when it is their turn to act, though at this point that would require me to sort of re-build most of my engine.
Post Reply