Implementing a collision algorithm in TASM

73 Views Asked by At

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.

1

There are 1 best solutions below

0
Sep Roland On

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.

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:

          Xsquare                 Xapple
          |                       |
          v                       v
Ysquare ->.*****         Yapple ->.*****
           *****                   *****
           *****                   *****
           *****                   *****
           *****                   *****

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.

Xsqr  Xapp    DifferenceX is 6 -> No collision
|     |
v     v
.*****.*****
 ***** *****
 ***** *****
 ***** *****
 ***** *****

Xsqr Xapp    DifferenceX is 5 -> No collision
|    |
v    v
.****.*****
 **********
 **********
 **********
 **********

XsqrXapp    DifferenceX is 4 -> Collision (only if DifferenceY is < 5)
|   |
v   v
.***.@****
 ****@****
 ****@****
 ****@****
 ****@****
PROC check_collision
  mov  ax, [Xsquare]
  sub  ax, [Xapple]
  jns  DeltaX
  neg  ax
DeltaX:
  cmp  ax, [SnakeBody]
  jnb  NoCollision

  mov  ax, [Ysquare]
  sub  ax, [Yapple]
  jns  DeltaY
  neg  ax
DeltaY:
  cmp  ax, [SnakeBody]
  jnb  NoCollision
Collision:

  ...  Here you do whatever it is that you need to do

NoCollision:
    ret
ENDP check_collision