It is currently Fri Nov 16, 2018 5:03 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Sat May 26, 2018 6:24 am 
Offline

Joined: Sat May 26, 2018 6:14 am
Posts: 49
Location: Italy
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:
;=====================================
; 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:
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! :)


Top
 Profile  
 
PostPosted: Sat May 26, 2018 6:45 am 
Offline

Joined: Sat May 26, 2018 6:14 am
Posts: 49
Location: Italy
I solved! :D

Code:
;=====================================
; 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:
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.


Top
 Profile  
 
PostPosted: Sat May 26, 2018 8:55 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 419
Glad you figured it out kikutano!

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

Code:
  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:
  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:
  ; 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:
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  INX
  INX
 

Try using this instead:


Code:
CLC
TXA
ADC #12
TAX
 



Then end result would be something like:

Code:
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


Top
 Profile  
 
PostPosted: Sat May 26, 2018 8:58 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 419
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.


Top
 Profile  
 
PostPosted: Sat May 26, 2018 9:12 am 
Offline

Joined: Sat May 26, 2018 6:14 am
Posts: 49
Location: Italy
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.


Top
 Profile  
 
PostPosted: Sun May 27, 2018 3:50 am 
Offline

Joined: Thu Aug 20, 2015 3:09 am
Posts: 414
Too slow to make myself useful, but it's always good to see a new face here. Welcome to NESdev!


Top
 Profile  
 
PostPosted: Sun May 27, 2018 11:42 pm 
Offline

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


Top
 Profile  
 
PostPosted: Tue May 29, 2018 12:01 am 
Offline

Joined: Sat May 26, 2018 6:14 am
Posts: 49
Location: Italy
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! :)


Top
 Profile  
 
PostPosted: Tue May 29, 2018 1:35 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 419
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


Top
 Profile  
 
PostPosted: Tue May 29, 2018 5:15 am 
Offline

Joined: Sat May 26, 2018 6:14 am
Posts: 49
Location: Italy
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.


Top
 Profile  
 
PostPosted: Tue Jun 05, 2018 8:45 am 
Offline

Joined: Sat May 26, 2018 6:14 am
Posts: 49
Location: Italy
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


Top
 Profile  
 
PostPosted: Tue Jun 05, 2018 8:05 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 419
Looks great!


Top
 Profile  
 
PostPosted: Wed Jun 06, 2018 12:46 am 
Offline
User avatar

Joined: Sat Feb 16, 2013 11:52 am
Posts: 320
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.


Top
 Profile  
 
PostPosted: Wed Jun 06, 2018 5:02 am 
Offline

Joined: Sat May 26, 2018 6:14 am
Posts: 49
Location: Italy
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! :)


Top
 Profile  
 
PostPosted: Wed Jun 06, 2018 9:20 pm 
Offline
User avatar

Joined: Thu Jul 23, 2015 7:54 pm
Posts: 181
Location: USA
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group