Enemies falling off ledges on the left side cause player to die in platformer

CluckFox

Active member
The following modification allowed the snail to walk off the left of the screen with Null edge-reaction and no player damage. There is a related issue where the monster walks off a slightly-scrolled screen and the player backtracks, but I haven't debugged it yet. Give this doCompareBoundingBoxes a try and let me know if anything changes:

Code:
;;;
doCompareBoundingBoxes:
    ;;; more complicated than this
    ; LDA self_screen
    ; CMP other_screen
    ; BNE noBboxCollision
   
   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Here we will check the horizontal collision.
;;; First we need to check the RIGHT SCREEN + RIGHT BBOX of self against the
;;; LEFT SCREEN + LEFT BBOX of other.  If it is less, then there is no collision.

    LDA self_screen_right
    CMP other_screen_left
    BEQ +theseAreEqual
        ;;; the self screen and other screen are not equal.
        ;;; But if the self screen is MORE than the other screen,
        ;;; it is still possible that this could return a collision.
        JMP +checkOtherSide
   
    +theseAreEqual
        ;;; CluckFox for Forums - wrap-around glitch test
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        LDA other_screen_left
        CMP other_screen_right
        BEQ +keepChecking       ;; other left == other right
        BCC +keepChecking       ;; other left < other right
        JMP +noBboxCollision    ;; other left > other right???
       
        +keepChecking
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   
        ;;; we need to check the *other* side
        LDA self_screen_left
        CMP other_screen_right
        BEQ +normalBoundsCheck
            ;; this means bounds are being straddled.
            LDA bounds_right
            CMP other_left
            BCC +noBboxCollision
                JMP +hCol
        +normalBoundsCheck
   
        ;; the self screen and other screen are equal
        ;; which means now it is a matter of checking the
        ;; self right bbox against the left bbox.
        LDA bounds_right
        CMP other_left
        BCC +noBboxCollision
   
   
    +continueCollisionCheck
    +checkOtherSide   
    LDA self_screen_left
    CMP other_screen_right
    BEQ +theseAreEqual
        JMP +noBboxCollision   
    +theseAreEqual
        ;;; check the *other* side
        LDA self_screen_right
        CMP other_screen_left
        BEQ +normalBoundsCheck
            JMP +noBboxCollision
        +normalBoundsCheck
            LDA bounds_left
            CMP other_right
            BCS +noBboxCollision
       
+hCol

    LDA other_bottom
    CMP bounds_top
    BCC noBboxCollision
    LDA bounds_bottom
    CMP other_top
    BCC noBboxCollision
;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;   
   
   
   
    LDA #$01 ;; read that YES, there was a collision here. (could make this the object ID)
    RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   
noBboxCollision;; there is no collision here horizontally.
    LDA #$00 ;; read that NO, there was no collision.
    RTS
   
   
getOtherColBox:
    TYA
    PHA

        ; LDA Object_x_hi,x
        ; CLC
        ; ADC #$10
        ; LDA Object_screen,x
        ; ADC #$00
        ; STA other_screen_right
        LDY Object_type,x
       
        LDA Object_x_hi,x
        CLC
        ADC ObjectBboxLeft,y
        STA other_left
        LDA Object_screen,x
        ADC #$00
        STA other_screen_left
       
        LDA other_left
        CLC
        ADC ObjectWidth,y
        STA other_right
        LDA Object_screen,x
        ADC #$00
        STA other_screen_right
   
       
        LDA other_right

        SEC
        SBC other_left
        LSR
        STA other_center_x
       
        LDA ObjectBboxTop,y
        CLC
        ADC Object_y_hi,x
        STA other_top
        CLC
        ADC ObjectHeight,y
        STA other_bottom
        SEC
        SBC other_top
        LSR
        STA other_center_y ;; self center in the vertical direction.
        ; LDA Object_screen,x
        ; STA other_screen
   
    PLA
    TAY
    RTS
 

CluckFox

Active member
@CluckFox That did it! Wow, thanks so much! Is there any way to submit that fix to the NesMaker people? Seems like a good update to their scrolling code.
I don't know if the change is ready for the core or module distributions, but since I already posted it to the Forums the NESMaker folks are allowed and welcome to do with it what they wish.
 

dale_coop

Moderator
Staff member
They come here to check those bugs, often...
Also, in each new updates, usually, a LOT of code has been changed. That script might not be the same, and it sure might have been already fixed ;)
 

CluckFox

Active member
I should, then, add the disclaimer that the above code is not meant as a lasting (or even correct) solution. It's a debugging tool and work-around for games-in-progress between updates.
 

vanderblade

Active member
The following modification allowed the snail to walk off the left of the screen with Null edge-reaction and no player damage. There is a related issue where the monster walks off a slightly-scrolled screen and the player backtracks, but I haven't debugged it yet. Give this doCompareBoundingBoxes a try and let me know if anything changes:

Code:
;;;
doCompareBoundingBoxes:
    ;;; more complicated than this
    ; LDA self_screen
    ; CMP other_screen
    ; BNE noBboxCollision
  
  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Here we will check the horizontal collision.
;;; First we need to check the RIGHT SCREEN + RIGHT BBOX of self against the
;;; LEFT SCREEN + LEFT BBOX of other.  If it is less, then there is no collision.

    LDA self_screen_right
    CMP other_screen_left
    BEQ +theseAreEqual
        ;;; the self screen and other screen are not equal.
        ;;; But if the self screen is MORE than the other screen,
        ;;; it is still possible that this could return a collision.
        JMP +checkOtherSide
  
    +theseAreEqual
        ;;; CluckFox for Forums - wrap-around glitch test
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        LDA other_screen_left
        CMP other_screen_right
        BEQ +keepChecking       ;; other left == other right
        BCC +keepChecking       ;; other left < other right
        JMP +noBboxCollision    ;; other left > other right???
      
        +keepChecking
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
        ;;; we need to check the *other* side
        LDA self_screen_left
        CMP other_screen_right
        BEQ +normalBoundsCheck
            ;; this means bounds are being straddled.
            LDA bounds_right
            CMP other_left
            BCC +noBboxCollision
                JMP +hCol
        +normalBoundsCheck
  
        ;; the self screen and other screen are equal
        ;; which means now it is a matter of checking the
        ;; self right bbox against the left bbox.
        LDA bounds_right
        CMP other_left
        BCC +noBboxCollision
  
  
    +continueCollisionCheck
    +checkOtherSide  
    LDA self_screen_left
    CMP other_screen_right
    BEQ +theseAreEqual
        JMP +noBboxCollision  
    +theseAreEqual
        ;;; check the *other* side
        LDA self_screen_right
        CMP other_screen_left
        BEQ +normalBoundsCheck
            JMP +noBboxCollision
        +normalBoundsCheck
            LDA bounds_left
            CMP other_right
            BCS +noBboxCollision
      
+hCol

    LDA other_bottom
    CMP bounds_top
    BCC noBboxCollision
    LDA bounds_bottom
    CMP other_top
    BCC noBboxCollision
;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;  
  
  
  
    LDA #$01 ;; read that YES, there was a collision here. (could make this the object ID)
    RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
noBboxCollision;; there is no collision here horizontally.
    LDA #$00 ;; read that NO, there was no collision.
    RTS
  
  
getOtherColBox:
    TYA
    PHA

        ; LDA Object_x_hi,x
        ; CLC
        ; ADC #$10
        ; LDA Object_screen,x
        ; ADC #$00
        ; STA other_screen_right
        LDY Object_type,x
      
        LDA Object_x_hi,x
        CLC
        ADC ObjectBboxLeft,y
        STA other_left
        LDA Object_screen,x
        ADC #$00
        STA other_screen_left
      
        LDA other_left
        CLC
        ADC ObjectWidth,y
        STA other_right
        LDA Object_screen,x
        ADC #$00
        STA other_screen_right
  
      
        LDA other_right

        SEC
        SBC other_left
        LSR
        STA other_center_x
      
        LDA ObjectBboxTop,y
        CLC
        ADC Object_y_hi,x
        STA other_top
        CLC
        ADC ObjectHeight,y
        STA other_bottom
        SEC
        SBC other_top
        LSR
        STA other_center_y ;; self center in the vertical direction.
        ; LDA Object_screen,x
        ; STA other_screen
  
    PLA
    TAY
    RTS
Thanks for this! I only tested it out once, but there were no bugs, and it "so far" has eradicated the issue. More testing to do, though.
 

baardbi

Well-known member
The following modification allowed the snail to walk off the left of the screen with Null edge-reaction and no player damage. There is a related issue where the monster walks off a slightly-scrolled screen and the player backtracks, but I haven't debugged it yet. Give this doCompareBoundingBoxes a try and let me know if anything changes:

Code:
;;;
doCompareBoundingBoxes:
    ;;; more complicated than this
    ; LDA self_screen
    ; CMP other_screen
    ; BNE noBboxCollision
  
  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Here we will check the horizontal collision.
;;; First we need to check the RIGHT SCREEN + RIGHT BBOX of self against the
;;; LEFT SCREEN + LEFT BBOX of other.  If it is less, then there is no collision.

    LDA self_screen_right
    CMP other_screen_left
    BEQ +theseAreEqual
        ;;; the self screen and other screen are not equal.
        ;;; But if the self screen is MORE than the other screen,
        ;;; it is still possible that this could return a collision.
        JMP +checkOtherSide
  
    +theseAreEqual
        ;;; CluckFox for Forums - wrap-around glitch test
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        LDA other_screen_left
        CMP other_screen_right
        BEQ +keepChecking       ;; other left == other right
        BCC +keepChecking       ;; other left < other right
        JMP +noBboxCollision    ;; other left > other right???
      
        +keepChecking
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
        ;;; we need to check the *other* side
        LDA self_screen_left
        CMP other_screen_right
        BEQ +normalBoundsCheck
            ;; this means bounds are being straddled.
            LDA bounds_right
            CMP other_left
            BCC +noBboxCollision
                JMP +hCol
        +normalBoundsCheck
  
        ;; the self screen and other screen are equal
        ;; which means now it is a matter of checking the
        ;; self right bbox against the left bbox.
        LDA bounds_right
        CMP other_left
        BCC +noBboxCollision
  
  
    +continueCollisionCheck
    +checkOtherSide  
    LDA self_screen_left
    CMP other_screen_right
    BEQ +theseAreEqual
        JMP +noBboxCollision  
    +theseAreEqual
        ;;; check the *other* side
        LDA self_screen_right
        CMP other_screen_left
        BEQ +normalBoundsCheck
            JMP +noBboxCollision
        +normalBoundsCheck
            LDA bounds_left
            CMP other_right
            BCS +noBboxCollision
      
+hCol

    LDA other_bottom
    CMP bounds_top
    BCC noBboxCollision
    LDA bounds_bottom
    CMP other_top
    BCC noBboxCollision
;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;  
  
  
  
    LDA #$01 ;; read that YES, there was a collision here. (could make this the object ID)
    RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
noBboxCollision;; there is no collision here horizontally.
    LDA #$00 ;; read that NO, there was no collision.
    RTS
  
  
getOtherColBox:
    TYA
    PHA

        ; LDA Object_x_hi,x
        ; CLC
        ; ADC #$10
        ; LDA Object_screen,x
        ; ADC #$00
        ; STA other_screen_right
        LDY Object_type,x
      
        LDA Object_x_hi,x
        CLC
        ADC ObjectBboxLeft,y
        STA other_left
        LDA Object_screen,x
        ADC #$00
        STA other_screen_left
      
        LDA other_left
        CLC
        ADC ObjectWidth,y
        STA other_right
        LDA Object_screen,x
        ADC #$00
        STA other_screen_right
  
      
        LDA other_right

        SEC
        SBC other_left
        LSR
        STA other_center_x
      
        LDA ObjectBboxTop,y
        CLC
        ADC Object_y_hi,x
        STA other_top
        CLC
        ADC ObjectHeight,y
        STA other_bottom
        SEC
        SBC other_top
        LSR
        STA other_center_y ;; self center in the vertical direction.
        ; LDA Object_screen,x
        ; STA other_screen
  
    PLA
    TAY
    RTS
Thank you thank you thank you! I've been trying to fix this bug for 18 months now, without any luck. I just applied this fix and did a full playthrough of my game. The "hit out of nowhere" problem only happened once. It might have been a coincidence. Looks like this problem is solved, which means I might be able to release my game before christmas after all :) :) :)
 

baardbi

Well-known member
@CluckFox you magnificent genius! Looks like you solved this thing :D I changed edge reaction on all my monsters to Null. Since I did that (as well as applying your fix) I didn't experience a single hit out of nowhere! This is amazing and I'm so grateful. Thank you again :)
 
Holy Shit! I had to get creative and just tell people in the Instruction Manual to kill all monsters and not let them run away from you or you'll die. Just playing the first level of my game with this applied took care of the known bad spots.

May all your days be awesome for this!
 
Top Bottom