Collision detection problem with my project.

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
kikutano
Posts: 115
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Collision detection problem with my project.

Post by kikutano »

Hello to everyone,
I'm working on an Arkanoid clone for NES all in ASM 6052 just for fun, currently, in my game, the ball collide fine with the walls, with the paddle player and I'm really happy for this. But, when I try to compute the collision with the bricks, somethings goes wrong.

Code: Select all

;=====================================
; Ball Collision Detection With Bricks
;=====================================  
CheckCollisionOnAllBricks:
  LDX #$00
CheckCollisionOnAllBricksLoop:
  LDA brick_sprites, x
  
  ;Y MIN
  CMP BALL_POS_Y
  BCS PerformBallNotHitBrick 

  ;Y MAX
  CLC 
  ADC #$08
  CMP BALL_POS_Y
  BCC PerformBallNotHitBrick 

  ;X MIN
  INX 
  INX 
  INX
  LDA brick_sprites, x
  DEX
  DEX
  DEX
  CMP BALL_POS_X
  BCS PerformBallNotHitBrick

  ;X MAX
  CLC
  ADC #$18
  CMP BALL_POS_X
  BCC PerformBallNotHitBrick

  ; Collisione
PerformBallCollisionWithBrick:
  LDA #$01
  STA $0212
  JMP CCCOABContinueLoop

PerformBallNotHitBrick: 
  LDA #$00
  STA $0212
  JMP CCCOABContinueLoop

CCCOABContinueLoop:

  INX
  INX
  INX 
  INX 
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  
  CPX #$18
  BNE CheckCollisionOnAllBricksLoop
The collision detection with the ball is simple, i get the position of the ball and i check if the ball is in the brick corner, this for all bricks ( in this code there are only 2 bricks ), every bricks is composed by 3 tiles with 8 pixels of height and 12 pixels of weight. So i increase my X register to get the positions of the corners that are stored here:

Code: Select all

brick_sprites:
      ;yPos tile attr xPos
  
  .db $3A, $04, $0A, $70   ;sprite 0
  .db $3A, $05, $0A, $78   ;sprite 1
  .db $3A, $06, $0A, $7F   ;sprite 2

  .db $22, $04, $0A, $87   ;sprite 0
  .db $22, $05, $0A, $8F   ;sprite 1
  .db $22, $06, $0A, $97   ;sprite 2


The strange things is that if I use only one brick and finish the check by CPX #$0C, everythings works great, BUT if i put two bricks as in the example code and i finish the cicle by compater CPX #$18 for some reason it get just the second brick, the first brick is ignored. I really can't understand where I'm wrong. Anyone can help me?

Thanks a lot and sorry for my English! :)
User avatar
kikutano
Posts: 115
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Re: Collision detection problem with my project.

Post by kikutano »

I solved! :D

Code: Select all

;=====================================
; Ball Collision Detection With Bricks
;=====================================  
CheckCollisionOnAllBricks:
  LDX #$00
CheckCollisionOnAllBricksLoop:
  LDA brick_sprites, x
  
  ;Y MIN
  CMP BALL_POS_Y
  BCS PerformBallNotHitBrick ; La pallina si trova SOPRA il mattoncino, non ci sarà collisione

  ;Y MAX
  CLC 
  ADC #$08
  CMP BALL_POS_Y
  BCC PerformBallNotHitBrick ; La pallina si trova SOTTO il mattoncino, no collisione

  ;X MIN
  INX 
  INX 
  INX
  LDA brick_sprites, x
  DEX
  DEX
  DEX
  CMP BALL_POS_X
  BCS PerformBallNotHitBrick

  ;X MAX
  CLC
  ADC #$18
  CMP BALL_POS_X
  BCC PerformBallNotHitBrick

  ; Collisione
PerformBallCollisionWithBrick:
  LDA #$01
  STA $0212
 [b][i] JMP ComputeCollidingWithBrick[/i][/b]

PerformBallNotHitBrick: 
  LDA #$00
  STA $0212
  JMP CCCOABContinueLoop

CCCOABContinueLoop:

  INX
  INX
  INX 
  INX 
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  
  CPX #$18
  BNE CheckCollisionOnAllBricksLoop

[i][b]ComputeCollidingWithBrick:[/b][/i]

When I get a collision, I've to to stop the cycle and exiting and compute the collision in

Code: Select all

ComputeCollidingWithBrick: 
, the previous code works, but if i don't exit to the cycle when I get a collision, the next interaction on the next brick will set the collision as False.

Man, ASM programming is so insane :P.
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Collision detection problem with my project.

Post by pubby »

Glad you figured it out kikutano!

Now that it's working here are a few tricks which can speed up your code:

Code: Select all

  BCS PerformBallNotHitBrick ; La pallina si trova SOPRA il mattoncino, non ci sarà collisione

  ;Y MAX
  CLC 
CLC is redundant here. The BCS above it ensures that the carry bit will always be 0 at this point.

Code: Select all

  INX 
  INX 
  INX
  LDA brick_sprites, x
  DEX
  DEX
  DEX
Can be written as "LDA brick_sprites+3, x". No need for INX/DEX at all.

Code: Select all

  ; Collisione
PerformBallCollisionWithBrick:
  LDA #$01
  STA $0212
   JMP ComputeCollidingWithBrick

PerformBallNotHitBrick: 
  LDA #$00
  STA $0212
  JMP CCCOABContinueLoop
One thing you can do is use the carry bit to return this information, rather than a memory location. That tends to easier.

Code: Select all

  INX
  INX
  INX 
  INX 
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  
Try using this instead:

Code: Select all

CLC
TXA
ADC #12
TAX
  

Then end result would be something like:

Code: Select all

CheckCollisionOnAllBricks:
  LDX #$00
CheckCollisionOnAllBricksLoop:
  LDA brick_sprites, x
  
  ;Y MIN
  CMP BALL_POS_Y
  BCS PerformBallNotHitBrick ; La pallina si trova SOPRA il mattoncino, non ci sarà collisione

  ;Y MAX
  ADC #$08
  CMP BALL_POS_Y
  BCC PerformBallNotHitBrick ; La pallina si trova SOTTO il mattoncino, no collisione

  ;X MIN
  LDA brick_sprites+3, x
  CMP BALL_POS_X
  BCS PerformBallNotHitBrick

  ;X MAX
  ADC #$18
  CMP BALL_POS_X
  BCS PerformBallCollisionWithBrick

PerformBallNotHitBrick: 
  CLC
  TXA
  ADC #12
  TAX
  
  CPX #$18
  BCC CheckCollisionOnAllBricksLoop
  CLC
PerformBallCollisionWithBrick:
  RTS
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Collision detection problem with my project.

Post by pubby »

BTW, you probably know this, but Arkanoid uses the background to draw blocks and not sprites. Collisions are checked by masking rounding the ball's position to the block size and looking up that position in a bit array.

This doesn't require loops, so it's more efficient than sprites. You can also display a lot more blocks by doing this.
User avatar
kikutano
Posts: 115
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Re: Collision detection problem with my project.

Post by kikutano »

Ok, thanks a lot for your suggestions. I never wrote anything in ASM, so I'm a complete newbie. :) Now I will try to put the Bricks on background.
Rahsennor
Posts: 479
Joined: Thu Aug 20, 2015 3:09 am

Re: Collision detection problem with my project.

Post by Rahsennor »

Too slow to make myself useful, but it's always good to see a new face here. Welcome to NESdev!
User avatar
kikutano
Posts: 115
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Re: Collision detection problem with my project.

Post by kikutano »

Thanks, probably I will post other questions during the development of my Arkanoid Clone :).
User avatar
kikutano
Posts: 115
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Re: Collision detection problem with my project.

Post by kikutano »

pubby wrote:BTW, you probably know this, but Arkanoid uses the background to draw blocks and not sprites. Collisions are checked by masking rounding the ball's position to the block size and looking up that position in a bit array.

This doesn't require loops, so it's more efficient than sprites. You can also display a lot more blocks by doing this.
Did you have some source or link that I can read? Thanks! :)
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Collision detection problem with my project.

Post by pubby »

Nope, I don't have any sources or articles :(

If you post what you're having trouble with then me or someone else can help you out though. :) Have you figured out how to change the background?

Also, there is an open source NES breakout game here you can look at: https://github.com/AleffCorrea/BrickBreaker
User avatar
kikutano
Posts: 115
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Re: Collision detection problem with my project.

Post by kikutano »

pubby wrote:Nope, I don't have any sources or articles :(

If you post what you're having trouble with then me or someone else can help you out though. :) Have you figured out how to change the background?

Also, there is an open source NES breakout game here you can look at: https://github.com/AleffCorrea/BrickBreaker
I'm working on using background and not sprites for bricks, if I had some issue I will ask here :P. Btw thanks for the link I will try to learn somethings from that code.
User avatar
kikutano
Posts: 115
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Re: Collision detection problem with my project.

Post by kikutano »

I'm putting all on background, now I've to rewrite the collision detection with the bricks :). The hard part is understand how the palette and color works :D. I hope to release the source code as soon as I can.

Image
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Collision detection problem with my project.

Post by pubby »

Looks great!
User avatar
Punch
Posts: 365
Joined: Sat Feb 16, 2013 11:52 am

Re: Collision detection problem with my project.

Post by Punch »

I'm the author of the brick breaker game ^^

To interpret collision detection here's what it does:

"Move" the ball temporarily.

Translate the coordinates of the ball in relation to the tilemap's start position (in your case, subtract 16 to the ball's X and Y coords since the "play area" starts at (16,16))

For each corner of the ball bounding box, divide its coordinates by 16 (since my game uses 16x16 blocks, you might want to divide X by 16 and Y by 8 in your case). Those 4 values are the blocks in the background in which the ball is currently touching/inside.

Clear two bytes, to be used as flags for horizontal and vertical movement collision.

For each of the 4 tiles: check what type of tile it is (empty, solid, indestructible, resistant, explosive, hole, you name it) and apply the proper response to the collision (destroy tile?), but don't change the ball direction yet. Evaluate the balls movement vector and if the ball is supposed to change its horizontal/vertical direction after colliding, turn on their respective flags.

After checking all 4 tiles, finally use the flags to change the ball's trajectory.

End.


I hope it's kinda clear, let us know if you still need help.
This is a block of text that can be added to posts you make. There is a 255 character limit.
User avatar
kikutano
Posts: 115
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Re: Collision detection problem with my project.

Post by kikutano »

Punch wrote:I'm the author of the brick breaker game ^^

To interpret collision detection here's what it does:

"Move" the ball temporarily.

Translate the coordinates of the ball in relation to the tilemap's start position (in your case, subtract 16 to the ball's X and Y coords since the "play area" starts at (16,16))

For each corner of the ball bounding box, divide its coordinates by 16 (since my game uses 16x16 blocks, you might want to divide X by 16 and Y by 8 in your case). Those 4 values are the blocks in the background in which the ball is currently touching/inside.

Clear two bytes, to be used as flags for horizontal and vertical movement collision.

For each of the 4 tiles: check what type of tile it is (empty, solid, indestructible, resistant, explosive, hole, you name it) and apply the proper response to the collision (destroy tile?), but don't change the ball direction yet. Evaluate the balls movement vector and if the ball is supposed to change its horizontal/vertical direction after colliding, turn on their respective flags.

After checking all 4 tiles, finally use the flags to change the ball's trajectory.

End.


I hope it's kinda clear, let us know if you still need help.
Thanks a lot! :)
User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Re: Collision detection problem with my project.

Post by Sogona »

One thing that isn’t super trivial is figuring out how to “delete” nametable blocks - calculating the position in the nametable from the ball’s x and y position to draw new tiles to. It’s a bit more complicated than just dividing by 16 and looking up a byte in a collision map.
I can’t recall off the top of my head exactly how to do it, but it involves some 16-bit bit shifting. I know there are forum posts about it though. Basically you find the address of the first tile depending on where you collided, change it, and then since it appears you’re using 16x8 pixel metatiles, you’d just increment whatever PPU address you’re at and change that tile as well. Be sure to update your collision map in regular RAM as well.

Of course, you’d want to put this all into a buffer, and then perform the PPU updates during vblank. I don’t know if you have a VRAM buffer set up just yet; but there’s information on the wiki about it as well. Just something to think about.
Post Reply