Yeah...not sure if that's how collision detection works, but what I'm doing is: If the ball's y coordinate is the same as the paddle, AND if it falls within the range of the paddles surface, then it's a collision so bounce the ball. I check the x-coordinate of my paddle, which is composed of 2 sprites. that's why you see a comparison of ballx with $0207 and $020B, but I can create variables for those to be safe.
That's not my entire code, just a snippet. I can post all of it. Been going over this for several days, and can't see why it goes through sometimes.
Code:
.inesprg 1 ; 1x 16KB PRG code
.ineschr 1 ; 1x 8KB CHR data
.inesmap 0 ; mapper 0 = NROM, no bank swapping
.inesmir 1 ; background mirroring
.rsset $0000 ;;start variables at ram location 0
ballx .rs 1
bally .rs 1
motion .rs 1
motiony .rs 1
buttons .rs 1 ; player 1 gamepad buttons, one bit per button
paddleright .rs 1
RIGHTWALL = $F0 ; when ball reaches one of these, do something
TOPWALL = $20
BOTTOMWALL = $E0
LEFTWALL = $04
;;;;;;;;;;;;;;;
.bank 0
.org $8000
ballcolor: .incbin "test.dat"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;STORE THE INITIAL POSITION OF THE BALL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDA #$80
STA ballx
STA bally
LDA #$01
STA motion
STA motiony
RESET:
SEI ; disable IRQs
CLD ; disable decimal mode
LDX #$40
STX $4017 ; disable APU frame IRQ
LDX #$FF
TXS ; Set up stack
INX ; now X = 0
STX $2000 ; disable NMI
STX $2001 ; disable rendering
STX $4010 ; disable DMC IRQs
vblankwait1: ; First wait for vblank to make sure PPU is ready
BIT $2002
BPL vblankwait1
clrmem:
LDA #$00
STA $0000, x
STA $0100, x
STA $0200, x
STA $0400, x
STA $0500, x
STA $0600, x
STA $0700, x
LDA #$FE
STA $0300, x
INX
BNE clrmem
vblankwait2: ; Second wait for vblank, PPU is ready after this
BIT $2002
BPL vblankwait2
LoadPalettes:
LDA $2002 ; read PPU status to reset the high/low latch
LDA #$3F
STA $2006 ; write the high byte of $3F00 address
LDA #$00
STA $2006 ; write the low byte of $3F00 address
LDX #$00 ; start out at 0
LoadPalettesLoop:
LDA ballcolor, x ; load data from address (palette + the value in x)
; 1st time through loop it will load palette+0
; 2nd time through loop it will load palette+1
; 3rd time through loop it will load palette+2
; etc
STA $2007 ; write to PPU
INX ; X = X + 1
CPX #$20 ; Compare X to hex $10, decimal 16 - copying 16 bytes = 4 sprites
BNE LoadPalettesLoop ; Branch to LoadPalettesLoop if compare was Not Equal to zero
; if compare was equal to 32, keep going down
LoadSprites:
LDX #$00 ; start at 0
LoadSpritesLoop:
LDA sprites, x ; load data from address (sprites + x)
STA $0200, x ; store into RAM address ($0200 + x)
INX ; X = X + 1
CPX #$0C ; Compare X to hex $0C, the 12 bytes of sprite data
BNE LoadSpritesLoop ; Branch to LoadSpritesLoop if compare was Not Equal to zero
; if compare was equal to 32, keep going down
LDA #%10010000 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
STA $2000
LDA #%00011110 ; enable sprites, enable background, no clipping on left side
STA $2001
Forever:
JMP Forever ;jump back to Forever, infinite loop
NMI:
LDA #$00
STA $2003 ; set the low byte (00) of the RAM address
LDA #$02
STA $4014 ; set the high byte (02) of the RAM address, start the transfer
LDA #%10010000 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
STA $2000
LDA #%00011110 ; enable sprites, enable background, no clipping on left side
STA $2001
LDA #$00 ;;tell the ppu there is no background scrolling
STA $2005
STA $2005
JSR ReadController1
JMP EnginePlaying
EngineDone:
JSR CheckPaddleCollision
RTI ; return from interrupt
EnginePlaying:
;;;;;;;;;;;;;;;;;;;;;;;;MAKE THE BALL MOVE;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MoveRight:
LDA motion ;Check which direction the motion is in and make sure we're moving right first
BEQ MoveLeft
LDA ballx
ClC
ADC #$01
CMP #RIGHTWALL ; Add one to the motion of the ball in x-direction and check for collision against right wall
BCC RightDone ; If ballx < RightWall, then jump to right done and save the current value of ballx
STA ballx ; otherwise, we have hit the wall so we still must save current values(ballx) and also change motion = 0
LDA #$00 ; so mark that the ball is now moving left
STA motion
JMP BallMovingDone
RightDone:
STA ballx
LDA #$01
STA motion
JMP BallMovingDone
MoveLeft:
LDA motion
BNE MoveRight
LDA ballx
SEC
SBC #$01
CMP #LEFTWALL
BCS LeftDone
STA ballx
LDA #$01
STA motion
JMP BallMovingDone
LeftDone:
STA ballx
LDA #$00
STA motion
BallMovingDone:
LDA ballx
STA $0203
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Make the ball move in the y-direction;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MoveDown:
LDA motiony ;Check which direction the motion is in and make sure we're moving right first
BEQ MoveUp
LDA bally
ClC
ADC #$01
CMP #BOTTOMWALL ; Add one to the motion of the ball in x-direction and check for collision against right wall
BCC DownDone ; If ballx < RightWall, then jump to right done and save the current value of ballx
STA bally ; otherwise, we have hit the wall so we still must save current values(ballx) and also change motion = 0
LDA #$00 ; so mark that the ball is now moving left
STA motiony
JMP BallDone
DownDone:
STA bally
LDA #$01
STA motiony
JMP BallDone
MoveUp:
LDA motiony
BNE MoveDown
LDA bally
SEC
SBC #$01
CMP #TOPWALL
BCS UpDone
STA bally
LDA #$01
STA motiony
JMP BallDone
UpDone:
STA bally
LDA #$00
STA motiony
BallDone:
LDA bally
STA $0200
LDA #$00 ;;Just making sure to update the rest of the sprite information, e.g. tile number and attributes(color)
STA $0201
LDA #$01
STA $0202
PaddleLeft:
LDA buttons
and #%00000010
BEQ PaddleLeftDone
LDA $0207
SEC
SBC #$01
CMP #LEFTWALL ;So just compare to the leftwall. If the value is now less, DO NOT store it. This works because next time accumulator
BCC PaddleLeftWall ;is loaded, the old value will still be there, which will be in the valid range. Thus paddle will not go beyond wall.
STA $0207
LDA $020B
SEC
SBC #$01
CMP #LEFTWALL
BCC PaddleLeftWall
STA $020B
jmp PaddleLeftDone
PaddleLeftWall: ;;store the border x values for both sprites just to be sure
LDA #$04
STA $0207
LDA #$0C
STA $020B
PaddleLeftDone:
PaddleRight:
LDA buttons
and #$00000001
BEQ PaddleRightDone
LDA $020B
CLC
ADC #$01
CMP #RIGHTWALL ;The wall collision mechanism for the right wall is similar, EXCEPT, notice that sprite $020B comes first since that is the rightmost
BCS PaddleRightWall ; sprite and hits the wall first. Originally, we had it with sprite $0207 first(like for left), but since that is the left most sprite, by the time it hit the wall
STA $020B ; the rightmost sprite had already gone through it. So thats why we need to switch and check rightmost sprite first.
LDA $0207
CLC
ADC #$01
CMP #RIGHTWALL
BCS PaddleRightWall
STA $0207
jmp PaddleRightDone
PaddleRightWall: ;;store the border x values for both sprites
LDA #$E8
STA $0207
LDA #$F0
STA $020B
PaddleRightDone:
JMP EngineDone
;; READ THE CONTROLLER AND MOVE PADDLE ;;
ReadController1:
LDA #$01
STA $4016
LDA #$00
STA $4016
LDX #$08
ReadController1Loop:
LDA $4016
LSR A ; bit0 -> Carry
ROL buttons ; bit0 <- Carry
DEX
BNE ReadController1Loop
RTS
CheckPaddleCollision:
LDA bally
CMP #$98 ;we have checked that the ball has hit the top of the paddle surface
BEQ PaddleRange ;now lets check that the x values also lie within the paddle surface
jmp NoHit
PaddleRange:
LDA ballx ;;if the balls x coordinate < paddle left sprite, it is a miss
CMP $0207
BCC NoHit
LDA $020B ;;if balls x coordinate > paddle right sprite, it is a miss
CLC
ADC $08
STA paddleright
LDA ballx
CMP paddleright
BCS NoHit
Hit:
LDX #$00
STX motiony
NoHit:
RTS
;;;;;;;;;;;;;;
.bank 1
.org $E000
palette:
.db $0F,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$0F
.db $0F,$1C,$15,$14,$31,$02,$38,$3C,$0F,$1C,$15,$14,$31,$02,$38,$3C
sprites:
;vert tile attr horiz
.db $80, $00, $01, $40 ;sprite 0 The ball is only in tile 0. Ball will start in center of screen
.db $A0, $10, $00, $80 ;The paddle sprite information. It is composed of 2 sprites
.db $A0, $11, $00, $88
.org $FFFA ;first of the three vectors starts here
.dw NMI ;when an NMI happens (once per frame if enabled) the
;processor will jump to the label NMI:
.dw RESET ;when the processor first turns on or is reset, it will jump
;to the label RESET:
.dw 0 ;external interrupt IRQ is not used in this tutorial
;;;;;;;;;;;;;;
.bank 2
.org $0000
ship: .incbin "ball.chr" ;includes 8KB graphics file from SMB1
[Page-widening comment fixed by MOD]