Object collision
Moderator: Moderators
-
- Posts: 2158
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
Object collision
I know how to move sprites and do backgrounds and all that, but how do you make an object collide with another one? I couldn't really find any info on it, so can someone help me? thanks.
Well, if you know how to move sprites, you know their position, correct? I'm unsure about what do you plan but... anyway, keep track of sprite #0 - if it's a game character (or whatever) and you wanna collision, there are 2 points:
A. Sprite x Sprite collision = you could keep track of their X,Y positions in RAM 200-2FF as example. Once X1 = X2 and Y1 = Y2 (in a latency of S pixels, where S is the size of your desired sprite), you got a strike and triggers the event.
B. Sprite x Background collision = even if you use sprite #0 hits to detect solid background pixel, it's useless most of times. This way, you must read the nametable (a tile in X,Y position) and compares with the sprite - it would had attributes (as solid, air, spikes...). Another RAM region would get the things working good.
I'm sorry, try ASM code by yourself. Get the idea and test it.
A. Sprite x Sprite collision = you could keep track of their X,Y positions in RAM 200-2FF as example. Once X1 = X2 and Y1 = Y2 (in a latency of S pixels, where S is the size of your desired sprite), you got a strike and triggers the event.
B. Sprite x Background collision = even if you use sprite #0 hits to detect solid background pixel, it's useless most of times. This way, you must read the nametable (a tile in X,Y position) and compares with the sprite - it would had attributes (as solid, air, spikes...). Another RAM region would get the things working good.
I'm sorry, try ASM code by yourself. Get the idea and test it.
Zepper
RockNES author
RockNES author
First, given two rectangles specified by left, right, top, and bottom, determine whether they overlap. Can you do that?
Then for each game object, construct its bounding box. (Normally, games will leave a few pixels outside the bounding box to compensate for the fact that sprite cels aren't rectangular.)
For each pair of game objects, compare their bounding boxes to see if they overlap.
Then for each game object, construct its bounding box. (Normally, games will leave a few pixels outside the bounding box to compensate for the fact that sprite cels aren't rectangular.)
For each pair of game objects, compare their bounding boxes to see if they overlap.
-
- Posts: 2158
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
I didn't really understand what you were saying there Fx3, though it's probably completely logical, and I'm just bad at interperting things into my own head. I have an idea to tell it when the object moving is in tile #99, it will disable the RIGHTKEYdown function. But I don't know how to define a variable in RAM for a tile #, because you can only say something like this:
Something = $80
you couldn't say this:
Something = #80
You can only define variables with hex crap, you can't do it with decimal, and that sucks! I think I'm using a crappy assembler, though, I'm using Nesasm, and I heard that sucks. I'm probably not making sense, so I'm gonna stop babling now.
Something = $80
you couldn't say this:
Something = #80
You can only define variables with hex crap, you can't do it with decimal, and that sucks! I think I'm using a crappy assembler, though, I'm using Nesasm, and I heard that sucks. I'm probably not making sense, so I'm gonna stop babling now.
-
- Posts: 2158
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
Sorry, ignore that thing above. This is my code:
I know that that isn't correct by the way. I don't know how to get it to stop when it's at location 99,100 if 100 is Y and 99 is X. It of course stops at in the column where X= 99, and in the column where Y= 100. Ya know what I mean? I can't think of a better way to explain it. How do you get it so it only stops when X= 99 and Y=100?
Code: Select all
Collide:
lda Y_Pos
cmp #100
beq NOTHINGdown
lda X_Pos
cmp #99
beq NOTHINGdown
Please, you must clarify what you want to do. Go read again what I and tepples wrote about it.
Zepper
RockNES author
RockNES author
-
- Posts: 2158
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
Sorry I'm not clear enough about what i want. I am trying to make a collision with my moving sprite, and a still sprite. It has the effect of a background collision, where when you hit the sprite, you stop moving. The still sprite basicly acts as a block like on mario. Sorry if I'm annoying everyone with my dumb questions...
These questions aren't dumb, just kinda hard.
I'd say that collision detection is one of the trickier things to code. At least for for sprite-to-bg. Sprite-to-sprite is easier and a good place to start, since the sprites are on the same coordinate system to begin with.
What you need to do to use bounding boxes like tepples said, is to do some range checking. This probably isn't an ideal example, but here's how I do this in Munchie Attack.
notes:
player's "mouth" sprite starts at $204
food objects start at $240
the @itsblank label is where it goes for 'no hit'.
the BCC/BCS branch after CMP is used to do greater/less than checking. For example, food objects are coming from the right, so the food's coordinate has to be less than the player's right edge, and greater than the player's left edge to count as a hit.
The values added and subtraced change the size of the box.
Also see here for some info about sprite-to-bg collisions:
http://www.greggman.com/mckids/programming_mc_kids.htm
I'd say that collision detection is one of the trickier things to code. At least for for sprite-to-bg. Sprite-to-sprite is easier and a good place to start, since the sprites are on the same coordinate system to begin with.
What you need to do to use bounding boxes like tepples said, is to do some range checking. This probably isn't an ideal example, but here's how I do this in Munchie Attack.
notes:
player's "mouth" sprite starts at $204
food objects start at $240
the @itsblank label is where it goes for 'no hit'.
the BCC/BCS branch after CMP is used to do greater/less than checking. For example, food objects are coming from the right, so the food's coordinate has to be less than the player's right edge, and greater than the player's left edge to count as a hit.
The values added and subtraced change the size of the box.
Code: Select all
hit_detection:
ldx #0
@hitloop:
lda $241,x
sta tiletype
bne :+
jmp @itsblank
:
lda $243,x
sec
sbc #8
cmp $207
bcc :+
jmp @itsblank
:
clc
adc #24
cmp $207
bcs :+
jmp @itsblank
:
lda $240,x
sec
sbc #15
cmp $204
bcc :+
jmp @itsblank
:
clc
adc #30
cmp $204
bcs :+
jmp @itsblank
:
lda #0 ; if it makes it all the way here, it was hit
sta $241,x
sta $245,x
sta $249,x
sta $24D,x
http://www.greggman.com/mckids/programming_mc_kids.htm
collision sample logic
my guess is that you are doing something like this:
byte check_for_collision(
byte sprite_1_x, int sprite_1_y,
byte sprite_2_x, int sprite_2_y,
byte x_distance, /*max X distance needed for collision*/
byte y_distance /*max Y distance needed for collision*/
)
{
byte x_diff = sprite_1_x - sprite_2_x;
if (x_diff < 0)
x_diff = -x_diff;
if (x_diff > x_distance)
return(0); /*no collision*/
byte y_diff = sprite_1_y - sprite_2_y;
if (y_diff < 0)
y_diff = -y_diff;
if (y_diff > y_distance)
return(0); /*no collision*/
return(1); /*collision happened*/
}
Translating to assembly language should not be that difficult.
byte check_for_collision(
byte sprite_1_x, int sprite_1_y,
byte sprite_2_x, int sprite_2_y,
byte x_distance, /*max X distance needed for collision*/
byte y_distance /*max Y distance needed for collision*/
)
{
byte x_diff = sprite_1_x - sprite_2_x;
if (x_diff < 0)
x_diff = -x_diff;
if (x_diff > x_distance)
return(0); /*no collision*/
byte y_diff = sprite_1_y - sprite_2_y;
if (y_diff < 0)
y_diff = -y_diff;
if (y_diff > y_distance)
return(0); /*no collision*/
return(1); /*collision happened*/
}
Translating to assembly language should not be that difficult.
Yeah. You need to change the branch condition and/or destination of the first check. What comes to mind for me is this:Celius wrote: When I say and, I don't mean the actuall command. Is there some way to say only go to NOTHINGdown, if Y_Pos = 100 and X_Pos = 93?
Code: Select all
lda y_pos
cmp #100
bne skip
lda x_pos
cmp #93
beq NOTHINGdown
skip:
Oh man, you should have seen the code for a PC sidescroller I tried to write when I was first learning C. I used fractional values for the player position and I think my "move until hit obstacle" tried every single sub-pixel position. A later version found the intercept of the movement vector. Still all major overkill; this wasn't a physics simulation that required absolute accuracy.
Draw a picture and think about the minimum work necessary to find if movement is possible, and how far. Then find simplifications that don't add much more work than the minimum. Be sure to abstract the problem to only the essential details.
Also, find a way to enjoy experimenting with 6502 programming techniques. It really helps to write simple debugging output routines to print a byte (or find an emulator with a good debugger), so you can write short test code and see the results.
Draw a picture and think about the minimum work necessary to find if movement is possible, and how far. Then find simplifications that don't add much more work than the minimum. Be sure to abstract the problem to only the essential details.
Also, find a way to enjoy experimenting with 6502 programming techniques. It really helps to write simple debugging output routines to print a byte (or find an emulator with a good debugger), so you can write short test code and see the results.
Combining the responses already given in another way, here's my $0.02: You obviously don't want to write custom code to detect collision between every object on every map of every level of your game. As blargg suggests, you should try to abstract this problem so that it is more general. This abstracted version (often called a "engine") should allow you design levels using the concept of objects, as opposed to pixels. The key is to get the level of abstraction right. The more abstract it is the more general your engine is, but it also becomes more difficult to implement it. You want it abstract enough that it simplifies your design, but not so abstract that it does more than you need.