AllDarnDavey
Active member
An issue I kept running into in the MetroidVania Module was I would occasionally get duplicate monsters loaded into the same spot. It's not always easy to tell, especially if their AI behavior is in sync, but it can cause some major slowdown as what looks like a single enemy is actually two on top of each other (and I've even seen three stacked up). If your duplicate enemies do things like fire projectiles then it'll tank performance even faster. Below is an example of what looks like 2 enemies, but in fact is 4, Mesen's Sprite Viewer shows the double stack of enemies, but the slowdown is immediately noticeable.
What's happening is when the camera seam (1/2 a screen width offscreen in either direction) hits the enemy load position, the enemy is loaded and prepped to activate once visible. If you scroll back and forth a bit (easy to do while wall jumping or dodging bullets), your scroll back might not be far enough to trigger unloading the enemy, and then when you scroll forward again, a second duplicate enemy is loaded on the same spot.
To fix this I made a change to the doUpdateCamera routine bit of code that loads the monsters, so it double checks to see if there is already a monster loaded into that X position first. I could've had it check for duplicate X position, then also check Y position, but I only did an X check to save a few CPU cycles. It does mean that my monsters have to be set at least one tile apart horizontally, but I'm okay with that -- in fact it makes it easy to see if the script is working, if I put 2 monsters in the same X position and 1 doesn't load, I know the script is doing it's job.
Just replace the checkSeamForMonsterPosition section of your doUpdateCamera.asm routine script (it's should be right at the end), with this version.
EDIT: DON'T REPLACE THE ENTIRE FILE WITH THIS CODE, JUST THE LAST SECTION
What's happening is when the camera seam (1/2 a screen width offscreen in either direction) hits the enemy load position, the enemy is loaded and prepped to activate once visible. If you scroll back and forth a bit (easy to do while wall jumping or dodging bullets), your scroll back might not be far enough to trigger unloading the enemy, and then when you scroll forward again, a second duplicate enemy is loaded on the same spot.
To fix this I made a change to the doUpdateCamera routine bit of code that loads the monsters, so it double checks to see if there is already a monster loaded into that X position first. I could've had it check for duplicate X position, then also check Y position, but I only did an X check to save a few CPU cycles. It does mean that my monsters have to be set at least one tile apart horizontally, but I'm okay with that -- in fact it makes it easy to see if the script is working, if I put 2 monsters in the same X position and 1 doesn't load, I know the script is doing it's job.
Just replace the checkSeamForMonsterPosition section of your doUpdateCamera.asm routine script (it's should be right at the end), with this version.
Code:
checkSeamForMonsterPosition:
;; y is loaded before subroutine.
LDA (pointer6),y
STA temp
ASL
ASL
ASL
ASL
STA temp2
LDA scrollUpdateColumn
AND #%11110000
CMP temp2
BNE +noMonsterToLoadInThisColumn
;;check if a monster is already loaded in that x position first
LDX #$00
monsterDupeCheck:
LDA Object_x_hi,x
CMP temp2
BEQ +noMonsterToLoadInThisColumn
INX
CPX #TOTAL_MAX_OBJECTS
BNE monsterDupeCheck
LDA temp
AND #%11110000
STA temp1
CMP #%11110000
BEQ +noMonsterToLoadInThisColumn
CreateObjectOnScreen temp2, temp1, tempD, #$00, scrollUpdateScreen
+noMonsterToLoadInThisColumn:
RTS
EDIT: DON'T REPLACE THE ENTIRE FILE WITH THIS CODE, JUST THE LAST SECTION