Collision vs screen rendering difference

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

Post Reply
User avatar
zanto
Posts: 57
Joined: Sun Mar 07, 2021 11:15 pm
Location: Rio de Janeiro, Brazil

Collision vs screen rendering difference

Post by zanto »

So, I'm having trouble with collision detection being displayed on screen. What I have of the collision detection algorithm works so far (it only checks vertically)... but it works on the code, the results seem okay when I check the values in the debugger. However, when I look at the screen, the bullet (the small sprite) is 4 pixels far from the enemy (the white ball). I marked in blue the sprites' vertical center position. This screenshot was taken at the frame the debugger froze the emulator. I put a breakpoint in an instruction after the collision is detected.
Untitled.png
Untitled.png (3.82 KiB) Viewed 4024 times
This is the bullet behavior routine. It checks for collision before moving the bullet. This code is executed almost at the beginning of the game loop (only after controls):

Code: Select all

COLLISION_ENEMY_TEST_LOOP:
	LDA BigEntType, Y			; find enemies to check for collision
	CMP #EntityType::Enemy
	BNE AFTER_ENEMY_TEST
	STX arg1						; store bullet's index in entity array
	LDA #COLLISION_PLAYER_BULLET
	STA arg2						; store bullet's index in collision data array
	STY arg3						; store enemy's index in entity array
	LDA #COLLISION_ENEMY_TYPE1
	STA arg4						; store enemy's index in collision data array
	STX store_x
	STY store_y
	JSR CHECK_COLLISION			; check if collision happened (we don't do anything with it so far)
	LDX store_x
	LDY store_y
AFTER_ENEMY_TEST:
	INY
	TYA
	;CMP #MAX_ENTITIES
	;BEQ AFTER_COLLISION_TEST
	;JMP COLLISION_ENEMY_TEST_LOOP
AFTER_COLLISION_TEST:
	
	LDA BigEntYPos, X				; update bullet's y pos
	SEC
	SBC #$04
	BCS :+
	JSR DELETE_BIG_ENTITY
	JMP AFTER_PLAYER_BULLET_BEHAVIOR
:
	STA BigEntYPos, X
.endproc	
I put this code right at the beginning of the main loop because I thought the collision would work with the values displayed on screen. What am I missing this time?
Last edited by zanto on Sat Mar 13, 2021 9:48 pm, edited 1 time in total.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Collision vs screen rendering difference

Post by tokumaru »

Games need to have all their state computed before a new visual frame can be generated and displayed, so at the time you detect the collision in the code, it's still the previous frame being displayed on the screen. After the collision is detected, you still have to react to it, define the new positions of all the sprites, etc., etc. and then when the next vblank starts, an NMI will fire and all the information computed during your game logic loop will be drawn on the screen, and only then you'll be able to see the consequences of the collision.
User avatar
zanto
Posts: 57
Joined: Sun Mar 07, 2021 11:15 pm
Location: Rio de Janeiro, Brazil

Re: Collision vs screen rendering difference

Post by zanto »

Yeah, I imagine I'm getting the order I'm supposed to do things wrong. I had it even worse before, there was a difference of 8 pixels.

Right now what I have is:

1) main loop starts
2) check collision
3) update bullet position
4) load sprites into memory
5) wait for screen render, screen renders
6) back to main loop

I thought that since the y position is computed on the previous frame and the collision would only be computed after the bullet being shown on the correct spot.

If I change things like this, I get the same problem as before, the bullet is shown 8 pixels below the enemy when triggering the collision:
1) main loop starts
2) update bullet position
3) check collision
4) load sprites into memory
5) wait for screen render, screen renders
6) back to main loop

Is there a standard order to do these things?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Collision vs screen rendering difference

Post by tokumaru »

zanto wrote: Sat Mar 13, 2021 10:13 pmYeah, I imagine I'm getting the order I'm supposed to do things wrong.
This is not about the order of the game logic at all... no matter what you do, you will not get an immediate graphical representation of something that just happened in the game logic! The NES isn't automatically drawing your game's state to the screen, everything that the NES draws, it does because YOU tell it to. And once you do tell it what to draw, it needs to wait until the NEXT vblank in order to actually update what's on screen. If you're setting up a breakpoint for something that's happening in the game logic, there's no way that this condition will be visible on the screen before the next frame is rendered.
2) check collision
3) update bullet position
Well, people normally want to move objects first, then check for collisions, because some things may have to be adjusted in response to the collisions. For example, if your player collides against a wall or another solid object, you'll want to eject it before the next frame is drawn, otherwise the player sprite will be displayed inside the wall or solid object for a frame.
Is there a standard order to do these things?
This can vary a lot depending on how complex the collisions are in the game (e.g. whether objects can push others, carry others, etc.), but typically you'll want to move everything and validate all the new positions and states before you start buffering stuff to render, to make sure that you're always rendering a consistent game state.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Collision vs screen rendering difference

Post by unregistered »

tokumaru, thank you so much for reminding me about always slow screen updates! :D Collision is rough to troubleshoot when this fact is missing.
Post Reply