Page 1 of 4

pong collision from nerdy nights

Posted: Thu Nov 10, 2011 12:40 pm
by log in
After making the background and the controls for pong i made the paddlecollision.
I used the information from the nerdy nights rom:

if ballx <paddle1
if bally > paddley top
if bally < paddley bottum
bounce,ball now moving left

So with the information from the rom i made this:

checkpaddlecollision
lda ballx
com paddlex
beq paddlerange

; compaire the ballx with the paddlex constant


paddlerange:
lda bally
com paddleytop
bcc paddlerangedone
lda #$00
sta ballright
lda #$01
sta ballleft
paddlerangedone:


I added 3 other variables(for a 4 sprites paddle) and it works but not ok.
The paddle bounces BUT only if the ball makes it,sometimes it bounces half way the screen depending of the position of the paddle.

Did i something wrong or is this a bad collision method?

Re: pong collision from nerdy nights

Posted: Thu Nov 10, 2011 3:15 pm
by Kasumi
APOLOGIES TO LOG IN FOR THE (NOW FIXED) BAD EXPLANATION

First off, is this pseudo code?

I'm never seen com, only cmp.

Second off, what you've described in the if statements is more or less how you do it, except your check for X should be > not <.

This is what happens when it's ballx < paddlex.

Code: Select all

| = Paddle
* = ball

           |    
*          |    
           |
    
The ball's x position is less than the paddle's x position
The ball's y position is greater than the paddle's top y position
The ball's y position is less than the paddle's bottom y position

So the ball bounces left even though the ball is nowhere near the paddle.
Something similar would happen with the reversed condition with the ball on the right, so it might be worth doing two x checks as well if you don't want the player to hit the ball after it has already passed the paddle on the right.

That said, your actual 6502 code is not doing the checks you laid out at all. See comments.

Code: Select all

checkpaddlecollision
lda ballx
cmp paddlex
beq paddlerange;If ball's x position is equal to paddle's x position branch to paddlerange

; You're not skipping anything here. You branch to paddlerange
;But if you didn't branch the except same
;thing would happen because no code is in between the branch
;and the label.

;Did you mean bcc instead of beq, since you
;want to do the y check only if the ball's x position is to the right of the paddle?

;Did you mean to branch to paddlerangedone, which would skip
;the y collision check so a bounce can't occur in the case?
paddlerange:
lda bally
cmp paddleytop
bcc paddlerangedone;if ball y < paddleytop branch to paddlerangedone

;You also need to do the second y check you described in the if statement, or the ball will bounce whenever the ball is below the paddle's top. 
;Even if it's also below the paddle's bottom.
lda #$00;Do this stuff;
sta ballright;
lda #$01
sta ballleft
paddlerangedone: 
So basically, your current code doesn't check X at all. It bounces the ball whenever the ball's position is greater than or equal to the paddle's top. Meaning this is a hit:

Code: Select all

      
      |
      |
      |
	  *
So is this:

Code: Select all

              |
              |
              |
			  
			  
*
Here is how the flags are set after a compare:

Code: Select all

          +-------------------------+---------------------+
          |                         |  N       Z       C  |
          +-------------------------+---------------------+
          | A, X, or Y  <  Memory   |  1       0       0  |
          | A, X, or Y  =  Memory   |  0       1       1  |
          | A, X, or Y  >  Memory   |  0       0       1  |
          +-----------------------------------------------+
You have to do the checks you described (with my fix for X), and branch passed the ball bounce code any time one of them isn't true. That way if all of them are true, the ball will bounce.

Edit: For those curious about my error, I said log in's y branch was wrong when it is not. I also suggested changing his x beq to bcs when it should be bcc. I always get confused when mixing if statements with assembly because

Code: Select all

if(whatever == whatever){;If equal run the code below
//code
}
but

Code: Select all

lda whatever
cmp whatever
beq label;If equal skip the code below
;code

label:
That's really no excuse, though. Sorry, log in.

You just need to fix the x branch and add the second y check, not reverse the condition of the existing y check and add a y check.

Posted: Tue Nov 15, 2011 3:46 pm
by log in
NO APOLIGIES NEEDED :wink:
BUT..help would be nice.

Before i saw the fixed post. I Changed my code a couple of times and now im 100% lost.

I got some spare time and im working on my code again.

my code.

checkpaddlecollision
LDA ballx
CMP (typo i did not mean COM)padllex
BCC paddlerange


paddlerange:
LDA bally
CMP paddley
BCC paddlerangedone

Im pretty sure this is ok,
But my second check is wrong i think.

LDA bally
CMP paddle14 (the 4th sprite and bottom sprite of the 4)
BCC paddlerangedone (or should this be BCS?

LDA #$00
STA ballright
LDA #$01
STA ballleft
paddlerangedone:

Is the mistake here or from other things i changed in my code?

Posted: Tue Nov 15, 2011 6:36 pm
by Kasumi
I realize I wrote a lot (and made an error at first) , but that post describes what needs to be done. You've still got a branch that doesn't branch over anything.

When an instruction is run, various flags are set. I posted how cmp sets the flags in my last post. The branch commands skip all the code between the branch and the label if the branch condition is true. (So bcc whatever will go directly to the label whatever if the carry flag is clear. Otherwise, the program will run the first instruction below the branch instruction and go from there. )

So this:

Code: Select all

 
BCC paddlerange;If this instruction wasn't here, the program would run exactly the same

;because there is nothing here to skip. 
paddlerange: ;If we branch to this label, or if we don't branch, the same code is run.

isn't doing what it needs to. Your goal is to branch passed the y checks entirely if the X check fails, because if the X check fails there's no collision.

Your first y check uses bcc to branch if bally < paddley. So it doesn't make sense to use bcc again to branch if bally >= paddley's bottom. You'd want the reverse condition (bcs), or you're branching if bally < paddley's bottom instead of branching when bally >= paddley's bottom.

Posted: Wed Nov 16, 2011 3:56 pm
by log in
Thanks for your reply.
But my code is stil buggy.Sorry to be a pain.
But i fixed my code 2 times and bugs keeps popping up.

First i added a second y check with bcs so i have the first with bcc and the second with bcs.Tried the code and it kind of worked.
It just bounced way before the paddle sometimes.
But i still needed to change the x check.

I needed to get x check branced passed the y check if it failed.
so i did this{

checkpaddlecollision
lda ballx
cmp paddlex
bcc paddlerange
jmp nohit

go on with my code and added nohit at the end so if thex collision fails the program goes to nohit and rts and all should be fine but now there is no collision at all??
What am i doing wrong ?This should work 100%

Posted: Wed Nov 16, 2011 6:53 pm
by Kasumi
Questions you should ask yourself when you run into bugs:
1. What exactly is this code doing? If you don't really know, it may help to write a complete run down.
2. What exactly does it need to do?

By answering these two questions, you should be able to figure out what's wrong by the thing in the first answer that doesn't match the second answer.

Code: Select all

checkpaddlecollision
lda ballx
cmp paddlex
bcc paddlerange
jmp nohit
paddlerange:;I assume paddlerange is still here?
This is a run down of exactly what your code is doing:

lda ballx.; The accumulator has the ball's x position.
cmp paddlex.; This will clear the carry flag if what's in the accumulator (currently ballx) < paddlex, or set the carry flag if the accumulator >= paddlex
bcc paddlerange; This will jmp to paddlerange is the carry flag is clear. So by extension of the logic of the last line, it will jmp to paddlerange if ballx < paddlex.
jmp nohit; This will jmp to nohit. Because of the branch behind it, it will only do so when ballx >= paddlex. (i.e. that the carry is set)

The problem you are having with this exact sequence of events is that the ball bounces way before the paddle. It's doing this because your x branch is wrong. What happens when the X branch is wrong?
Kasumi wrote:
This is what happens when it's ballx < paddlex.

Code: Select all

| = Paddle
* = ball

           |    
*          |    
           |
    
The ball's x position is less than the paddle's x position
The ball's y position is greater than the paddle's top y position
The ball's y position is less than the paddle's bottom y position
So to fix it you must...?

Posted: Fri Nov 18, 2011 4:51 pm
by log in
To fix it i must.....uhm

I must fix my x branch thats clear to me.

My y collisions are good

paddlextop = bcc
paddlebottum = bcs

so ballx > paddlex =bcs? no thats not correct

I have changed my code with every branch.

less: bcc
equal : beq
greater bcs

even with bmi bpl etc.
But the ball bounces way before the paddle at times or not at all.

Looking and reading brances and other stuff over and over i even found other exsamples like

ldx
lda
cmp
bne
inx
stx

but i got the feeling im more and more lost or not?

Posted: Fri Nov 18, 2011 7:31 pm
by Kasumi
Never ever change branches to other random branches because you know which branch is broken. Choose the substitute that makes sense logically.

Code: Select all

          +-------------------------+---------------------+
          |                         |  N       Z       C  |
          +-------------------------+---------------------+
          | A, X, or Y  <  Memory   |  1       0       0  |
          | A, X, or Y  =  Memory   |  0       1       1  |
          | A, X, or Y  >  Memory   |  0       0       1  |
          +-----------------------------------------------+ 
Look up the comparison you want in this table. That's how the flags will be set after a cmp. You can branch to a label if one of these is set or clear.

Say you have code that makes a character jump. You branch passed that code when the jump button is NOT pressed, since that is when you DON'T want it to run.

Here, we're going to branch passed the bounce code when the collision CAN'T have occurred. Got it?

So here's exactly what you need.

Code: Select all

;Untested, but should work
lda ballx
cmp paddlex
bcc skipballbounceleft;If ballx < paddlex, go to skipballbounceleft
;We didn't skip. So ballx must be >= paddlex.
lda bally
cmp paddley 
bcc skipballbounceleft;if bally < paddley go to skipballbounceleft
;We didn't skip. So bally must be >= paddley. As well, ballx >= paddlex.
cmp paddlybottom
bcs skipballbounceleft;If bally >= paddleybottom, go to skipballbounceleft
;We didn't skip. So bally must be < paddlebottom
;As well, ballx >= paddlex
;As well, bally >= paddley.
;All the conditions for bouncing are true. So we put the bounce code here
LDA #$00
STA ballright
LDA #$01
STA ballleft 
skipballbounceleft:;If any of the bounce conditions were false, this is where we would end up. 
If there's something there you don't follow, please ask. There's no point copying the code if you don't understand it.

Now, one other thing you may not realize: ballx (if my assumptions of what you've written so far are correct) is the top left corner of the ball. paddlex is the top left corner of the paddle. So the ball will only bounce when it's top left point is passed the paddle with this code.

The same for y. It's possible for the ball to be inside the paddle and still miss a collision in a case like this:

Code: Select all

0= ball
1 = paddle
2 = both

00
021
 11
 11
 11
So keep that in mind before thinking it's not working. This should still work most of the time, though. (assuming I didn't make another error :oops: )

If it does work, and you understand it, fixing the missed collisions like the above will be the next step.

Posted: Sat Nov 19, 2011 2:59 am
by tokumaru
Kasumi wrote:Never ever change branches to other random branches because you know which branch is broken. Choose the substitute that makes sense logically.
Just wanted to second this. Never, ever, ever "guess" code. All that happens when you do this is you end up with something that might blow up in your face in the future, even if it all appears to work well at first. If you don't understand why a piece of code is working, it will most likely fail eventually, when run under other circumstances.

Posted: Sat Nov 19, 2011 9:57 am
by log in
Oh man i feel stupid right now :oops: .

Instead of working with the hits

X >
Y >
Y <

You work witn no hits

x < =bcc
y < = bcc
y > = bcs

this means no jumping or other strange moves to make clear what is hit and what is not.
Just give all the misses a place at the end of the code and you will get a hit what is followed by a bounch code.

Posted: Sat Nov 19, 2011 6:14 pm
by log in
OMG :cry:

It stilldoesn't work
this is my code


lda ballx
cmp paddle1x
bcc skip

lda bally
cmp paddle1ytop
bcc skip

lda bally
cmp paddle14
bcs skip

lda #$01
sta ballright
lda #$00
sta ballleft

Skip:

jmp gameengindone
rts


So this is turning in a real nightmare ,i understand it better now but it still doesn't work.please tell me there is a error here and that not my complete code is full of bugs .the ball still bounces to early

Posted: Sun Nov 20, 2011 4:37 pm
by Kasumi
Edit: Wait. This is wrong:

Code: Select all

lda #$01
sta ballright
lda #$00
sta ballleft 
This code has always been for a ball bouncing left off a paddle on the right. That's what you said in your first post. That's why the bounce code that you first posted, and what I have always posted is this:

Code: Select all

lda #$00
sta ballright
lda #$01
sta ballleft 
The collision detection code we've worked with so far will only work for the ball bouncing left off a paddle on the right.

And while it probably wouldn't affect this specifically, here is another odd thing about your code:

Code: Select all

Skip:

jmp gameengindone
rts 
Because that jmp is directly before the rts, the rts will never be executed. If what you've posted is a subroutine, that means your stack is probably corrupt.

Posted: Tue Nov 22, 2011 7:01 am
by log in
thanks for another reply. :oops:

But it was a typo on the forum i got it like you said and it still doesn't work
I got the feeling there is another bug in my code .
For some strange reason i got the feeling i made a mistake in de sprites or something ill check everything again.

Posted: Tue Nov 22, 2011 8:29 am
by Kasumi
If you want, post the code (as a file download, not in a forum post please) or a rom and I'll look through it. It shouldn't be long enough for that to be a hassle yet. (May be a few days before I can look, though. I'll be away from home for a week or so)

I finally did actually test that collision code and it gives the results I expect from it, so it is probably not that.

One other question: Are you retyping the code for the forum? Because you can just copy and paste it from your actual file so I see what you see.

Posted: Tue Nov 22, 2011 3:08 pm
by log in
Kasumi wrote:If you want, post the code (as a file download, not in a forum post please) or a rom and I'll look through it. It shouldn't be long enough for that to be a hassle yet. (May be a few days before I can look, though. I'll be away from home for a week or so)

I finally did actually test that collision code and it gives the results I expect from it, so it is probably not that.

One other question: Are you retyping the code for the forum? Because you can just copy and paste it from your actual file so I see what you see.
Im working on 2 computers 1 from work and its old and not always willing to help. :evil: Hope that explains some.

I pmed you my source code because my computer refuses to email. :evil:

THANK YOU VERY MUCH ,kasumi
I think i have a sprite bug or something with controls bug?

Anyway this might be helpfull for other newbie's :roll: is this a error in the rom explanation of nerdynights?

;;if ball x < paddle1x
;; if ball y > paddle y top
;; if ball y < paddle y bottom
;; bounce, ball now moving left

This is copy and pasta from the rom...or am i making a fool out of myself :oops:

From what if learned so far from kasumi and the nesdev site it should be
>
>
<

And are there other errors known from the nerdy nights?