Need some help and advice with my collision detection

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

tepples
Posts: 22150
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Need some help and advice with my collision detection

Post by tepples » Sat Sep 13, 2014 6:43 am

Sik wrote:
Kasumi wrote:Does $2005/$2000 really have to be written every frame?
Yes, because the address completely changes after it rendered the entire screen (the address keeps changing as it fetches the pixels for the background).
How so? If you change t (top of screen) through $2005, and you don't modify the background through $2005-$2007, then the PPU will keep the scroll in the same position. (In "skinny" terms, this is the v := t, or set video memory pointer to top of screen, that occurs in the vsync after the pre-render line.) But if you're planning to scroll, you should plan on setting $2005 every frame for two reasons: 1. you'll be loading new map data at the edge of the screen, and 2. the camera will be moving.

SNgamer
Posts: 44
Joined: Tue Feb 11, 2014 7:12 am

Re: Need some help and advice with my collision detection

Post by SNgamer » Sat Sep 13, 2014 7:40 am

Kasumi wrote:Okay, figured it out. Here's a ROM (Let me know if you want it removed, it's here to prove I'm not nuts), as well as the changes. If the changes I listed don't give you this result, tell me and I will find out what I forgot.

Code: Select all

main:;checks for collision
bit $2002
bpl main
lda $0204;vert pos of metasprite
clc
adc #$09
lsr a
lsr a
lsr a
sta ypos
lda $0207;hor pos of metasprite
lsr a
lsr a
lsr a
sta xpos
I made your main loop actually wait for the vblank to start (bit $2002, bpl). There are better ways to do this which I hope I'll remember to list in another post, but I have something to do like right now.

I changed your CLC, RORs to LSR A. LSR ignores the carry, so no need to CLC. LSR is identical to CLC, then ROR basically. (Both of these may not have had much to do with the problem, but when I didn't list everything and tried it, it didn't work.)
I also remembered some opcode that would act like clc+ror combo (so carry is not shifted into the accumulator), but i could not remember what that was, so i sticked with clc+ror
thanks for this one
I added this to the end of your NMI:

Code: Select all

lda #$80
sta $2000

lda #$00 
sta $2005
sta $2005
This sets the scroll every frame. It's good practice to do it every frame, even if it doesn't change. A bit $2002 before those $2005 writes would be the most safe, but you cannot do this because of it messes up the frame wait stuff I mentioned above. (Which is part of why there are other ways to do it that I can't cover right this minute)
is it really necessary to enable NMI at the end of every frame? or is this in order to reset scroll position? i am a bit confused on this one, maybe you can find some time to explain later.
Finally, I did this:

Code: Select all

lda $0204;vert pos of metasprite
clc
adc #$09
lsr a
lsr a
lsr a
sta ypos
The PPU draws sprites one pixel lower than the position you give it. (A y position of 0 will be drawn on scanline 1, etc.) So I added 1 here to compensate.
this is something i did not know, this is very useful info

User avatar
Kasumi
Posts: 1292
Joined: Wed Apr 02, 2008 2:09 pm

Re: Need some help and advice with my collision detection

Post by Kasumi » Sat Sep 13, 2014 8:10 am

Kasumi wrote:There are better ways to do this which I hope I'll remember to list in another post, but I have something to do like right now.
That errand is now complete, so back to this. An easy to wait for vblank is this:

Code: Select all

main:;checks for collision
lda vblankoccurred;A new variable you must define
mainvblankwait:
cmp vblankoccurred
beq mainvblankwait
It loads the value of vblankoccurred in A before the loop, then compares that value to vblankoccurred. It counts on the NMI to change vblankoccurred during the loop. So in your NMI, you just need this somewhere to break that loop:

Code: Select all

inc vblankoccurred;whatever it was, it's now different so the loop will break
It's also good to do this because using bit $2002, bpl can occasionally miss frames.

With your main loop now running once per frame instead of constantly, you can move the code that animates your character to the main loop instead of the NMI. It doesn't matter much in this case, but it's good practice to have nothing in the NMI that doesn't absolutely need to be there. (Sprite DMA, tile updates that need to be done during gameplay need to be there. Music engine doesn't need to be but is cool to put there after the required stuff is done, just so music won't slow down if your main loop is running too many things.)

Already covered lsr/clc, ror. One other tiny note is that you occasionally compare with 0 when it isn't required.

Code: Select all

lda yadd
cmp #$00
beq rts_le
In that case you can remove the cmp and the program will work exactly the same, because lda will set the zero flag if what was loaded is equal to zero.

The last thing to mention is (indexed),y addressing which may help you avoid large cmp, branch trees when your game gets larger. It allows you to load from an address you can change, rather than one specified at compile time the way a label's is.

Code: Select all

lda #<level0;Low byte of this label's address
sta addr;Addr pointing to the first of two bytes of zero page RAM

lda #>level0;high byte of this label's address
sta addr+1;Addr+1 is the second of two bytes of zero page RAM

;With the label's address now in contiguous zero page RAM, the following statements will get the same value in A
lda level0,y
lda (addr),y
This is useful. Right now, you have your one screen broken up into 4 labels to access more than 256 bytes. Instead, you could use (indexed),y and change the location of the pointer to go further than 256 bytes under the label. (But you have to use y instead of x like you're doing now since indexed,x does something different.)

Code: Select all

lda ypos
lsr
lsr
lsr
tax
beq skipaddressfix
addressfixloop:
inc addr+1;(this adds 256 bytes to the pointer, so each time the ypos divided goes up one, the pointer will access the next 256 bytes of data)
dex
bne addressfixloop
skipaddressfix:
Doing this and using (indexed),y allows you avoid all the quadrupled up code underneath le1, le2, and le3. With le0 using indexed, it's all you'd need. And again, it doesn't matter much in this case, but once your game has more data having to evenly space labels would get tedious, so that's a good thing to learn about.
SNgamer wrote: is it really necessary to enable NMI at the end of every frame? or is this in order to reset scroll position?
Solely to set the scrolling nametable again, heh. It's a bit sloppy. A nicer way to do it is to keep the last value in $2000 in a mirror in RAM. Then you can perform bitwise logic to it.

Code: Select all

lda mirror2000
and #%11111100;The first nametable is ensured, nothing else is changed
sta $2000
sta mirror2000

SNgamer
Posts: 44
Joined: Tue Feb 11, 2014 7:12 am

Re: Need some help and advice with my collision detection

Post by SNgamer » Sat Sep 13, 2014 9:20 am

thank you for your tips, i very appreciate them. these will improve my programs heavily (as i now see that i have them coded in very untidy and inefficent way :oops: )

User avatar
Prime
Posts: 32
Joined: Sun Sep 21, 2014 10:18 pm

Re: Need some help and advice with my collision detection

Post by Prime » Sun Sep 21, 2014 10:37 pm

Search tokumaru threads he goes in depth about the subject within five seconds of his explanation i was aware how to implement it.
He's got the clearest writing on the subject, as a matter of fact he explains all subjects the clearest i've ever seen.Kasumi is a notable second they both go into deep detail as so the op can understand.

SNgamer
Posts: 44
Joined: Tue Feb 11, 2014 7:12 am

Re: Need some help and advice with my collision detection

Post by SNgamer » Wed Sep 24, 2014 6:09 am

Prime wrote:Search tokumaru threads he goes in depth about the subject within five seconds of his explanation i was aware how to implement it.
He's got the clearest writing on the subject, as a matter of fact he explains all subjects the clearest i've ever seen.Kasumi is a notable second they both go into deep detail as so the op can understand.
Do you mind supplying me with a link. This sound pretty helpful

User avatar
Prime
Posts: 32
Joined: Sun Sep 21, 2014 10:18 pm

Re: Need some help and advice with my collision detection

Post by Prime » Sun Sep 28, 2014 4:23 am

Absolutely SNgamer a couple links to the subject

viewtopic.php?f=2&t=352

viewtopic.php?f=10&t=9953

Celius
Posts: 2157
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Re: Need some help and advice with my collision detection

Post by Celius » Mon Sep 29, 2014 2:32 pm

Wow, that first thread is embarrassing! You may be able to extract some helpful information out of that one, but man... it's painful to read. I can't believe that was me. I clearly had absolutely no sense of forum etiquette/grace/actually listening.

I know there have been some discussions of this topic recently, with fairly in-depth coverage. Here are some other examples:

viewtopic.php?f=2&t=9702
viewtopic.php?f=10&t=11423
viewtopic.php?f=10&t=11022

Hopefully these will help too.

User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Re: Need some help and advice with my collision detection

Post by Tsutarja » Mon Oct 13, 2014 3:22 am

I don't know how much help this will be, but in theory, this is the way I would program hit detection with solid objects:
-As an example, falling speed is 3 pixels per frame
-The game checks if the space 3 pixels under the player is free
-If yes, move there
-If not, check again 2 pixels away
-If that is free, move 2 pixels down
-If not check 1 pixel away
-If that is free, move there
-If not, vertical speed is 0
-You need to have the same hit detection with slight changes four times to cover all four directions

I don't know how complicated this would be in 6502, but I have used this kind of hit detection in my games that use different programming language.
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi

User avatar
tokumaru
Posts: 11907
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Need some help and advice with my collision detection

Post by tokumaru » Mon Oct 13, 2014 3:02 pm

Tsutarja wrote:I don't know how complicated this would be in 6502
Not complicated, just slow in case there are collisions. The NES is pretty slow, and any task that's performed in loops consumes clock cycles pretty fast, so you should avoid those as much as possible, specially if you can predict the end result sooner.

The faster approach is to test the desired movement, and if that isn't allowed, instead of going back pixel by pixel and testing again you can simply compute what the last allowed position is. The collision data should allow you to do that. If the blocks that build your world are 16x16 pixels large, and you just verified that a coordinate 4 pixels within this block hit a solid pixel, its a waste to test again all the way up if you know that the whole block is solid. Just place the object immediately above the block and you're good. This also works with slopes, because using the slope's collision data you can place the object at the topmost pixel.

Post Reply