NES ASM Tips – Box Collision

One of the most important parts in any game, code wise, is to have some form of collision detection between sprites. This is Assembly Code snippet ( using NESASM3) should help you out when it comes to box to box collision and uses little space, so should be quite fast. We’re only using the A register AND 9 bits of RAM for simplicity.

Here we go, first with the variables being declared in Zero Page:

spriteCollider1Top = $40 ; SPRITE COLLIDER 1 TOP
spriteCollider1Left = $41 ; SPRITE COLLIDER 1 LEFT
spriteCollider1Width = $42 ; SPRITE COLLIDER 1 WIDTH
spriteCollider1Height = $43 ; SPRITE COLLIDER 1 HEIGHT

spriteCollider2Top = $44 ; SPRITE COLLIDER 2 TOP
spriteCollider2Left = $45 ; SPRITE COLLIDER 2 LEFT
spriteCollider2Width = $46 ; SPRITE COLLIDER 2 WIDTH
spriteCollider2Height = $47 ; SPRITE COLLIDER 2 HEIGHT

spriteCollisionResult = $48 ; SPRITE COLLISION RESULT - 0 = NO COLLISION, 1 = COLLISION

Next Up, The Function Itself, with an explanation of what we’re doing:

;COLLISION DETECTION BETWEEN SPRITES - RETURNS THE RESULT AS 0 OR 1
DetectCollisions:
PHA ; STORE OUR CURRENT A REGISTER ON THE STACK
LDA #$00
STA spriteCollisionResult ;INITIALIZE spriteCollisionResult to 0 (no collision found)
; START FIRST CASE
CLC                     ; CLEAR OUR CARRY FLAG
LDA spriteCollider1Left ; LOAD A WITH X1
ADC spriteCollider1Width ; ADD THE W1 TO X1
CMP spriteCollider2Left ; COMPARE X2 WITH A
BMI FinishCollisionCheckBetter ; IF GREATER, THEN SKIP THE REST, RETURN 0

; START 2ND CASE
CLC ; CLEAR OUR CARRY FLAG
LDA spriteCollider2Left ;LOAD A WITH X2
ADC spriteCollider2Width ; ADD W2 TO X2
CMP spriteCollider1Left ; COMPARE WITH LEFT OF X1
BMI FinishCollisionCheckBetter ; IF LESS THEN, SKIP THE REST, RETURN 0

; START THIRD BRACKET
CLC ; CLEAR OUR CARRY FLAG
LDA spriteCollider1Top ; LOAD A WITH Y1
ADC spriteCollider1Height ; ADD H1 TO Y1
CMP spriteCollider2Top ; COMPARE Y2 WITH A
BMI FinishCollisionCheckBetter ; IF LESS THEN, SKIP THE REST, RETURN 0

; START FOURTH BRACKET
CLC ; CLEAR OUR CARRY FLAG
LDA spriteCollider2Top ; LOAD A WITH Y2
ADC spriteCollider2Height ; ADD H2 TO Y2
CMP spriteCollider1Top ; COMPARE Y1 WITH A
BMI FinishCollisionCheckBetter ; IF LESS THEN, SKIP THE REST, RETURN 0

;THERE WAS A COLLISION! - STORE OUR COLLISION RESULT
LDA #$01
STA spriteCollisionResult 

FinishCollisionCheckBetter:
PLA ; RESTORE OUR CURRENT A REGISTER FROM THE STACK

RTS ; RETURN TO MAIN GAME LOOP

So, to use this effectively, simply set your sprite bits up appropriately, then Jump to the function (well, subroutine) by calling:

JSR DetectCollisions

If there is a collision between the two points, spriteCollision Result should contain a value of 1, otherwise it’s just a 0

Hopefully, this has helped someone out there get past one of the stumbling blocks with NES ASM development.

Happy coding everyone!