The algo im trying to implement is https://gbdev.io/gb-asm-tutorial/part3/collision.html
This is the code to get the Centers of Both the apple and the snake
shr bx,1
mov [CenterSquare_X], bx
mov bx, [Y]
shr bx,1
mov [CenterSquare_Y], bx
mov bx, [Xapple]
shr bx,1
mov [CenterApple_X], bx
mov bx, [Yapple]
shr bx,1
mov [CenterApple_Y], bx
call check_collision
this is the code fore the collision testing:
mov ax, [CenterSquare_X]
sub ax, [CenterApple_X]
jns DeltaX
neg ax
DeltaX:
cmp ax, [SnakeBody]
jnb NoCollision
mov ax, [CenterSquare_Y]
sub ax, [CenterApple_Y]
jns DeltaY ; Jump short if not sign (SF=0)
neg ax
DeltaY:
cmp ax, [SnakeBody]
jnb NoCollision ; Jump short if not below
Collision:
CALL rnd_y
call rnd_x
Inc [Player_Score]
cmp [Player_Score], 59
jne score_Show
inc [level]
mov [Player_Score], 49
mov cx, [level]
ADD [SnakeBody], cx
ADD [Speed], cx
score_Show:
call set_cursor
call Score
NoCollision:
RET
ENDP check_collision ; hitbox code
For some reason this code only works when the x of the apple is divisible by 5 and the y of the apple is divisible by 5 although the algo should work for cases that is it not on those axiss.
after looking thru a debugger i coudnt find the reason, the collision was working the rnds were working and the centers were working.
My full code:
MODEL small
STACK 100h
DATASEG
; --------------------------
Y dw 100 ; of charchter
X dw 100 ; of charchter
TIME_AUX DB 0 ; for waiting in between frames
PressFlag db 0 ; press flag
SnakeBody dw 5 ; body of charcter
Xapple dw 80 ; y of apple
yapple dw 80 ; x of apple
Random_x dw 80 ; my rnds
Random_y dw 80 ; my rnds
Speed dw 5 ; speed of snake
Player_Score DB 48 ; ascii value of 0
level dw 1
SEED dw 11
FlagForRnd dw 1 ; if its RND_y we can use any y value times 5 if its x it can be any value from 150,1
CenterSquare_Y dw 0
CenterSquare_X dw 0
CenterApple_Y dw 0
CenterApple_X dw 0
Diffrence_Y dw 0
Diffrence_X dw 0
; --------------------------
CODESEG
proc set_cursor
MOV AH, 02h
MOV BH, 0
MOV DH, 1 ; Adjust row for the score display
MOV DL, 1 ; Adjust column for the score display
INT 10h
RET
ENDP set_cursor
PROC Score
mov ah, 09h ; Display character function
mov bh, 0 ; Page number
mov cx, 1 ; Number of times to display character
mov al, [byte ptr Random_x] ; Character to display
ADD AL, '0' ; Convert to ASCII
mov bl, [byte ptr level] ; Attribute (text color)
int 10h
MOV AH, 02h
MOV BH, 0
MOV DH, 1 ; Adjust row for the score display
MOV DL, 1 ; Adjust column for the score display
INT 10h
MOV AH, 02h
MOV BH, 0
MOV DH, 1 ; Adjust row for the score displayx
MOV DL, 20 ; Adjust column for the score display y
int 10h
ENDP Score
PROC moves
MOV AH, 01h ; Function 01h - Check for Key Press
INT 16h
JZ exit_moves ; Jump if ZF is set (no key pressed)
MOV AH, 00h ; Function 00h - Read Key Stroke
INT 16h
; Check if AH contains 'W' (ASCII value 87)
CMP AL, 'w'
je w_pressed
; Check if AH contains 'D' (ASCII value 68)
CMP AL, 'd'
je d_pressed
; Check if AH contains 'A' (ASCII value 65)
CMP AL, 'a'
je a_pressed
; Check if AH contains 'S' 'S'
CMP AL, 's'
JMP s_pressed
exit_moves:
RET
ENDP moves
PROC w_pressed
mov [PressFlag], 1
mov cx , [Speed]
SUB [Y], cx
CHECK_TIME1: ;time checking loop
MOV AH,2Ch ;get the system time
INT 21h ;is the current time equal to the previous one(TIME_AUX)?
CMP DL,[TIME_AUX] ;is the current time equal to the previous one(TIME_AUX)?
JE CHECK_TIME1
MOV [TIME_AUX],DL
CALL draw
call moves
CMP [PressFlag],1
je w_pressed
RET
ENDP w_pressed
PROC d_pressed
mov [PressFlag], 2
mov cx , [Speed]
ADD [X], cx
CHECK_TIME2: ;time checking loop
MOV AH,2Ch ;get the system time
INT 21h ;is the current time equal to the previous one(TIME_AUX)?
CMP DL,[TIME_AUX] ;is the current time equal to the previous one(TIME_AUX)?
JE CHECK_TIME2
MOV [TIME_AUX],DL
CALL draw
call moves
cmp [PressFlag],2
je d_pressed
ret
ENDP d_pressed
PROC a_pressed
mov [PressFlag], 3
mov cx , [Speed]
SUB [X], cx
CHECK_TIME3: ;time checking loop
MOV AH,2Ch ;get the system time
INT 21h ;is the current time equal to the previous one(TIME_AUX)?
CMP DL,[TIME_AUX] ;is the current time equal to the previous one(TIME_AUX)?
JE CHECK_TIME3
MOV [TIME_AUX],DL
CALL draw
call moves
CMP [PressFlag],3
je a_pressed
ret
ENDP a_pressed
PROC s_pressed
mov [PressFlag], 4
mov cx , [Speed]
ADD [Y], cx
CHECK_TIME4: ;time checking loop
MOV AH,2Ch ;get the system time
INT 21h ;is the current time equal to the previous one(TIME_AUX)?
CMP DL,[TIME_AUX] ;is the current time equal to the previous one(TIME_AUX)?
JE CHECK_TIME4
MOV [TIME_AUX],DL
CALL draw
call moves
CMP [PressFlag],4
je s_pressed
RET
ENDP s_pressed
PROC draw
MOV AX, 0C07h ; Function 0Ch, Set Pixel Color
MOV BH, 0 ; Page number (usually 0 in mode 13h)
; Draw the gray border
MOV CX, 40 ; X-coordinate of the left border
MOV DX, 49 ; Y-coordinate of the top border
MOV SI, 0
MOV DI, 0
MOV AL, 8 ; Color for gray pixels
draw_row_loop_border:
draw_pixel_loop_border:
INC CX
INC DI
INT 10h
CMP DI, 240 ; Width of the border
JNE draw_pixel_loop_border
SUB CX, 240 ; Reset X-coordinate to start
MOV DI, 0
INC DX
INC SI
CMP SI, 150 ; Height of the border
JNE draw_row_loop_border
MOV AX, 0C07h ; Function 0Ch, Set Pixel Color
MOV BH, 0 ; Page number (usually 0 in mode 13h)
; Draw the apple
MOV CX, [Xapple] ; X-coordinate of the apple
MOV DX, [yapple] ; Y-coordinate of the apple
MOV SI, 0
MOV DI, 0
MOV AL, 4 ; Color (choose a color different from the snake)
draw_row_loop_apple:
draw_pixel_loop_apple:
INC CX
INC DI
INT 10h
CMP DI, [SnakeBody] ; size of the apple must be the same size of the snake for collison to work
JNE draw_pixel_loop_apple
SUB CX, [SnakeBody] ; without this, the apple is not drawing up; it's drawing to the side
MOV DI, 0
INC DX
INC SI
CMP SI, [SnakeBody]; size of the apple must be the same size of the snake for collison to work
JNE draw_row_loop_apple
; Draw the snake
MOV CX, [X] ; X-coordinate of the snake head
MOV DX, [Y] ; Y-coordinate of the snake head
MOV SI, 0
MOV DI, 0
MOV AL, 2 ; Color green (you can choose a different color)
draw_row_loop:
draw_pixel_loop:
INC CX
INC DI
INT 10h
CMP DI, [SnakeBody]
JNE draw_pixel_loop
SUB CX, [SnakeBody]
MOV DI, 0
INC DX
INC SI
CMP SI, [SnakeBody]
JNE draw_row_loop
mov bx, [X]
shr bx,1
mov [CenterSquare_X], bx
mov bx, [Y]
shr bx,1
mov [CenterSquare_Y], bx
mov bx, [Xapple]
shr bx,1
mov [CenterApple_X], bx
mov bx, [Yapple]
shr bx,1
mov [CenterApple_Y], bx
call check_collision
RET
ENDP draw
PROC check_collision ; checks for collison with snake
mov ax, [CenterSquare_X]
sub ax, [CenterApple_X]
jns DeltaX
neg ax
DeltaX:
cmp ax, [SnakeBody]
jnb NoCollision
mov ax, [CenterSquare_Y]
sub ax, [CenterApple_Y]
jns DeltaY ; Jump short if not sign (SF=0)
neg ax
DeltaY:
cmp ax, [SnakeBody]
jnb NoCollision ; Jump short if not below
Collision:
CALL rnd_y
call rnd_x
Inc [Player_Score]
cmp [Player_Score], 59
jne score_Show
inc [level]
mov [Player_Score], 49
mov cx, [level]
ADD [SnakeBody], cx
ADD [Speed], cx
score_Show:
call set_cursor
call Score
NoCollision:
RET
ENDP check_collision ; hitbox code
;Randoms
PROC rand2num1toValue_Y
push dx
push bx
xor dx, dx ; Compute randval(DX) mod 10 to get num
mov bx, 26 ; between 1 and given value
div bx
inc dx ; DX = modulo from division
mov [Random_y], ax
pop bx
pop dx
RET
ENDP rand2num1toValue_Y
PROC rand2num1toValue_X
push dx
push bx
xor dx, dx ; Compute randval(DX) mod 10 to get num
mov bx, 26 ; between 1 and given value
div bx
inc dx ; DX = modulo from division
mov [Random_x], dx
pop bx
pop dx
ret
ENDP rand2num1toValue_X
; Set LCG PRNG seed to system timer ticks
; Inputs: AX = seed
; Modifies: AX
; Return: nothing
Proc srandsystime
xor ax, ax ; Int 1Ah/AH=0 to get system timer in CX:DX
int 1Ah
mov [seed], dx ; seed = 16-bit value from DX
ret
ENDP srandsystime
PROC rand
push dx
mov ax, 25173 ; LCG Multiplier
mul [word ptr seed] ; DX:AX = LCG multiplier * seed
add ax, 13849 ; Add LCG increment value
mov [seed], ax ; Update seed
; AX = (multiplier * seed + increment) mod 65536
pop dx
ret
ENDP rand
Proc rnd_x
call srandsystime ; Seed PRNG with system time, call once only
call rand ; Get a random number in AX
call rand2num1toValue_X
mov [Xapple], ax
ret
ENDP rnd_x
Proc rnd_y
call srandsystime ; Seed PRNG with system time, call once only
call rand ; Get a random number in AX
call rand2num1toValue_Y
mov [yapple], ax
RET
ENDP rnd_y
PROC game_logic
CHECK_TIME: ;time checking loop
MOV AH, 2Ch ;get the system time
INT 21h ;is the current time equal to the previous one(TIME_AUX)?
CMP DL, [TIME_AUX] ;is the current time equal to the previous one(TIME_AUX)?
JE CHECK_TIME ; if it is the same, skip updating the game state
; If it reaches this point, it's because the time has passed
MOV [TIME_AUX], DL ;update time
CALL moves
call draw
cmp [level] , 1
RET
ENDP game_logic
start:
MOV AX, @data
MOV DS, AX
MOV AX, 13h
INT 10h ; Set video mode 13h (320x200 pixels, 256 colors)
game_loop:
CALL game_logic
JMP game_loop
exit:
MOV AX, 4C00h
INT 21h
END start```
Your code "to get the Centers of Both the apple and the snake" is wrong because you're still halving the coordinates instead of the sizes! I already reported this in my previous answer. You did correct the mixing of X's and Y's though.
Both your Square and your Apple have the same size. You have set it at 5.
Next is what your square and apple look like. I have marked the center of the square by 'S' and the center of the apple by 'A':
This is how you calculate the centers:
For there to be a collision in the X direction, the difference between the X coordinates has to be smaller than 5. The same goes for the difference in the Y direction. And both conditions must be true at the same time.