The algorithm was made by GB-ASM:
You check the differences between 2 centers of 2 objects,and if the absolute value of the 2 differences are both smaller then the sam of their half widths, there is a collision.
My TASM code:
PROC check_collision ; checks for collision with snake
mov bx, [X]
shr bx,1
mov [CenterSquare_Y], bx
mov bx, [Y]
shr bx,1
mov [CenterSquare_X], bx
; Find middle point of apple
mov bx, [Xapple]
shr bx,1
mov [CenterApple_X], bx
mov bx, [Yapple]
shr bx,1
mov [CenterApple_Y], bx
mov cx , [CenterSquare_Y]
mov bx , [CenterApple_Y]
SUB bx , cx
mov [Diffrence_Y] , bx
cmp bx , 0
jg check_Diffrence
Neg bx
mov cx , [CenterSquare_X]
mov bx , [CenterApple_X]
SUB bx , cx
mov [Diffrence_X] , bx
cmp bx , 0
jg check_Diffrence
Neg bx
check_Diffrence:
mov ax, [SnakeBody]
shr ax ,1
cmp [Diffrence_Y] , ax
jne skip_draw_apple
cmp [Diffrence_X] , ax
jne skip_draw_apple
CALL rnd_y
call rnd_x
skip_draw_apple:
RET
ENDP check_collision
Full code:
IDEAL
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 50 ; my rnds
Random_y dw 50 ; 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 it's RND_y we can use any y value times 5 if it's 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 display x
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 Keystroke
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'
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 collision 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 collision 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
; after moving snake find center square and center apple
; Find middle point of SNAKE
CALL check_collision
RET
ENDP draw
PROC check_collision ; checks for collision with snake
mov bx, [X]
shr bx,1
mov [CenterSquare_Y], bx
mov bx, [Y]
shr bx,1
mov [CenterSquare_X], bx
; Find middle point of apple
mov bx, [Xapple]
shr bx,1
mov [CenterApple_X], bx
mov bx, [Yapple]
shr bx,1
mov [CenterApple_Y], bx
mov cx , [CenterSquare_Y]
mov bx , [CenterApple_Y]
SUB bx , cx
mov [Diffrence_Y] , bx
cmp bx , 0
jg check_Diffrence
Neg bx
mov cx , [CenterSquare_X]
mov bx , [CenterApple_X]
SUB bx , cx
mov [Diffrence_X] , bx
cmp bx , 0
jg check_Diffrence
Neg bx
check_Diffrence:
mov ax, [SnakeBody]
shr ax ,1
cmp [Diffrence_Y] , ax
jne skip_draw_apple
cmp [Diffrence_X] , ax
jne skip_draw_apple
CALL rnd_y
call rnd_x ; moves snake to x coords
;mov dx, [Random_x]
;ADD DX , 40 ; CURRENTLY BROKEN FIX BY GETTING ACTUAL TRUE RANDOMS ALSO NUMBER THAT IS ADDED MUST BE DIVISIBLE BY THE SPEED OF BODY OF SNAKE!!!
;mov [Xapple], dx
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
skip_draw_apple:
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], dx
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 cx, AX ; save AX in register
mov AX, [Random_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 cx, AX ; save AX in register
mov AX , 0
mov al, 5 ; CHANGE LATER TO FIT GRID
mul cx
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
The Collision isn't working I know that because the apple isn't moving when you are supposed to collide.
Your check_collision proc is so not implementing the above description! It's utter nonsense because it is halving the coordinates instead of the sizes, it is mixing X's and Y's, and it does a lot more stuff that simply can't work.
Forget about the above algorithm and see how it can work.
Both your Square and your Apple have the same size. You have set it at 5.
The way you draw them is special but hey, it can work. This is what it looks like:
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.