Destroy Me Edge Reaction Not Working on Projectiles (4.5.9 LR Platformer and Metroidvania Mods)

vanderblade

Active member
Has anybody else with a scrolling game that involves players shooting a lot run into this issue where the Destroy Me edge reaction doesn't work on player projectiles?

Because of this, if I stop and just fire into the edge of the screen, I can lock up my game quite easily.

My work around is to always encourage the player forward (it's a run and gun so it sort of works). I also use short destroy me timers on the player projectiles (although these seemingly don't work once the object exits the screen). I also use solids and enemies to absorb player projectiles. Now, this works for the most part. But I would REALLY like to skip collision checks on my player projectiles to save processing power and avoid just a little more slow down. Thing is, if I do this, there's a chance the player's projectiles will build up more just outside the screen and crash the game, and this is almost guaranteed on static boss fight screens.

So, how do we solve this? I can't be the only person who has encountered this.
 

vanderblade

Active member
So, in trying to solve one problem, I think I found a solution to this problem. It's the same solution!

Basically, I used this thread to solve an enemy left edge wrapping issue, but by using the below, I think I also solved the issue with projectiles not destroying themselves.


Specifically, this bit:

In doHandleObjects.asm

Uncomment out the below code. Why is it commented out in the first place? Dunno. Fixes two major issues with the scrolling engine.

Code:
;CLC
;ADC #$10 ;; arbitrary - approximate width of objects
 

vanderblade

Active member
Nice catch @vanderblade ! my fix was just to slow down the projectiles and have the destroy themselves before the could leave the edge
Turns out it doesn't really fix this after all. False hope. I was slowing down projectiles and having them destroy themselves, but because of my chunky sprites, I was experimenting (and hoping) to use projectiles that were really fast and only existed for a few frames.

Basically, I'm trying to balance between trying to get rid of slowdown while not breaking my game.

So, this issue still persists. Is there anyway to get projectiles in a scrolling mod to actually destroy themselves at screen edge!?
 

9Panzer

Well-known member
Damn. This one is a pretty big issue. In Panzer2 I have a playable character that shoots arrows - I'm regularly crashing the game and getting messed up.
Hopefully someone can look at this a little closer that understands the Metrodvania module.
 

9Panzer

Well-known member
@vanderblade I was tinking with the doDrawSprites_PlatformBase.asm and found part of it refering to "thistileisOffScreen" I added a check here against my player weapon and I think I may have fixed it. Can you try on your build?

Its around line 315.
;;;;;;;;;;;; Here, we need to evaluate if this tile should be drawn
;;;;;;;;;;;; based on the comparison to camX.
JSR evaluateTileAgainstCameraPosition
BEQ thisTileIsInCamRange

LDA Object_type,x ;;;; This is the start of the new check.
CMP #02 ;;;; this is my players weapon.
BNE +NotWeapon
DestroyObject
+NotWeapon ;;;;; this is the end of my snippet.


JMP thisTileIsOffScreen
thisTileIsInCamRange



DrawSprite tempA, tempB, tempC, tempD
 

dale_coop

Moderator
Staff member
Instead of:
Code:
LDA Object_type,x ;;;; This is the start of the new check.
CMP #02 ;;;; this is my players weapon.
BNE +NotWeapon

You could also check the "player weapon" and "monster weapon" flags:
Code:
LDA Object_flags,x ;;;; This is the start of the new check.
AND #%00010100 ;;;; if player weapon or monster weapon.
BEQ +NotWeapon
 

vanderblade

Active member
This is great, but I use special draw code for my projectiles to save processing time. I've tried to JMP to the part of the code right before this check after the projectiles are drawn but I get errors. @dale_coop, if I have unique draw code up top, where can I then jump to avoid errors?

For example, after finding that the sprite is a specific kind of projectile, I manually draw the sprite and then JMP to doneDrawingThisSprite. I've tried jumping to just before the JSR check but I get glitches. I'll keep working on it. This would be excellent if it works.

Code:
+isPlayerProjectile
        ;;; DRAW PLAYER PROJECTILE
        GetActionStep temp
        CMP #$00
        BNE +buzzCheck
            JMP +drawNormalProjectile
        
        +buzzCheck
        CMP #$01
        BEQ +drawBuzzSaw
            JMP +BuzzSawReverseCheck
            
        +drawBuzzSaw   
        DrawSprite tempA, tempB, #$49, #%00000000
        JMP doneDrawingThisSprite
 
Last edited:

9Panzer

Well-known member
Nice @dale_coop ! I didn't realize you could specify a number for for the CMP for an object type. I thought you had to use the bytes.

@vanderblade Try switching the JMP from doneDrawingThisSprite to JMP doDrawSpritesLoop then you will run the check properly for the offscreen portion.

Also, I ran into some issues at my home PC with having the code in the sprite loop.
You may want to try putting the code snippet after thisTileIsOffscreen

thisTileIsOffScreen:


LDA Object_type,x
CMP #02
BNE +NotWeapon
DestroyObject
+NotWeapon



;;;;;;;;;;; check to see if the row is finished.
 

vanderblade

Active member
Cheers for this. Unfortunately, it's no dice for me still.

Does this definitely work for you? Just to test the base code, I got rid of my bespoke draw code and ran this. But I was still able to freeze up my game by firing a multi-shot weapon into the left side of the screen for several seconds. Maybe something was off. If it works for you for sure, then I need to look into it on my end some more. And eventually, I'll need to try to integrate this into my weird ass sprite draw script.

The hope is, of course, that players have no need to turn around and fire madly into the left screen edge on scrolling sections since all the action is coming at them from the right. But until I can fix the issue, it remains a game-breaking bug.
 

9Panzer

Well-known member
I took another look and I can't figure out whats not working for you. This totally fixed my issue.
Maybe send me over what you have - its gotta be something simple.

;;;;;;;;;;;; Here, we need to evaluate if this tile should be drawn
;;;;;;;;;;;; based on the comparison to camX.


JSR evaluateTileAgainstCameraPosition
BEQ thisTileIsInCamRange

LDA Object_flags,x ;;;; This is the start of the new check.
AND #%00010100 ;;;; if player weapon or monster weapon.
BEQ +NotWeapon
DestroyObject
+NotWeapon ;;;;; this is the end of my snippet.

JMP thisTileIsOffScreen
thisTileIsInCamRange

DrawSprite tempA, tempB, tempC, tempD

thisTileIsOffScreen:
 
@vanderblade I was tinking with the doDrawSprites_PlatformBase.asm and found part of it refering to "thistileisOffScreen" I added a check here against my player weapon and I think I may have fixed it. Can you try on your build?

Its around line 315.
Trying to do something else on impact with edge with the player object
Specifically trying to flip the sprite and move the opposite direction... works with the right side but not the left:
``` LDA Object_flags,x ;;;; This is the start of the new check.
AND #%00000010 ;;;; if player
BEQ +NotPlayer
LDX player1_object
LDA Object_x_hi,x
CMP #$80
BCC +isRight
LDA #$01
STA ScreenFlip
ChangeFacingDirection player1_object, #FACE_LEFT
LDA #%00000000
STA ScreenFlags00
JMP +NotPlayer
+isRight
LDA #$00
STA ScreenFlip
ChangeFacingDirection player1_object, #FACE_RIGHT
LDA #%00000000
STA ScreenFlags00
+NotPlayer``
Is there something I'm missing?
 
Trying to do something else on impact with edge with the player object
Specifically trying to flip the sprite and move the opposite direction... works with the right side but not the left:

Is there something I'm missing?
okay it's something to do with how the script detects the right side of the screen...
evaluateTileAgainstCameraPosition:

LDA Object_x_hi,x
STA pointer
LDA Object_screen,x
AND #%00001111
STA pointer+1

LDA pointer


Compare16 pointer+1, pointer, camX_hi, camX
; arg0 = high byte of first value
; arg1 = low byte of first value
; arg2 = high byte of second value
; arg3 = low byte of second value

+
JMP checkForDrawingOffCamera

++
;DestroyObject
LDA #$01
RTS
checkForDrawingOffCamera
LDA Object_x_hi,x
CLC
ADC self_right
STA pointer
LDA Object_screen,x
ADC #$00
AND #%00001111
STA pointer+1

LDA camX

STA pointer5
LDA camX+1
clc
ADC #$01
STA temp
Compare16 pointer+1, pointer, temp, pointer5; camX
+
LDA #$01
rts
++
LDA #$00
rts
what's the easiest way for the Left?
 
okay it's something to do with how the script detects the right side of the screen...

what's the easiest way for the Left?
FIXED IT! just needed to check for this:
evaluateTileAgainstCameraRightPosition:
LDA Object_x_hi,x
STA pointer
LDA Object_screen,x
AND #%00001111
STA pointer+1

LDA pointer
Compare16 pointer+1, pointer, camX_hi, camX
+
JMP checkForDrawingOffCameraRight
++
LDA #$01
RTS

checkForDrawingOffCameraRight
LDA Object_x_hi,x
CLC
SBC self_left
STA pointer
LDA Object_screen,x
SBC #$00
AND #%00001111
STA pointer+1

LDA camX

STA pointer5
LDA camX+1
clc
ADC #$01
STA temp
Compare16 pointer+1, pointer, temp, pointer5; camX
+
LDA #$01
rts
++
LDA #$00
rts
 
Top Bottom