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:
1 2 3 4 5 6 7 8 9 10 11 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
;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:
1 |
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!