Hello.
I want to make a collision with sprites but it turns out only to line the whole height of the screen.
Code:
COLLISION = $B5
Code:
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:
LoadObject:
LDA object, x
STA $0300, x
INX
CPX #$10
Is there any particular reason you're doing
Code:
LDA $0203
CLC
ADC #$01
STA $0203
Instead of just INCing $0203? The only reason I ask is because I see you DECing $0203.
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!
Button presses was discussed here recently...
viewtopic.php?f=10&t=13106&start=15And I wrote a simplified Sprite vs Sprite collision code here...
viewtopic.php?f=10&t=12993&p=150683You can learn a ton by searching old forum posts.
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.
Here's another simple collision article, if you still need help.
http://www.gamedev.net/page/resources/_ ... ction-r735What 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.
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:
PLAYER = $0203
OBJECT = $0300
but get an error during initialization:
Code:
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?
belltone wrote:
Code:
PLAYER = $0203
Code:
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 "#".
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:
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:
lda #MYCONSTANT
is actually saying "treat this label's address as an immediate value." and gets assembled as
Code:
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:
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.
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.
Attachment:
collision.jpg [ 55.04 KiB | Viewed 3281 times ]
I changed it to assembler ASM6.
Declare variables:
Code:
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.
Attachment:
hex_object.jpg [ 199.97 KiB | Viewed 3281 times ]
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:
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;}
Attachment:
collision_1_new.zip [31.22 KiB]
Downloaded 86 times
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.
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:
check_collision .dsb 1
COLLISION = $DE
Object detection:
Code:
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?
Attachment:
collizion_2.zip [30.06 KiB]
Downloaded 93 times
You may be aware, but we are having this same discussion in a different thread...
viewtopic.php?f=2&t=13279I 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.
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:
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:
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.
Quote:
LDA $2002
Let's review what PPU Register $2002 does.
At the beginning of V-blank, the 1000 0000 ($80) bit will become 1. Code usually checks this from the $2002 register when NMIs are not active (because NMIs also occur at the start of V-blank, you don't need to check if you're in V-blank...the program will jump to the NMI code at the start of V-blank, so we already know it is occurring).
During the rendering portion...if the PPU detects that a non-transparent pixel of sprite zero (the very first sprite) overlap a non- transparent pixel of the background, the 0100 0000 ($40) bit of $2002 will become 1. Games typically use this to time scrolling splits mid-screen. They never use this (sprite zero hit) to detect object collision.
Furthermore, if the PPU detects that you have more than 8 sprites on a scanline, the 0010 0000 bit ($20) will become 1. This may not be useful to you, but some people have used this to time a second mid-frame event, like a second scrolling split. These 8 sprites can be completely transparent... the PPU doesn't know the difference.
Finally, reading from $2002 (LDA $2002) also has the effect of resetting writes to $2005/2006 back to 'waiting for the first write'.
Again, collision detection is not done with $2002.