nesdev.com
http://forums.nesdev.com/

Flickering of different tiles within the same meta sprite
http://forums.nesdev.com/viewtopic.php?f=2&t=18440
Page 1 of 2

Author:  DRW [ Sun Feb 10, 2019 3:25 am ]
Post subject:  Flickering of different tiles within the same meta sprite

In my game, I have a simple shuffle mechanism for meta sprites, so that they start to flicker when too many sprites are on the scanline.
I simply shift the start index of the characters array by 1 every frame. And then I switch between iterating the array from front to back or from back to front every frame.

That's pretty simple because there are about 10 characters max and the shuffling makes sure the hardware sprites get written in a different order every time.
Also, the player character is outside of the shuffling. He always gets written first so that he never flickers.

So, if I have five small meta sprites (with a width of 16 pixels each) next to each other, everything is fine: The hero never flickers and the opponents take turns in flickering.

But now I have the following situation:

I have two meta sprites: The hero with a normal size and a huge wide boss, so that the number of sprites is exceeded when both characters are next to each other.

Now, while the meta sprites are shuffled, the hardware sprites are of course written in a fixed order: The sprite output function simply reads every byte from the array that is the current character's animation phase and that's it.

So, the result is: When both characters are on the same scanline, the right side of the boss simply disappears. Because there are only two meta sprites and one of them is outside of the shuffling. And the right part of the boss is always drawn last.

Even if I included the hero into the shuffling, it would still look odd: The body of the boss wouldn't flicker equally, but it would always be its right side that flickers because that's what's written last.


So, how do games usually do this? If you have one huge boss and flickering is necessary, how do you make sure that the flickering occurs over various parts of his body?


I cannot rewrite the sprite copy function to use a shuffling mechanism as well.
Because I store the palette value for each tile in the beginning of the meta sprite animation phase definition, two bits for each tile.
And then, I have three different counters: One for the current tile position, one for the palette values position and one for the current bit shift inside this palette values byte.
If I included shuffled reading, this would make the palette value caluclation more time consuming since I'd have to recalculate the current position each time instead of simply doing it once and then incrementing the values from there.


Likewise, if I decide to shuffle the hardware sprites themselves after they have been written to an array, then this is still a huge overhead.

Because for shuffling meta sprites, I simply have to check a few conditions for each meta sprite and then the DrawMetaSpriteAsHardwareSprites function gets called with the current index.
Not only do the condition checks only occur about 10 times per frame (once for each meta sprite), but the actual copying function is called the same number of times as if I hadn't included a shuffling mechanism.

But shuffling the actual hardware sprites would require actually copying each and every byte from one array to another. And it would be many times more data.

So, it would be 10 times the call of DrawMetaSpriteAsHardwareSprites (as before) plus the copying of 10 * NumberOfTilesPerCharacter * 4 bytes from one array to another, including setting the counter offset and the iteration order every time one of these 10 * NumberOfTilesPerCharacter tiles is copied.


So, do you know about an efficient way to let each body part flicker instead of just the rightmost one if there's a huge wide boss?

Author:  rainwarrior [ Sun Feb 10, 2019 3:46 am ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

Probably what I would do is break the boss into 2 or 3 metasprites, and let them be shuffled by your existing metasprite routine.

A related thing I did sometimes in Lizard: if a metasprite was symmetrical, I took advantage of that and sometimes randomly used it in flipped form, which also helped distribute flickering in a few cases.

I never really wanted a metasprite to be able to change its order, I like to be able to do layering if I need it. Plus it seems like a lot of extra overhead to shuffle individual tiles. It did mean that I just had to live with some tiles being more likely to flicker than others, though in some cases that's also an advantage... you can put the most visually critical tiles in the highest priority slot and control what order they drop out.

Another related note: you might consider adding more ordering possibilities to your metasprite shuffle besides just frontward and backward, as well. That might help vary which sprites participate in flicker in some situations too. You can probably do this with very little additional overhead.

Author:  calima [ Sun Feb 10, 2019 4:42 am ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

It'd be cheap to draw the big-ass boss metasprite backwards on even frames and forwards on normal frames.

Author:  FrankenGraphics [ Sun Feb 10, 2019 4:55 am ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

A bit trickier, but a method could be to increment the drawing order of that particular meta-sprite to your buffer each frame. A very local round robin thing. You need a separate routine (or one that can handle the exception), something in the object or sprite metadata to help the conditional, and a literal for wrapping around (could be the same used for the condition).

Project Blues' bosses are made of several objects+metasprites. The pro is simplicity and uniformity which helps with their animation schemes among other things. The con is separate collision handling, which limits what sorts of rooms you can put a boss in or they'll break apart/together. Plus the computation overhead puts a limit to resources.

Author:  tokumaru [ Sun Feb 10, 2019 5:25 am ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

I second the suggestion of breaking the boss into multiple metasprites. Unless your engine has a restriction of
1 object = 1 metasprite, which isn't very flexible, but even breaking the boss into multiple objects wouldn't be so bad.

Author:  gravelstudios [ Sun Feb 10, 2019 7:58 am ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

In the game I'm working on, I set aside a variable for the index in my shadow OAM at $0200. I loop through each object and determine which animation 'cell' that object should be displaying on that frame. When I copy the sprite tile data from the ROM object tables to the shadow OAM in RAM, I don't reset the index. I just pick up where I left off on the next object/frame. Unless all of the objects on the screen use up exactly all 64 sprite tiles (which is rare), it seems to result in a nice even sprite flicker all around.

And because my player character relies on sprite order to display correctly, I have a routine that resets the index if it would result in the player character sprite 'wrapping around' the edge of the shadow OAM array.

One major disadvantage is that if all the objects on screen use MORE than 64 tiles, the same objects at the end of the object table always get omitted from OAM on every frame until there is room for them. Fortunately, that doesn't happen often.

Author:  dougeff [ Sun Feb 10, 2019 8:49 am ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

I concur with breaking the boss into smaller chunks and shuffling the order of those chunks.

Author:  Bregalad [ Sun Feb 10, 2019 1:33 pm ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

Before you come up angry because others haven't answered your questions I'll try to answer your questions.

DRW wrote:
So, how do games usually do this? If you have one huge boss and flickering is necessary, how do you make sure that the flickering occurs over various parts of his body?
[...]
So, do you know about an efficient way to let each body part flicker instead of just the rightmost one if there's a huge wide boss?

There's no agreed ways games does things like this. Each developer has it's own habits. For example Konami have a very particular way of putting sprites in a pseudo-random order, which create a very specify cycling. This exclude sprite layering. Other game makers comes up with their own strategies, sometimes it's even game specific.

As for what I'd do if I was in your situation I'd probably include the hero's sprite in the shuffling, and I don't think it's a problem if only a part of your boss flickers, as long as it doesn't dissapear completely. That's pretty standard NES graphics.

Author:  DRW [ Sun Feb 10, 2019 3:36 pm ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

Bregalad wrote:
Before you come up angry because others haven't answered your questions I'll try to answer your questions.

And again another side blow from Bregalad. You just have to do this, right?

When have I ever been angry in a technical development thread, hm?

And then he didn't even answer my questions:

"How did other games do it?"
"Every game did it differently."

"How do I solve my problem of only one part flickering?"
"Why don't you simply declare your problem as "not a problem" and leave it at that?"


Regarding the several suggestions:


One character = several meta tiles.

There are two ways here:

Either, the character is actually composed of several game characters.
I think this is not so good because in this case, you have to synchronize several characters with each other: x and y position, current palette value when the character is blinking etc. I consciously programmed the characters with arbitrary sizes, specifically to avoid that.

The other possibility is to have several meta sprites, but one game logic character.
I.e you still have one x and y position, one palette offset value, one character type value, one energy bar etc. But instead of one meta sprite ID, you have an array of meta sprite IDs and arrays for the x and y offsets relative to the actual x and y position.

But in this case, I'm not sure whether the shuffling is really that good. After all, now you would have an outer and an inner loop:
Outer loop: for each character
Inner loop: for each meta sprite ID in the character.

And in this case, the meta sprites of the same character would still be quite together. For example, you wouldn't have the situation that you draw the first meta sprite of character 1, then the meta sprites of characters 2, 3, 4 etc. and then the last meta sprite of character 1 again. So, I'm not sure if the shuffling would really be that good here.
Other than that, it might be a solution. Maybe. Although I still don't really like the idea of adjusting game logic stuff just to accomodate to a certain hardware quirk.


The best solution would be if I could just choose the sprite slot for the next hardware sprite randomly. But apart from calling the randomizer each time, this might take time away when the array is almost full and you choose a slot and have to iterate through the array until you find an empty slot.


Regarding simply turning around the drawing order in each frame: In this case, only the left and right parts would flicker, but never the middle parts.


Round robin inside the meta sprite:
My sprites are stored in a way, so that the palette indices come first, then come the tiles themselves. One palette byte is used for four tiles since it has eight bits, but you only need two bits per tile for the palette value, that's why they aren't simply stored next to each other.
This way, I have three counters at the start: One to the palette values, one to the tiles and one value to indicate how many bit pairs of the current palette value have been read.
For each drawn tile, I increment the tile counter and the bit pair counter. As soon as the bit pair counter is 4, I set it back to 0 and increment the palette counter.
This way, I can easily pick up the next item.
If I had some kind of round robin method, this would make the calculations more complicated: The palette counter wouldn't just be at byte 0 in the beginning. And the bit pair counter would have to be calculated as well. Furthermore, you would have to check for the round robin stuff after every tile and recalculate the counters if the condition is met.


About not resetting the start index of the shadow copy of the hardware sprite array: Maybe this could work with mininal overhead and without changing the actual game logic. It would leave the sprite drawing logic largely alone.
I'd only have to adjust the hardware sprite index when it reaches 0 because in my game, I never use all 64 sprites, so after moving them offscreen once in the beginning, I leave the lower portion of the sprite array unused, including when I delete all old sprites. Saves some time.

O.k., if I want to leave the hero and its weapons out of the flickering, I would have to do it in a way so that I save the current sprite index into a temporary variable, then I set the index to a fixed location that is always used for the hero, then I call the sprite drawing function and then I set the index back before drawing the regular characters. Could make the deletion of the hero's weapons a bit more complicated since they can have arbitrary sprite sizes as well.

Author:  tokumaru [ Sun Feb 10, 2019 3:40 pm ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

I understand that some people think the player sprite is too important to flicker, and while it's true that many times we have or eyes on the player, mainly for making movement-related decisions, we also take our eyes away from the player quite a lot, to take the level geometry and the positions of other objects into account as well, so I really think that including the player in the sprite cycling is a sensible decision.

What you must avoid at all costs, is to have *any* sprite disappear for more than one frame, because then you might start making it hard for the player to keep track of the positions of the various objects.

Author:  DRW [ Sun Feb 10, 2019 3:49 pm ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

Two more things:

tokumaru wrote:
1 object = 1 metasprite, which isn't very flexible

Why is this not flexible? Or rather: Apart from my specific flickering issue, why would flexibility be even an issue here? What exactly can I not do with this setup?

rainwarrior wrote:
Another related note: you might consider adding more ordering possibilities to your metasprite shuffle besides just frontward and backward, as well. That might help vary which sprites participate in flicker in some situations too. You can probably do this with very little additional overhead.

My current solution (on a per-character basis) is:
Switching between forwards and backwards in every frame.
And incrementing the start counter in every frame.

So, if we had six characters, this would be the order:
- 1 2 3 4 5 6
- 2 1 6 5 4 3
- 3 4 5 6 1 2
- 4 3 2 1 6 5
- 5 6 1 2 3 4
- 6 5 4 3 2 1

Would you say this is a good shuffling mechanism?

Author:  dougeff [ Sun Feb 10, 2019 4:50 pm ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

Quote:
Would you say this is a good shuffling mechanism?


That might be ok for small metasprites, but I don't see how that would improve very large metasprites.

Author:  Fiskbit [ Sun Feb 10, 2019 5:02 pm ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

Another approach you could consider is having a table of shuffled sprite indices and always picking the next index from that table; your index into the table always linearly increases (and wraps around and it isn't reset between frames), but the tile it represents is shuffled. This does a pretty good job, though overlapping sprites may look a bit odd at times because the component tiles of any given sprite end up with very different priorities.

Author:  rainwarrior [ Sun Feb 10, 2019 5:06 pm ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

DRW wrote:
Either, the character is actually composed of several game characters.
I think this is not so good because in this case, you have to synchronize several characters with each other: x and y position, current palette value when the character is blinking etc. I consciously programmed the characters with arbitrary sizes, specifically to avoid that.

You don't need to have any logic for the boss character distributed to the other components though. Make a very simple type of character that is just a sprite and nothing else. It can remain the main character's job to do everything, and it can just pass the needed sprite/X/Y to its subordinate characters.

DRW wrote:
Switching between forwards and backwards in every frame.
And incrementing the start counter in every frame.
...
Would you say this is a good shuffling mechanism?

If your list is short it's not awful, at least every sprite will appear first every several frames, but in the general case it's not very good.

A good shuffler should be changing the relative order of sprites. Changing the start position doesn't accomplish this very well. If you start on 2, you still have 2 before 3 before 4, etc... the only order you've changed by doing that is that 1 is now after things, but every other order relationship is intact.

Taking every second, or every third sprite, for example, would do a lot more to shuffle the order used. (My own preferred technique is to select an increment from a table of prime numbers, which is used to step through the list in modulo.)

Author:  gravelstudios [ Sun Feb 10, 2019 5:13 pm ]
Post subject:  Re: Flickering of different tiles within the same meta sprit

Quote:
The best solution would be if I could just choose the sprite slot for the next hardware sprite randomly. But apart from calling the randomizer each time, this might take time away when the array is almost full and you choose a slot and have to iterate through the array until you find an empty slot.

Maybe a short routine that cycles through 0-63 in a pseudo-random order before it repeats, and just use it for sprite cycling (separate from whatever other RNG system you have in place). Something like this I think would cycle through all 64 sprites only once before repeating. So that way, you wouldn't have to worry about looking for an empty slot. you would always know the next slot it chooses is empty:

Code:
LDA seed
ASL A
ASL A
CLC
ADC seed
CLC
ADC #03
STA seed
AND #%00111111

Page 1 of 2 All times are UTC - 7 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/