Collision with objects

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

belltone
Posts: 19
Joined: Wed Sep 09, 2015 6:00 pm

Collision with objects

Post by belltone »

Hello.

I want to make a collision with sprites but it turns out only to line the whole height of the screen.

Code: Select all

COLLISION = $B5

Code: Select all

LatchController:
  LDA #$01
  STA $4016   
  LDA #$00
  STA $4016 

ReadA:   
  LDA $4016            
  AND #%00000001      
  BEQ ReadADone 
 
  LDA $0203    
  CMP #COLLISION    
  BNE DoneСollision  
  
  DEC $0203          
DoneСollision:    
  LDA $0203           
  CLC                 
  ADC #$01       
  STA $0203            
ReadADone:
How to make a sprite collision with this code:

Code: Select all

LoadObject:
  LDA object, x
  STA $0300, x
  INX
  CPX #$10
User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Re: Collision with objects

Post by Sogona »

Is there any particular reason you're doing

Code: Select all

  LDA  $0203
  CLC
  ADC #$01
  STA $0203
Instead of just INCing $0203? The only reason I ask is because I see you DECing $0203.
User avatar
darryl.revok
Posts: 520
Joined: Sat Jul 25, 2015 1:22 pm

Re: Collision with objects

Post by darryl.revok »

Are you using $0200-$02XX for Sprite OAM? (I'm going to proceed in my code assessment as if you are. I think you are)

If so, you wouldn't typically use that address as your actual object location. Usually, game objects are made of multiple sprites, and the draw locations for the individual sprites are relative to the position of the object as a whole. The draw position would also vary from scrolling.

If you don't scroll at all and your objects are all 8x8 pixels, then I guess you could do it that way. I never thought about doing it way because other design aspects precluded it.

First, if you compare the X position of one object to the X position of another object and BNE, you will only catch collisions that occur when the objects have the exact same X position, not when they overlap. So 7/8 possible collisions locations will be missed.

A sprite with an X position of 00 will occupy pixels 00-07.

If you decrement, and then don't branch out, you proceed to also add following. DEC to a memory location performs a read, modify, and write, all in one step.

Basically, your program does this:

1. See if controller 1 pressed A, exit routine if not
2. Load X position of Sprite 00
3. Subtract 181 from X position of sprite 00, (not saving result and behaving as if carry is set) and if the answer of that subtraction is not zero, branching to DoneCollision
4. If the answer from that subtraction was exactly zero, the X position of sprite 00 is decremented (it will now be 180)
DoneCollision:
5. The value of the X position of sprite 00 is loaded into the accumulator
6. Carry flag is cleared.
7. 1 is added to this value (If the value originally equalled 181, it now equals 181. If the value originally equalled anything else, then it is now one greater than it's original value.
8. That value is stored back to the location that will be used for X position of sprite 00.

I'm new here too but hopefully that helps you move forward a bit.

Stick with it!
User avatar
dougeff
Posts: 2876
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Collision with objects

Post by dougeff »

Button presses was discussed here recently...
viewtopic.php?f=10&t=13106&start=15

And I wrote a simplified Sprite vs Sprite collision code here...viewtopic.php?f=10&t=12993&p=150683

You can learn a ton by searching old forum posts. :)
nesdoug.com -- blog/tutorial on programming for the NES
belltone
Posts: 19
Joined: Wed Sep 09, 2015 6:00 pm

Re: Collision with objects

Post by belltone »

Thank you very much, I read everything that concerns the collision of objects, but to me as a novice is difficult to understand.

I think you need to calculate the coordinates of both the player and the object with which the collision continue to make comparisons and if a player gets to the coordinates of the object to prohibit further movement until it will not go beyond.

Please see what can do.
Attachments
collision.zip
Ball player, square wall with which the ball must face.
(31.87 KiB) Downloaded 114 times
User avatar
dougeff
Posts: 2876
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Collision with objects

Post by dougeff »

Here's another simple collision article, if you still need help.
http://www.gamedev.net/page/resources/_ ... ction-r735

What happens after collision is detected is up to you, whether stopping movement (and or pushing back a few pixels to avoid overlap), or bouncing back, etc. It's up to you.
nesdoug.com -- blog/tutorial on programming for the NES
belltone
Posts: 19
Joined: Wed Sep 09, 2015 6:00 pm

Re: Collision with objects

Post by belltone »

Thank you for the link, but I'm interested in writing a collision in assembler.

I know it's stupid and doesn't work, i could declare:

Code: Select all

PLAYER = $0203
OBJECT = $0300
but get an error during initialization:

Code: Select all

  LDA #PLAYER
  LDY #OBJECT
  CMP #OBJECT

  BNE Done
  LDA #%00000001
  STA $4015
 
  LDA #%10111111
  STA $4000
 
  LDA #$C9
  STA $4002
  LDA #$00
  STA $4003

Done:
How can I record the coordinates of the player $0203 in the register А, the coordinates of the object $0300 in the Y register?
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Collision with objects

Post by tokumaru »

belltone wrote:

Code: Select all

PLAYER = $0203

Code: Select all

  LDA #PLAYER
The "#" in the LDA instruction means you're loading an immediate value. The problem is that A is an 8-bit register, and $0203 is a 16-bit value, so it simply isn't possible to put it in A. But this isn't even what you're trying to do, is it?

If you want to load the contents of memory position $0203 (the value of the constant/label PLAYER), just do LDA PLAYER, without the "#".
User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Re: Collision with objects

Post by Sogona »

All labels are just memory locations
What I like to do is separate my labels into constants and variables.

For variables, I don't care about the address itself, but what's in it. For constants, since they never change, I use its address as an immediate value.

so lets say you have:

Code: Select all

myvariable       .dsb 1 ;reserve 1 byte
MYCONSTANT  = $80
MYCONSTANT could be something like the x position of a wall that never changes.

the number sign in

Code: Select all

lda #MYCONSTANT
is actually saying "treat this label's address as an immediate value." and gets assembled as

Code: Select all

lda #$80
You, may already know that, but that confused the fuck out of me when I was first learning how to program in assembly.

So for a player's x position (In this case $0203), you'd want that to be a variable. If the object is moving, you'd want its coordinates to be variables too.

so it'd be something like this:

Code: Select all

  lda player_x
  cmp object_x
  bne +  ;branch if they arent touching
  ;if they are touching
  ;do stuff
  jmp @continue
+
  ;do stuff if they aren't touching
@continue:
  ;rest of code
Hope this helps.
belltone
Posts: 19
Joined: Wed Sep 09, 2015 6:00 pm

Re: Collision with objects

Post by belltone »

I did as instructed but a collision with an object signal is not happening instead is a clash along the line of the screen in the fact of the matter is in lessons Nerdy Nights (Starting Pong) where there are clashes with lines but not with objects, and this is not enough.
collision.jpg
I changed it to assembler ASM6.

Declare variables:

Code: Select all

player_x  equ $0200
player_y  equ $0203
The only thing that comes to mind is to record the contents of the accumulator in memory of STA #$30 in ReadA: 000030 and player movement will be set 01 if the player does not move it is reset to zero so check 00 is a background object if a player gets to the area where the other numbers, then the collision.
hex_object.jpg
Attachments
collision_1.zip
(29.74 KiB) Downloaded 97 times
User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Re: Collision with objects

Post by Sogona »

You're comparing $0203 (the sprite's X position) to the value in background label, whose address is $E000. The value of $E000 is #$00, which equates to the left edge of the screen. Are you trying to test collision with the plus sign made of zeros? Those aren't sprites.

The general way to do sprite collisions is to use hitboxes, which basically contain 4 variables: the positions of the 4 edges of the sprite.

I went ahead and modified your code slightly and just added a new sprite (To test collisions with), hitboxes for the 2 sprites, and routines to update the hitboxes and check for collision each frame.

The left and top edges of the 2 sprites' hitboxes are just their X and Y positions, and their right and bottom edges are just their X and Y positions plus 7. So this makes an 8 by 8 hitbox.

A really easy way to check for basic collision detection goes like this:

Code: Select all

if (player.hitbox_top > enemy.hitbox_bottom) {return 0;}
else if (player.hitbox_bottom < enemy.hitbox_top) {return 0;}
else if (player.hitbox_left > enemy.hitbox_right) {return 0;}
else if (player.hitbox_right < enemy.hitbox_left) {return 0;}
else {return 1;}
collision_1_new.zip
(31.22 KiB) Downloaded 100 times
Last edited by Sogona on Sat Sep 19, 2015 8:54 pm, edited 1 time in total.
User avatar
darryl.revok
Posts: 520
Joined: Sat Jul 25, 2015 1:22 pm

Re: Collision with objects

Post by darryl.revok »

Hmmm... some quick things.

You are comparing your object's location against "background". So, when it does that compare, it goes to the location background and pulls the first byte, which in this case is 00. That's why it always beeps when you cross zero.

I'm not sure exactly what you're trying to do, or if this is your line of thinking, but you can't do something as simple as comparing the object to your background table to detect for collisions. If you're doing background collisions that are more complex than the outer edge bounding box of pong, you'd have to know your object's position, and then reference that to the corresponding background tile for that position on your map. So, let's say your object is at 128, 64. This is a somewhat simplified explanation, but you'd have to divide 128 by 8 , which tells you're in the 16th tile column, then divide 64 by 8 and you'll know you're in the 8th row. So, then check the collision data for the tile at the 16th column and 8th row.

Also, you're still comparing just one pixel. Consider this. Your ball is 8 pixels by 8 pixels. Your ball could touch something 7 pixels to the right of it's draw position and it should still be a hit. So, it could be said that your ball has an 8 pixel by 8 pixel hitbox.

In one way or another, you basically need to do this for object/object collisions:

See if object Y is to the right of the left side of object X's hitbox, if not, there's no collision
See if object Y is to the left of the right side of object X's hitbox, if not, there's no collision
See if object Y is to the below the top of object X's hitbox, if not, there's no collision
See if object Y is to the above the bottom of object X's hitbox, if not, there's no collision. If so, you have a collision.

There's at least one quicker way I know to do it, but it pretty much involves summing the above process into a smaller equation. Once you get to that point I can dig up the link for you.

That's for object/object collisions, which it at first what I thought you were doing but this program looks like you're trying to go for background collisions. Background collisions, like I mentioned above, have to do with checking against a table of collision data, and you do this when the object moves, only in the directions that it's moving. (For example, don't check the left side of your hitbox against background if your object is moving right.) If you find that you've crossed into a solid tile, then you have to calculate how far to "eject" your object, that is, how far it needs to move to be pushed out of the solid tile.

You allow all of your movements to happen, whether or not they're into a collision tile, and then correct them before they're drawn.

Side note: You have logic in your NMI that doesn't need to be there, but I see you're using the Nerdy Nights style, which simplifies teaching certain aspects by just putting everything in NMI and guaranteeing your logic will execute at a set rate. Once you move on to the next thing, I'd suggest moving your controller reading and collision out of your NMI, adding code to protect your registers when NMI hits, and a delay loop in your main logic so that your main game logic cycle executes once per vBlank (with the exception of lag frames which aren't a concern now)

Let me know if that makes sense and if you have any questions. If we can get the first few things figured out, I'll try to help you get some footing to move forward.

Edit: Sogona covered some of this while I was typing the post, but I'm going to go ahead and upload it as is anyway.
belltone
Posts: 19
Joined: Wed Sep 09, 2015 6:00 pm

Re: Collision with objects

Post by belltone »

Thank you very much for your help is very good knowledge, they will be useful in the future for the creation of such a player or enemy bullets, and so on, I think understood the essence of the program will continue to do.

I did object detection background tile: $00 this background, other items: $01, $02, $03, and so on.

How good is this idea for the processor I do not know that's what happened:

Code: Select all

check_collision	.dsb 1
COLLISION = $DE
Object detection:

Code: Select all

object_detection:
  lda $2002
  sta check_collision
  cmp #COLLISION
  bne object_detection_done
  lda #$01
  sta $4015
  lda #$C9
  sta $4002
  lda #$00
  sta $4003
object_detection_done:
After the collision with the object of how to stop the movement of the player?
collizion_2.zip
(30.06 KiB) Downloaded 108 times
User avatar
dougeff
Posts: 2876
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Collision with objects

Post by dougeff »

You may be aware, but we are having this same discussion in a different thread...

viewtopic.php?f=2&t=13279

I have been doing...
-allow the move
-check collision
-if collision, "eject", opposite the direction of movement.

But, apparently there are many ways to go about this...as the above thread shows.

If your game is non-scrolling, and has 16x16 objects...you could do something like...
ejecting left... X and #$f0 = X
ejecting right... X + #$10, and #$f0 = X
ejecting up... Y and #$f0 = Y
ejecting down...Y + #$10, and #$f0 = Y

or any similar algorithm. You might be misaligned by 1 pixel with this one, I don't remember.
nesdoug.com -- blog/tutorial on programming for the NES
belltone
Posts: 19
Joined: Wed Sep 09, 2015 6:00 pm

Re: Collision with objects

Post by belltone »

I can take a variable for comparison at $2002 to create the effect of a collision but I still do not know how it can be easier to create one like something that:

Code: Select all

collision_status      .dsb 1
check_collision       .dsb 1

CollisionStatus:
  LDA #$00
  STA check_collision
  LDA $2002
  STA collision_status
  CMP #$C0
  BNE CollisionStatusDone:
CheckCollision:
  LDA check_collision
  CLC
  ADC #$01
  STA check_collision
CollisionStatusDone:
  RTS
And then I need to somehow stop the movement of the object if the $01 UNIT if zero then continue driving.

I tried to install using this code but it works only in one direction:

Code: Select all

  LDA object
  CMP #VARIABLE
  BNE ReadADone
  SEC
  SBC #$01
Help solve the problem I'm new and just learning a lot I do not understand.
Attachments
collision.zip
(39.34 KiB) Downloaded 92 times
Post Reply