It is currently Tue Nov 20, 2018 9:16 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 30 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Wed Nov 07, 2018 12:45 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
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


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 12:50 pm 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 310
Location: Rio de Janeiro - Brazil
A search gave me this https://forums.nesdev.com/viewtopic.php?f=2&t=10591

_________________
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 1:08 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
nesrocks wrote:


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


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 1:12 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 423
The BG bit does nothing to help BTW. Lower sprites in memory always have priority over the higher ones, regardless of the BG bit.


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 1:12 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6961
Location: Canada
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:
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.)


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 1:20 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10978
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 1:24 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
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


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 1:39 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10978
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 5:02 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
So I've attached a little flickering test I wrote. I'm not sure it looks right. Opinions are appreciated.

Thanks


Attachments:
File comment: Flickering Text
starter.nes [40.02 KiB]
Downloaded 18 times

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 5:34 pm 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 310
Location: Rio de Janeiro - Brazil
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!


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 5:48 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
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


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 5:57 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 2059
Location: Fukuoka, Japan
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.


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 6:09 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6961
Location: Canada
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.


Top
 Profile  
 
PostPosted: Wed Nov 07, 2018 6:31 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 146
Location: Colorado
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


Top
 Profile  
 
PostPosted: Thu Nov 08, 2018 4:44 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 797
Location: Denmark (PAL)
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 30 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group