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!

Why code NES games in ASM in 2018?

So, there’s a few reasons as to why I’ve chosen this for 2018:

The Challenge
There’s something about learning a new language, one that’s so different from anything I’ve learnt before, delving deep into the NES registers seems like a fun thing to try out also.

It’s The First “True” Console I owned
Yeah, like most kids I wanted a NES for bloody ages before I could place my tiny mitts on a controller, heck , I even remember the guy at the store attempting to sell me a megadrive instead back in the day, but my love for Megaman 2 from play sessions at my cousins house meant that simply wasn’t an option for 8 year old Ryan.

Even then, I wanted to make games for the console and would happily spend hours drawing out sprites on graph paper, even cutting out and drawing up fake cartridge boxes for games that I wanted to make happen. A racing game in the style of F1 race for the gameboy ( Turbo Racing on the NES was a regular favourite also back then ) and a platformer involving some fairly Mario-inspired little characters.

NOSTALGIA BE PRAISED!
Yeah! There’s a big chunk of nostalgia going on here, childhood hopes and dreams which never really left me. This year is certainly the year to accomplish them.

Now If you’ll excuse me, it’s back to the code for me 🙂

Wish me luck!

Background collisions, SFX and TURBO!

Well, today went really well, I fixed up my collision routines with the scrolling background, yup, it was using a simple offset, with a case for looping every 32 row increments, seems to work well. Possibly un-optimised but good enough so far.

There’s some rudimentary noises from both cars on screen based on their speed and distance from each other, also collision noises are in there now.

The fuel-o-meter has turned into a working turbo bar to help catch-up or overtake other racers. It’s getting there, but I’m down to 4kb of ROM remaining now and the racer A.I. needs improving on the sly. I’d like to get some BGM in there also somehow.

CPU Usage is getting pretty high now though, so I may need to inestigate into other ways to load my level up. Setting colours for each tile through a switch is probably slower than referencing another variable directly I imagine but, well, a balance needs to be struck.

Tomorrow I’ll most likely be sorting out the code into banks to save space and going from there with more advanced A.I. (Not simple homing, falling of the track A.I.) those cars need to fall foul to going off track also and that’s going to be inetresting to set-up correctly!

Screenshot tonight is from the gameboy classic mode where, yes. Identical cars. I’m not too fussed about that. I am fussed about adding some steering animation though!

Getting There