nesdev.com
http://forums.nesdev.com/

Reading from PPU for background collision
http://forums.nesdev.com/viewtopic.php?f=2&t=16792
Page 2 of 2

Author:  rainwarrior [ Thu Dec 07, 2017 1:37 am ]
Post subject:  Re: Reading from PPU for background collision

It has a few names, but the term I'm used to for this type of data structure is "ring buffer".

Author:  DRW [ Thu Dec 07, 2017 1:59 am ]
Post subject:  Re: Reading from PPU for background collision

dougeff wrote:
Your game (DRW) has auto-scrolling. So, load if scroll multiple of 8 makes sense here. Any game where scroll can shift 2 pixels in 1 frame might miss a load.

In this case, you of course have to do a slightly different check.
For example
if ((NewScollingPosition & 7) < (OldScrollingPosition & 7))
or something like that.

na_th_an wrote:
As a hint for future games, you can avoid having to shift the entire array if you use a circular array with a moving, "virtual" first index.

Yeah, I thought about that. But having to calculate the index offset for every time the x position of any character is checked (which is quite a bit for various collision checks and the x position is an integer instead of just a byte) would have been more problematic and would have wasted more ROM space (and therefore more CPU time) than simply shifiting a 34 byte array every eight frames. (I even did this shift in Assembly for maximum speed.)

Author:  na_th_an [ Thu Dec 07, 2017 9:48 am ]
Post subject:  Re: Reading from PPU for background collision

rainwarrior wrote:
It has a few names, but the term I'm used to for this type of data structure is "ring buffer".


Thanks for the info. I just translated literrally from Spanish :)

DRW wrote:
Yeah, I thought about that. But having to calculate the index offset for every time the x position of any character is checked (which is quite a bit for various collision checks and the x position is an integer instead of just a byte) would have been more problematic and would have wasted more ROM space (and therefore more CPU time) than simply shifiting a 34 byte array every eight frames. (I even did this shift in Assembly for maximum speed.)


Yeah, I understand. It really depends on the size of your buffer.

Author:  Celius [ Thu Dec 07, 2017 1:39 pm ]
Post subject:  Re: Reading from PPU for background collision

The circular buffer concept is really quite easy to work with, especially in projects that only scroll horizontally or vertically. For me, the trick was to dedicate 2 pages of RAM to house a 2-screen rolling window of collision data (I store it in $600-$7FF). The data is formatted so that every 16 bytes represents a column of 16x16 pixel metatiles in the window. No matter what direction the camera is scrolling, determining where to "dump" newly revealed columns of tiles is extremely easy. You just take the in-level X coordinate of the camera boundary (the left boundary for scrolling left, right for scrolling right), AND it with $01F0, and add $0600. So if the camera scrolls so that the right boundary is at pixel $1BC1, which reveals a new column of metatiles, that column of metatiles would be dumped at (($1BC1 AND $01F0) + $0600) = $07C0.

Collision detection is just a step beyond this logic. After calculating the address of the column of tiles with the X coordinate, you divide the Y coordinate by 16 and use this as and use this as an index to that starting address.

Code:
;XHigh/XLow/YLow represent a set of in-game X/Y coordinates. X is 16-bit, Y is 8-bit due to no vertical scrolling.

lda XHigh
and #$01
clc
adc #$06
sta TempAddH

lda XLow
and #$F0
sta TempAddL

lda YLow
lsr a
lsr a
lsr a
lsr a
tay

lda (TempAddL),y   ;Your tile type

Author:  na_th_an [ Fri Dec 08, 2017 9:12 am ]
Post subject:  Re: Reading from PPU for background collision

Exactly what I do. For 1 way scrollers, I usually have a 16x16 buffer (specially vertical games), and a two-screener for 2-way scrollers (left-right, mostly). Calculating where to write to the buffer is trival and collision detection is really easy this way.

Author:  Celius [ Fri Dec 08, 2017 11:47 am ]
Post subject:  Re: Reading from PPU for background collision

The main thing I like about it is that it just works by itself without a lot of "special case" intervention. The only issue I ran into was if I sized my rolling window to be exactly 2 screens, I saw bad things happen when changing directions. Since both the left and right boundary of the window are exactly 2 screens apart, the address of where to dump new columns in the circular buffer is exactly the same for both directions. If the left bound is at pixel $1BC2, the right bound is at pixel $1DC2, which both evaluate to start at $7C0 in the circular buffer. Long story short, I would run into issues where it would skip updating values in the buffer that needed to change, if the scrolling direction changed. You could easily end up with corrupt collision data.

The easiest solution for me was to shrink my rolling window so that it's a little smaller than the width of the buffer. I just shrunk it down to like 480 pixels instead of 512.

Page 2 of 2 All times are UTC - 7 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/