How to delete / unload sprite? (nes 6502)
Moderator: Moderators
How to delete / unload sprite? (nes 6502)
Hi,
I need help with very simple matter. I want to destroy bullet on collision. I have collision detection but I can't find any tutorial / code example on how to delete / remove / unload a sprite.
I suspect that what i need to do is clear the memory location containing number of tile from the pattern table or prevent sprite from being drawn on the screen.
I need help with very simple matter. I want to destroy bullet on collision. I have collision detection but I can't find any tutorial / code example on how to delete / remove / unload a sprite.
I suspect that what i need to do is clear the memory location containing number of tile from the pattern table or prevent sprite from being drawn on the screen.
Re: How to delete / unload sprite? (nes 6502)
The recommended way is to set the Y coordinates to $F0 or above, where the PPU will never reach them.
Re: How to delete / unload sprite? (nes 6502)
Yep, setting the Y position anywhere between $F0-$FF is all you need to do; you can actually leave X position, tile number, and attribute alone if you want.
Re: How to delete / unload sprite? (nes 6502)
Do note that most games do not bother with deleting specific sprites though, since they don't statically allocate OAM slots to specific objects.
In the vast majority of games, OAM slots start "empty" (Y > 239) every frame, and the function that draws meta-sprites uses OAM slots as needed, often in pseudo-random order, so that sprite priorities are cycled over time (creating sprite cycling instead of dropout).
Since the sprite list is rebuilt from scratch every frame, there's no need to "erase" specific objects, you just don't draw them at all.
In the vast majority of games, OAM slots start "empty" (Y > 239) every frame, and the function that draws meta-sprites uses OAM slots as needed, often in pseudo-random order, so that sprite priorities are cycled over time (creating sprite cycling instead of dropout).
Since the sprite list is rebuilt from scratch every frame, there's no need to "erase" specific objects, you just don't draw them at all.
Re: How to delete / unload sprite? (nes 6502)
Thank you for your answers!
-
- Posts: 10
- Joined: Tue May 04, 2021 8:49 pm
Re: How to delete / unload sprite? (nes 6502)
Basic but nevertheless critical information for me! By doing this and handle all object logic outside the OAM-buffer I managed to solve a lot of the obstacles I ran into.tokumaru wrote: ↑Wed Jan 19, 2022 1:54 pm In the vast majority of games, OAM slots start "empty" (Y > 239) every frame, and the function that draws meta-sprites uses OAM slots as needed, often in pseudo-random order, so that sprite priorities are cycled over time (creating sprite cycling instead of dropout).
But I don’t know if my solution is the most optimal one. I have a loop in NMI that looks like this:
LDA FF
LDX 00
ClearOAM:
STA $200, X
INX
INX
INX
INX
BNE clearOAM
But that’s 960+ cycles every frame. Is that the way to go?
Re: How to delete / unload sprite? (nes 6502)
That's 1027 cycles in total, which is indeed expensive. A common solution is to only hide the sprites you don't use, though that may be difficult depending on your sprite shuffling algorithm. The nice thing about this is that the cost of the function goes down as the number of sprites used goes up (so it's cheaper when your other CPU costs are higher).
Another option is to unroll the loop. For example, you could do something like this:
That's only 499 cycles, a substantial improvement.
If you're willing to use an illegal instruction, the AXS #immediate instruction (opcode $CB: (A & X) - immediate) seems to be a reliable one and can cut down on this further:
That's only 403 cycles.
Another option is to unroll the loop. For example, you could do something like this:
Code: Select all
LDA #$FF
LDX #$3C
loop:
STA $0203,X
STA $0243,X
STA $0283,X
STA $02C3,X
DEX
DEX
DEX
DEX
BPL loop
If you're willing to use an illegal instruction, the AXS #immediate instruction (opcode $CB: (A & X) - immediate) seems to be a reliable one and can cut down on this further:
Code: Select all
LDA #$FF
LDX #$3C
loop:
STA $0200,X
STA $0240,X
STA $0280,X
STA $02C0,X
AXS #$04
BPL loop
Re: How to delete / unload sprite? (nes 6502)
That's what I always do. After all the game logic has been processed and all objects have generated their OAM entries, a simple loop puts any remaining sprites off screen. The exact implementation of this loop will vary depending on how you select free OAM slots for use (some games fill the OAM sequentially, others advance a prime number of slots after each sprite, etc.), but you can just use the same logic to keep selecting slots and hiding the sprites until there are no more free sprites.
-
- Posts: 10
- Joined: Tue May 04, 2021 8:49 pm
Re: How to delete / unload sprite? (nes 6502)
Thanks both of you! I will meditate on your replies.
I’ve learnt that figuring out things the hard way often pays off in the long run, but sometimes you run into a wall.
I’ve learnt that figuring out things the hard way often pays off in the long run, but sometimes you run into a wall.
tokumaru wrote: ↑Thu Apr 28, 2022 9:01 amThat's what I always do. After all the game logic has been processed and all objects have generated their OAM entries, a simple loop puts any remaining sprites off screen. The exact implementation of this loop will vary depending on how you select free OAM slots for use (some games fill the OAM sequentially, others advance a prime number of slots after each sprite, etc.), but you can just use the same logic to keep selecting slots and hiding the sprites until there are no more free sprites.
Re: How to delete / unload sprite? (nes 6502)
Copy_con^Z wrote: ↑Thu Apr 28, 2022 5:46 am LDA FF
LDX 00
ClearOAM:
STA $200, X
INX
INX
INX
INX
BNE clearOAM
But that’s 960+ cycles every frame. Is that the way to go?
I found this too slow as well. That's why I used the other extreme:
Code: Select all
.repeat 64, spriteId
STA Sprites + spriteId * 4
.endrepeat
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Re: How to delete / unload sprite? (nes 6502)
I go half-and-half and use a partially unrolled loop (verbatim from my own code):
Code: Select all
; Clear all sprites (set y positions to FF) [Affects Y]
sprmanager_clear
ldy #$00 ;The ADC is the only thing that can modify C, so clear it out here
clc ;(saves 2 cycles per loop, 16-2=14 (clc still happens once) in this case)
sprmanager_clear_loop
lda #$ff ;It's quicker to just set all of the Y positions to FF
sta spr_oam,y ;instead of actually clearing out the contents entirely.
sta spr_oam+$4,y ;Partially unrolled loop for an additional speed boost
sta spr_oam+$8,y
sta spr_oam+$C,y
sta spr_oam+$10,y
sta spr_oam+$14,y
sta spr_oam+$18,y
sta spr_oam+$1C,y
tya
adc #$20
tay
bcc sprmanager_clear_loop
lda spr_config ;This part is for OAM shuffling
adc #$33 ;If we get here, the carry bit MUST be set, so let's take advantage of it
sta spr_config ;by leaving out the CLC again (woo hoo, another 2 cycles saved)
sta spr_index
rts