Best way to handle sprites?

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
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Best way to handle sprites?

Post by mantanz »

I'm working on a side scrolling shooter and in the past using Unity etc I've often loaded my sprites into a pool and just activated them when needed. Sometimes I'd just move them off screen.

So basically with NES is it better to load my enemies/bullets etc and keep them off screen until needed or should I be loading them as needed? Does having loads of sprites loaded but not visible on screen affect performance?
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Best way to handle sprites?

Post by pubby »

What do you mean by "load"?

The NES always draws 64 sprites per frame. Sprites not visible are placed off-screen.
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Best way to handle sprites?

Post by mantanz »

Ah OK. Cool. So you can have all 64 ready to go? Perhaps loading wasn't the right term. I'm very new to this asm stuff.

It's possible to clear the PPU and load new tile sets on the fly right? Basically I want to turn the background black at the end of a level, clearing the background, and load a new tile set to use for a big Boss. Sorry, but unrelated to previous Q I guess.
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: Best way to handle sprites?

Post by FrankenGraphics »

Sprite readiness:
Yes, they're all there with wathever properties you've given them. You should keep them off screen via the y axis so they aren't in the way for the sprites per row limit, lest you might experience unnecessary sprite cancelling on-screen. You should also initialize them when the program starts so they're not randomly placed with random content.

Boss room:
A straightforward way to do it:
1) change all bg subpalette colours to black
2) change contents of pattern- attribute- and nametable.
3) change back subpalettes to what colours you want for the boss.

Changing tables can be varyingly visible - extra visible if you're using compression to save ROM space.

Edited for clarity
Last edited by FrankenGraphics on Sun Jul 23, 2017 2:10 am, edited 1 time in total.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Best way to handle sprites?

Post by tokumaru »

You appear to be mixing up sprites and objects. An object/actor/entity (or whatever you want to call it) is something that exists in the game world, while a sprite is just a visual representation of that thing. Sprites are quite limited on the NES (64 per frame, 8 per scanline), so games don't typically hardcode hardware sprites to game objects, but instead generate a new list of hardware sprites every frame based on the objects that are currently active, assigning different sprite slots for each object every frame. The purpose of this is mainly to cycle the priority of the sprites so that different sprites are dropped each frame in case the limits are reached (which can happen quite often depending on the type of the game), so you get flickering instead of completely invisible objects.

Contrary to popular belief, sprite flickering in NES games is not automatic: if the hardware finds more than 8 sprites on the same scanline, it will simply not draw anymore sprites on that scanline. It's up to the programmer to rotate the sprite priorities so that different sprites are dropped each frame.

Also, the NES has very limited processing power, so indeed most games only keep track of objects that are near the camera. In a side scroller this is pretty easy: just keep your list of objects sorted by their X coordinates and every few pixels scrolled compare the position of an imaginary "spawn column" against the coordinate of the next object in the list, and if it's larger, activate the object. Active objects can test their own coordinates against the camera and choose to deactivate themselves if they're too far.
mantanz wrote:It's possible to clear the PPU and load new tile sets on the fly right?
Yeah, but you can only write to VRAM during vblank or when rendering is disabled.
Basically I want to turn the background black at the end of a level, clearing the background, and load a new tile set to use for a big Boss.
The way a new tileset is loaded depends on the type of CHR memory you're using, ROM or RAM. ROM can be switched nearly instantaneously, since the process consists basically in telling the mapper to point to a different place in a bigger CHR-ROM chip (i.e. there's no data being moved anywhere), while CHR-RAM must be rewritten manually byte by byte. CHR-RAM is more common among homebrews, because the mappers that use CHR-RAM are usually easier/cheaper to recreate in cartridge form.

Either would work well for what you describe though, since you plan on fading to black and back in... If using CHR-ROM, just have the mapper switch the new tiles at any time, if using CHR-RAM, upload the new tileset byte by byte across several consecutive vblanks until the whole thing is done, then you can fade back in. With the fastest possible code (unrolled loop), you'd be able to update the whole 8KB of CHR-RAM in about half a second (i.e. 30 vblanks), but a full second using a regular loop doesn't sound bad either.
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Best way to handle sprites?

Post by mantanz »

Awesome, thanks for the info/help, guys! Pretty sure I understand all that :)

It's early days for me. So far I have my ship moving around. Next I'll implement my shooting bullets and then I'll start working out background stuff. Step by step :)
User avatar
Sumez
Posts: 919
Joined: Thu Sep 15, 2016 6:29 am
Location: Denmark (PAL)

Re: Best way to handle sprites?

Post by Sumez »

I'd say if you are just starting out, go with CHR-ROM for your graphics data. That way you never have to worry about "loading" anything. If you have multiple banks of ROM data for your graphics, you WILL have to tell the mapper chip which banks to use, which is really easy, but when you're starting out, I'd recommend to just keeping it to static pages of data for an entire level.

If the physical cartridge PCB isn't an issue, and you aren't planning on doing advanced graphics effects, there's no real reason to go with CHR-RAM. While it's fun to do stuff like faux parallax and raster effects, etc. with CHR-RAM I think it's easier to approach this when you are more familiar with how the NES hardware works.

By using CHR-ROM, the only things you have to write to the PPU is OBJ (sprite) information, and nametable (background) information. Each of these just tells the NES which graphics to output where when drawing frames.
As for your question, you absolutely need to tell the PPU about all 64 sprites every single frame! This is done during vblank by using DMA call that writes all 256 bytes of sprite data to the PPU from a buffer in your RAM, and usually you want to completely refresh all of this buffer during every frame of your game logic.
It might sound wasteful, but as tokumaru pointed out, it's often necessary to move the order of sprites around between each frame, and if any sprite isn't shown any more, it still needs to be updated with a Y coordinate to place it off screen.
So in short, there's no point in "preloading" sprites before they are needed, unless you just mean the graphics data, which as mentioned will be made ready by either bank switching to the correct data, or preparing your CHR-RAM.
User avatar
mantanz
Posts: 31
Joined: Fri Jul 21, 2017 4:38 am

Re: Best way to handle sprites?

Post by mantanz »

Sumez wrote:I'd say if you are just starting out, go with CHR-ROM for your graphics data. That way you never have to worry about "loading" anything. If you have multiple banks of ROM data for your graphics, you WILL have to tell the mapper chip which banks to use, which is really easy, but when you're starting out, I'd recommend to just keeping it to static pages of data for an entire level.

If the physical cartridge PCB isn't an issue, and you aren't planning on doing advanced graphics effects, there's no real reason to go with CHR-RAM. While it's fun to do stuff like faux parallax and raster effects, etc. with CHR-RAM I think it's easier to approach this when you are more familiar with how the NES hardware works.

By using CHR-ROM, the only things you have to write to the PPU is OBJ (sprite) information, and nametable (background) information. Each of these just tells the NES which graphics to output where when drawing frames.
As for your question, you absolutely need to tell the PPU about all 64 sprites every single frame! This is done during vblank by using DMA call that writes all 256 bytes of sprite data to the PPU from a buffer in your RAM, and usually you want to completely refresh all of this buffer during every frame of your game logic.
It might sound wasteful, but as tokumaru pointed out, it's often necessary to move the order of sprites around between each frame, and if any sprite isn't shown any more, it still needs to be updated with a Y coordinate to place it off screen.
So in short, there's no point in "preloading" sprites before they are needed, unless you just mean the graphics data, which as mentioned will be made ready by either bank switching to the correct data, or preparing your CHR-RAM.
Thanks for the info. Super helpful!
I do intend to release on physical cart but I'm learning as I go. Basically I'll start out really simple and keep iterating over, adding features and effects as I learn more about the machine. I know it's probably not the best approach to making a game but it's a good way to learn. But yeah, I'll keep it simple at first :)
Post Reply