help on first demo?
Moderator: Moderators
To get started with collision, first define what a collision is, in English. Once you have that solid, translate it to code. This step is likely to need subroutines that do the following:
- Sprite bounding box tracing: Given an actor's displacement, velocity, and size, compute a list of the (x, y) coordinates of all metatiles that its leading edge overlaps.
- Background object retrieval: Given (x, y) in world coordinates, return the number of the metatile in that position.
- Background object attributes: Given the number of a metatile, return whether this tile is passable.
Object collision with BG can be either very easy or very hard depending on how complicated is your BG. If you have blending tiles, tiles who moves the player automatically (such as moving sand or something) or that kind of stuff, things may be pretty compliceted. Assuming you just have a basic background, and that you just want make it walkable or not walkable, however, things are really simple.
First thing to do before a sprite-BG collision routine is a pixel-BG collision routine. For a given pixel position X and Y, you call a routine, the routine will convert the coordinate from pixel to tile, effecively finding which tile on the map is below your pixel, and then if the pixel is walkable return with carry set, and carry clear otherwise (or the other way arround it doesn't matter). There is a couple of different way to do this kind of stuff, just make your own.
Then, if you want to check if your player "can" go right, you have to check if lower-right corner and upper-right corner. If the player is bigger than your collision detection basis, you'll have to also check a middle-right point, or even more than this, but this is usually not needed. If all these checks passes, then you can add one to your player position effectively moving right. If at leat one of the checks fails, then the player cannot pass. Then just adapt it for other direction as well, it's exactly the same. If you're going to have gravity, you'll want to automatically have each object accelerate down, exept if they collide with the ground of course. That should do it.
Object/Object collision is even simpler, assuming all your object are simply rectangle shaped. If you want to do different shapes, I guess it's possible but should be a major pain. There is probably a couple of different ways to do it, I'll explain the way I did it. First have a routine that calculates an object's "corner coordinates". For example if the object is at (10, 20) on the screen and that it's tall of 8 and wide of 6, the corner coordinates would be (7, 12) (13, 12) (7, 20) and (13, 20). That is if your "object hot point" is on the bottom center of the object, which is usually the case. Then the object's bottom cordinate is the same as the hot point's coordinate, the object's top coordinate is hot point less height, the left point is hot point less half of width, and right point is hot point plus half of width. Adapt if your objects work differently tough.
Now that you have each "corner" coordinates of two objects you want to collide together, simply follow this logic :
If (object1HMax > ojbect2HMin) and (object1HMin < object2HMax) then the objects collide horizontally.
If (object1VMax > ojbect2VMin) and (object1VMin < object2VMax) then the objects collide vertically.
If object collide horizontally and vertically, they are in contact.
If can be usefull to do only vertical or horizontal collision detection to check if two objects are alighed, for example to trigger an enemy to do a particular attack when the player face it or for many other reasons.
First thing to do before a sprite-BG collision routine is a pixel-BG collision routine. For a given pixel position X and Y, you call a routine, the routine will convert the coordinate from pixel to tile, effecively finding which tile on the map is below your pixel, and then if the pixel is walkable return with carry set, and carry clear otherwise (or the other way arround it doesn't matter). There is a couple of different way to do this kind of stuff, just make your own.
Then, if you want to check if your player "can" go right, you have to check if lower-right corner and upper-right corner. If the player is bigger than your collision detection basis, you'll have to also check a middle-right point, or even more than this, but this is usually not needed. If all these checks passes, then you can add one to your player position effectively moving right. If at leat one of the checks fails, then the player cannot pass. Then just adapt it for other direction as well, it's exactly the same. If you're going to have gravity, you'll want to automatically have each object accelerate down, exept if they collide with the ground of course. That should do it.
Object/Object collision is even simpler, assuming all your object are simply rectangle shaped. If you want to do different shapes, I guess it's possible but should be a major pain. There is probably a couple of different ways to do it, I'll explain the way I did it. First have a routine that calculates an object's "corner coordinates". For example if the object is at (10, 20) on the screen and that it's tall of 8 and wide of 6, the corner coordinates would be (7, 12) (13, 12) (7, 20) and (13, 20). That is if your "object hot point" is on the bottom center of the object, which is usually the case. Then the object's bottom cordinate is the same as the hot point's coordinate, the object's top coordinate is hot point less height, the left point is hot point less half of width, and right point is hot point plus half of width. Adapt if your objects work differently tough.
Now that you have each "corner" coordinates of two objects you want to collide together, simply follow this logic :
If (object1HMax > ojbect2HMin) and (object1HMin < object2HMax) then the objects collide horizontally.
If (object1VMax > ojbect2VMin) and (object1VMin < object2VMax) then the objects collide vertically.
If object collide horizontally and vertically, they are in contact.
If can be usefull to do only vertical or horizontal collision detection to check if two objects are alighed, for example to trigger an enemy to do a particular attack when the player face it or for many other reasons.
I love your mini tuts Bregalad! I was thinking of something similar for bg collision. Tepples's post got me thinking a little and something resembling a pseudo code routine has been forming in my head over the day. Something like... yposition minus 8 until negative flag set, incrementing a value every dec 8. same for x. Add y_loop_count with x_loop_count and offset nametable by new value. Get value of tile in name table, then act accordingly. If my subconscious is as good at writing loops as I trust it to be, that should give something close to collision detection. I hope that made sence.
Here is some really rough code.
Is this close? It sounds like it would work to me but it feels to simple.
I really don't know how to do greater than/less than. I completely understand the corner checking logic and it sounds beautiful for square collision but I don't know how to implement gt ls.
Thanks all!
Here is some really rough code.
Code: Select all
lda y_pos
sta temp_y_pos
y_div_8:
lda temp_y_pos
dec #8
sta temp_y_pos
inc y_loop_count
and the flags
beq to neg flag set then jmp x_div_8
jmp y_div_8
lda x_pos
sta temp_x_pos
x_div_8:
lda temp_x_pos
dec #8
sta temp_x_pos
inc x_loop_count
and the flags
beq to neg flag set then jmp add_values
jmp x_div_8
add_values:
lda y_loop_count
adc x_loop_count
tax
lda #0
sta y_temp_pos
sta x_temp_pos
Next_loop:
lda (nametable), x
cmp tile number aka brick type
beq to unpassable brick jmp to get_tile_y
jmp to the some other code
get_tile_y:
lda y_temp_pos
adc #08
sta y_temp_pos
dec y_loop_count
bne get_tile_y
get_tile_x:
lda x_temp_pos
adc #08
sta x_temp_pos
dec x_loop_count
bne get_tile_x
compare:
lda y_pos
cmp y_temp_pos
beq collide
lda x_pos
cmp x_temp_pos
beq collide
I really don't know how to do greater than/less than. I completely understand the corner checking logic and it sounds beautiful for square collision but I don't know how to implement gt ls.
Thanks all!
For unsigned comparisons, the 'cmp' and 'sbc' instructions set up the carry flag such that 'bcc' means "branch if accumulator was less than memory", and 'bcs' means "branch if accumulator was greater than or equal to memory". In fact, the data sheet for at least one of Western Design Center's 6502 series chips suggests the synonyms 'bge' for 'bcs' and 'blt' for 'bcc'.
Skidlz: Do you know how to use arrays in C or any other programming language? If so, you might be able to prototype your collision logic in this language and then hand-compile it to 6502 assembly language.
Skidlz: Do you know how to use arrays in C or any other programming language? If so, you might be able to prototype your collision logic in this language and then hand-compile it to 6502 assembly language.
Thats wonderful! Why have I net heard of these?tepples wrote:For unsigned comparisons, the 'cmp' and 'sbc' instructions set up the carry flag such that 'bcc' means "branch if accumulator was less than memory", and 'bcs' means "branch if accumulator was greater than or equal to memory"
So I can scratch the flag checking and such.
Not even that familiar with C. I wrote a few things for my calc in TIGCC but thats about the extent of my practice. I just glanced at some array tuts. Sounds like its a bunch of ints/strings put end to end in one long int/string and then temporarily parsed for output? I'm not seeing how thats immediately relative so I guess I misunderstood what arrays are.tepples wrote:Skidlz: Do you know how to use arrays in C or any other programming language? If so, you might be able to prototype your collision logic in this language and then hand-compile it to 6502 assembly language.
Does my code look like its on the right track?
Thanks so much for sbc, bcc, bcs.
P.S. This is totally unrelated but I'm wondering, is a good method of inserting images floating around? I know the limitations of the system and that without drastic flickering tactics I will get very few colors. I did manage to break one image down to 4 colors and feed it through bmptochr.exe, so I know what image quality I'm dealing with. I was just wondering if there is an easy way to get an image into the red blue black white format.
*edit*I just realized in the code I need to multiply y by 32 to get the proper nametable offset.*edit*
Well, for the code I guess you'll have to try it yourself, it's hard to tell if it's good or not good just by looking at it like this. Some thing like "dec #$8" make me wondering, still. You'd want to use "sbc #$8" insted or something. dec is a bit like sbc #$01, exept the carry is not checked nor positionned.
For images, I guess nothing beats converting them manually, but I guess there is a few programms arround that can limit colors usually down to 16, this is a good start, then you limit the remaining colors "manually". I guess Tokumaru made a programm to covnert bmp->chr from files to avoid too much work, and it allows to do multiple layers (so you can place sprites on a BG or sprites on sprites at the same place on the screen, with different colors so that the image have more than 4). It's called nestc.exe, I don't know where you can find it.
For images, I guess nothing beats converting them manually, but I guess there is a few programms arround that can limit colors usually down to 16, this is a good start, then you limit the remaining colors "manually". I guess Tokumaru made a programm to covnert bmp->chr from files to avoid too much work, and it allows to do multiple layers (so you can place sprites on a BG or sprites on sprites at the same place on the screen, with different colors so that the image have more than 4). It's called nestc.exe, I don't know where you can find it.
Now that you say it, I see that dec was wrong there. I wrote it right on the forum and I guess dec sounded right at the time. It was meant to be more of a pseudo code/English explanation than executable code. Still I based my code off of that and I would have used dec accidentally. So thanks for pointing that out. I think I'm about ready to test the it so I will post results soon.