Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - Sprite flicker

Reply to topic
Author Message
  • Joined: 01 Feb 2014
  • Posts: 877
Reply with quote
Sprite flicker
Post Posted: Fri Jul 25, 2014 12:45 pm
Can someone quickly explain what exactly happens when the VDP hits the limit of more than 8 sprites per line? Does it a) cancel all following sprite draws (as if it encountered $d0 as an y position) or does it b) have something like a buffer for each line that holds up to 64 pixels and just stops drawing any exceeding that on a per-line basis?

In my game project I will have up to 12 sprites on the same line. It probably won't occur very often, but it is possible. I guess I'll have to implement some sort of sprite flicker routine to handle that. However, I'm not sure about the best way to do it.

Do I have to constantly shuffle around the order of all on-screen sprites? That would be quite costly either in RAM space (if I used a scond sprite table buffer for fast block transfers) or in processor time (if I shifted the positions one by one).
I assume it would be sufficient to return to the starting position after the twelveth shift, as that would ensure that there are never the same 12 sprites on the same line for two consecutive frames, or am I wrong?

Another way to handle the flicker I can imagine is to shuffle the order of the calls dealing with on-screen objects in the main loop. However, I'm not sure that would work, as the objects (player, enemies) are usually just 6 sprites big each. It would have the advantage of not having to touch the sprite table buffer after it has been written to, though.

There's one more thing that bothers me: Wouldn't an active sprite flicker routine mean that sprites start flickering as soon as they overlap, even when there are less than 8 sprites on a line? Is there a way to avoid that?

Or are there other, possibly better ways to deal with the sprite limit I haven't thought of yet?
  View user's profile Send private message
  • Joined: 16 Dec 2008
  • Posts: 38
  • Location: UK
Reply with quote
Post Posted: Fri Jul 25, 2014 12:53 pm
The Aspect engine keeps a copy of the SAT in RAM. On even frames it starts from the first srite and copies the buffer to the VDP in ascending order (outi). On odd frames it starts at the last sprite and copies in descending order (outd).

https://github.com/sonicretro/s2smsdisasm/blob/master/src/vdp.asm#L523
  View user's profile Send private message
  • Joined: 28 Sep 1999
  • Posts: 1197
Reply with quote
Post Posted: Sat Jul 26, 2014 2:14 am
Kagesan wrote
Can someone quickly explain what exactly happens when the VDP hits the limit of more than 8 sprites per line? Does it a) cancel all following sprite draws (as if it encountered $d0 as an y position)


It cancels all sprite draws for the current scanline. Sort of like $D0, but sprite drawing resumes on the next line.

Quote
Do I have to constantly shuffle around the order of all on-screen sprites? That would be quite costly either in RAM space (if I used a second sprite table buffer for fast block transfers) or in processor time (if I shifted the positions one by one).


That's right, in general the only thing you can do to reduce the sprite drop-out is to reorder things in RAM so different sprites get drawn before others. It is sort of a costly thing to do, and in the 16-bit era they put more of this reordering burden in hardware.

Quote
There's one more thing that bothers me: Wouldn't an active sprite flicker routine mean that sprites start flickering as soon as they overlap, even when there are less than 8 sprites on a line? Is there a way to avoid that?


They'd only flicker if you were applying your routine to the entire sprite table. I think instead you'd want to keep track of how many objects (multi-sprite objects) were on a line, and apply the routine for those sprites that are affected. This way sprites elsewhere on the screen, say with less than 8 sprites the lines they occupy, won't be affected by the re-ordering.

Maybe one crude approach would be to divide the screen into three horizontal areas (say 64 lines tall each), and if the object count in any area is enough to cause sprite drop-out, re-order the sprites that correspond to that region only.
  View user's profile Send private message Visit poster's website
  • Joined: 01 Feb 2014
  • Posts: 877
Reply with quote
Post Posted: Sat Jul 26, 2014 7:36 am
Glitch wrote
The Aspect engine keeps a copy of the SAT in RAM. On even frames it starts from the first srite and copies the buffer to the VDP in ascending order (outi). On odd frames it starts at the last sprite and copies in descending order (outd).

That's a clever approach, but I think it's a little too sophisticated for me, and it wouldn't work in my game without a major rewrite, as my sprite table varies in length, and the linked approch seems to rely on a couple of fixed values.

Charles MacDonald wrote
Maybe one crude approach would be to divide the screen into three horizontal areas (say 64 lines tall each), and if the object count in any area is enough to cause sprite drop-out, re-order the sprites that correspond to that region only.

That approach would fit nicely with my game, as each screen is already divided into three horizontal levels. However, you really got me thinking about the conditions that may cause a sprite drop-out, and since they are very specific, I think it might be possible to simplify the concept even further.

There are only ever three multi-sprite objects on screen, namely the player and two enemies. They can only attack each other if they are on the same level (thus having the same Y coordinates). Sprite drop-out can only occur when more than one of the three attacks at the same time.

Correct me if I'm wrong but I think it should work to just track how many 'attack' states are active at any given time and when the number is > 1 simply swap the drawing order of the enemy objects. That way I don't have to manipulate the individual sprite table entries and can keep the player object always on top. And the flicker would only be activated when necessary. Right?
  View user's profile Send private message
  • Joined: 28 Sep 1999
  • Posts: 1197
Reply with quote
Post Posted: Sat Jul 26, 2014 9:39 pm
Quote
I think it should work to just track how many 'attack' states are active at any given time and when the number is > 1 simply swap the drawing order of the enemy objects. That way I don't have to manipulate the individual sprite table entries and can keep the player object always on top. And the flicker would only be activated when necessary. Right?


That sounds reasonable. Speaking for myself I think I'd have to make a table of all the possibilities to look for any edge cases. :)

It sounds like you want the player to always be drawn (no flicker) and then only the enemies flicker. If you are reordering the entire set of sprites for the enemies based on the flicker condition, I guess they'd blink on and off at every other frame (30 Hz) which may or may not be difficult for the players to look at.

If it's hard to watch, you could do something like draw the top few sprites of one enemy and the bottom few sprites of the other, such that in any given frame some portion of both enemies are shown and the remaining portion flickers. That way none of them are entirely invisible for a frame.
  View user's profile Send private message Visit poster's website
  • Joined: 01 Feb 2014
  • Posts: 877
Reply with quote
Post Posted: Sun Jul 27, 2014 7:35 am
Charles MacDonald wrote
If it's hard to watch, you could do something like draw the top few sprites of one enemy and the bottom few sprites of the other, such that in any given frame some portion of both enemies are shown and the remaining portion flickers. That way none of them are entirely invisible for a frame.

That's a very good suggestion, thanks. I'll keep that in mind.
  View user's profile Send private message
Reply to topic



Back to the top of this page

Back to SMS Power!