在TASM中实现碰撞算法

问题描述 投票:0回答:1

算法由GB-ASM制定:
您检查 2 个物体的 2 个中心之间的差异,如果两个差异的绝对值小于它们的半宽度的总和,则存在碰撞。

我的 TASM 代码:

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

完整代码:

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

碰撞不起作用我知道,因为当你应该碰撞时苹果没有移动。

assembly game-development collision x86-16 tasm
1个回答
1
投票

算法由GB-ASM制定:
您检查 2 个物体的 2 个中心之间的差异,如果两个差异的绝对值小于它们的半宽度的总和,则存在碰撞。

您的 check_collision 过程是 so 没有实现上述描述!这完全是无稽之谈,因为它是将坐标而不是大小减半,它混合了 X 和 Y,而且它做了很多根本无法工作的事情。
忘记上面的算法,看看它是如何工作的。

您的 Square 和 Apple 的尺寸相同。您已将其设置为 5。
你绘制它们的方式很特别,但是嘿,它可以工作。这就是它的样子:

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

为了在 X 方向上发生碰撞,X 坐标之间的差必须小于 5。 Y方向的差值也是如此。并且这两个条件必须同时成立。

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
© www.soinside.com 2019 - 2024. All rights reserved.