Controlled sprite flicker

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

User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Controlled sprite flicker

Post by battagline »

I've been thinking about how to display more than 8 sprites on a single scanline. My understanding is you make them flicker in and out by setting the priority bit in byte 2 of the oam to be behind the background. What I'm not sure is if there is some sort of scanline collision detection that would somehow determine if there are more than 8 sprites on a single line, or if the sprites should be set to randomly flicker at different times to just decrease the likelyhood of them all showing at the same time on the same scanline.

What kind of strategies are generally used? I tried googling this, but didn't really come up with anything.

Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Controlled sprite flicker

Post by nesrocks »

https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Controlled sprite flicker

Post by battagline »

nesrocks wrote:A search gave me this https://forums.nesdev.com/viewtopic.php?f=2&t=10591
Not sure why that didn't come up for me.

Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Controlled sprite flicker

Post by pubby »

The BG bit does nothing to help BTW. Lower sprites in memory always have priority over the higher ones, regardless of the BG bit.
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Controlled sprite flicker

Post by rainwarrior »

battagline wrote:I've been thinking about how to display more than 8 sprites on a single scanline. My understanding is you make them flicker in and out by setting the priority bit in byte 2 of the oam to be behind the background. What I'm not sure is if there is some sort of scanline collision detection that would somehow determine if there are more than 8 sprites on a single line, or if the sprites should be set to randomly flicker at different times to just decrease the likelyhood of them all showing at the same time on the same scanline.
No, the priority bit will not help with this. That only draws that sprite behind the background, but it does not move it to a separate pass, so it will still interfere with other sprites on the same scanline even if they're not behind the background.

The way to deal with this is to change the order of the sprites within the OAM buffer.

The first step is not to put any particular character in a location. A lot of games hard-code sprites like this, but it makes flicker impossible. When you start a frame, set an "OAM index" to 0, every time you add a new sprite, put it at the index location, and add 4 to that index. To finish the frame, fill the rest of the OAM Y coordinates with $FF to hide any unused sprites.

Once you have a system like that in place, cycling the sprite order can be achieved by drawing your sprites in a different order each frame. You might try going through your object list forwards and backwards on different frames, or cycling thruogh them, or maybe have a few different orders.

Simple example:

Code: Select all

jsr oam_begin ; set index to 0
inc order_sequence
lda order_sequence
and #3
bne @order1
@order0:
	jsr draw_player
	jsr draw_enemies
	jsr draw_bullets
	jmp @order_end
@order1:
cmp #1
bne @order2:
	jsr draw_bullets
	jsr draw_enemies
	jsr draw_player
	jmp @order_end
@order2:
cmp #2
bne @order3:
	jsr draw_enemies
	jsr draw_player
	jsr draw_bullets
	jmp @order_end
@order3:
	jsr draw_player
	jsr draw_bullets
	jsr draw_enemies
@order_end:
jsr oam_finish ; fill unused sprite Ys
There are a lot of ways to do this reordering, and what's appropriate depends on your game (often you might want one sprite to always draw first so it never disappears), but this is the general idea. In my last game I use a table of prime numbers as an increment through my game object list, so that they get iterated in a different order each frame.

Though a lot of older games did things in pairs of frames one off, one on, I'd recommend against a sequence with only two steps if you're making a new game, otherwise you'll get the "Mega Man disappears when hit" thing when YouTube or Twitch shows the video at 30fps. Use sequences of 3 frames or longer to ensure that the flickering is still comprehensible at half framerate.

One more general recommendation: don't try to detect overlap, it's easier just keep changing the order every frame. (Technically the sprite overflow flag in $2002 is supposed to detect this in a limited way, but its implementation was broken and it reports false positives. Not very useful.)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Controlled sprite flicker

Post by tokumaru »

Note: Ninja'd by a lot of people, but I didn't write a reply for nothing so I'm posting anyway.

What you're looking for is called OAM cycling, and it has nothing to do with the priority bit.

Priorities between sprites is dictated by their order in OAM. Sprite 0 has the highest priority, sprite 63 the lowest. If more than 8 are present in any given scanline, only the 8 with the highest priorities will be rendered.

OAM cycling typically means randomizing the order of the sprites every frame, effectively randomizing their priorities, so that different sprites are dropped each frame.

You don't need to know when more than 8 sprites are sharing scanlines for this to work, because all sprites will be displayed when there are 8 or less, regardless of their priorities. The PPU does have a flag that indicates when sprites are dropped, but it only gets set once per frame (so you don't know which sprites are the problematic ones), and a bug in this flag's logic may report false positives.
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Controlled sprite flicker

Post by battagline »

Ok, so I need to look around for OAM cycling for more information. I wasn't sure what it was called so googling things like "NES intentional sprite flickering" didn't return what I was looking for.

Thanks for your help
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Controlled sprite flicker

Post by tokumaru »

Strictly speaking, all sprite flickering is intentional. The PPU itself never flickers sprites, it just doesn't draw the ones with lower priority when it finds too many of them.
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Controlled sprite flicker

Post by battagline »

So I've attached a little flickering test I wrote. I'm not sure it looks right. Opinions are appreciated.

Thanks
Attachments
starter.nes
Flickering Text
(40.02 KiB) Downloaded 287 times
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Controlled sprite flicker

Post by nesrocks »

It appears that you have two sprites for each letter and you're moving them outside the screen? You only should have one sprite for each letter and you don't have to move them at all. You cycle their address in memory so they alternate who's first in memory.
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Controlled sprite flicker

Post by battagline »

nesrocks wrote:It appears that you have two sprites for each letter and you're moving them outside the screen? You only should have one sprite for each letter and you don't have to move them at all. You cycle their address in memory so they alternate who's first in memory.
Actually what I'm doing is alternating the direction I write to oam, so on odd frames it writes from lowest to highest bytes and on even frames in writes from highest to lowest. I'm thinking since you move the whole block of OAM memory with the DMA no matter much it shouldn't matter that the used sprites alternate from one side of oam to the other, but if that's a problem for some reason, please let me know.

Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: Controlled sprite flicker

Post by Banshaku »

This subject comes just at the right time, when I'm considering how to approach it myself ^^;;;

I guess it depends on your system that you have implemented and how complicated is your engine. For example, I'm not doing sprite cycle at the moment (but must find how) and how I manage my sprites is that I add to a buffer a list of meta sprites with their information on every frame. Once everything is added to this buffer, I convert that buffer to OAM data.

I guess in my case, what I could do is on every odd frame I parse the buffer forward and even one backward and it could creates some very basic sprite cycling but it will still be depend on the order things are put inside, which for now it quite basic (player, bullets then soon entities, in that order).

Would it be enough, good question, but I guess I will know soon ^^;;; Is it a bad approach? I don't want to give some advice that are ill advised in the first place but I thought it was the right place to talk about it, instead of creating a new thread.
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Controlled sprite flicker

Post by rainwarrior »

battagline wrote:but if that's a problem for some reason, please let me know.
In cases where you have more than 16 sprites on a line, alternating direction will still leave the ones in the middle unseen, but that's maybe an extreme case.

Maybe a more minor issue is the middle ground where you have 9-15 sprites on a line: in this case only the low and high sprites will be flickering, but the ones in between will be solid. This gives very uneven looking flickering, as only some of the sprite tiles will participate in it. That's pretty normal for NES flickering, though, so this might be acceptable.

The other problem I mentioned above, alternating frames means that on YouTube or streams or some other common situations where there's a reduction to 30fps will leave people seeing only one of the two versions. Though, you could deal with that easily by reversing every 2 frames instead of every frame, or doing some pattern like 01001011.
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Controlled sprite flicker

Post by battagline »

rainwarrior wrote: Maybe a more minor issue is the middle ground where you have 9-15 sprites on a line: in this case only the low and high sprites will be flickering, but the ones in between will be solid. This gives very uneven looking flickering, as only some of the sprite tiles will participate in it. That's pretty normal for NES flickering, though, so this might be acceptable.

The other problem I mentioned above, alternating frames means that on YouTube or streams or some other common situations where there's a reduction to 30fps will leave people seeing only one of the two versions. Though, you could deal with that easily by reversing every 2 frames instead of every frame, or doing some pattern like 01001011.
My thought was I would like to design the game to try and avoid any flickering at all, and the flickering would only happen in cases where things went further than I had intended... just a thought, it may not end up working out but doing it this way doesn't spend many cycles and is pretty easy to implement
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
Sumez
Posts: 919
Joined: Thu Sep 15, 2016 6:29 am
Location: Denmark (PAL)

Re: Controlled sprite flicker

Post by Sumez »

rainwarrior wrote: Though, you could deal with that easily by reversing every 2 frames instead of every frame, or doing some pattern like 01001011.
I'd consider leaving a sprite invisible for more than one successive frame much more detrimental than a 30hz flicker rate.
If I'm making an NES game, I'm designing it for a CRT, not for YouTube, and a sprite disappearing for a single frame on a CRT will not flicker as clearly, and usually just appear like it goes partly transparent. Lose it for two frames in a row, and the flickering will be much more apparent.

I noticed this effect in my Donkey Kong port. Playing on emulator, a lot of people had issues with the frequent flickering. But playing it on a CRT it's nowhere near as noticeable.
Of course, I realise that most people will probably be playing your game on an emulator, or an LCD TV, but even on those, I think losing a sprite for two frames in a row will look off-putting when it's not intended as an effect (like Mega Man's invincibility frames)

Did anyone ever reverse engineer Dynamite Batman/Return of the Joker? I'd love to know which method they used.
Post Reply