如何使用mov ah,0 int 16h让蛇不断移动

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

我正在制作贪吃蛇游戏并遇到了问题。 目前,我使用了

int 21h
,因此它仅在我按下某个键时才会移动。现在我希望它连续移动,这样它就不会等待我按键,而只是检查缓冲区中是否有东西。为此,我使用
ah 0h and int 16h
但是,我不知道如何做到它会始终移动。我想我需要在某处添加一个循环来检查
dir
中的内容,并基于此它到达它应该去的地方,但我只是不知道循环应该是什么样子(我也认为我应该如果我没记错的话,请使用延迟)。 我认为相关部分是:

    mov ah, 0h
    int 16h
    mov [byte ptr saveal], al
    
    cmp [byte ptr saveal], 'w'
    jz w
    cmp [byte ptr saveal], 'a'
    jz a
    cmp [byte ptr saveal], 's'
    jz s
    cmp [byte ptr saveal], 'd'
    jz d
    cmp [byte ptr saveal], 'q'
    jmp exit
    
w:
    mov [byte ptr dir], 1
    call up
    jmp wasd
s:
    mov [byte ptr dir], 2
    call down
    jmp wasd    
a:
    mov [byte ptr di], 3
    call left
    jmp wasd
d:
    mov [byte ptr dir], 4
    call right
    jmp wasd

整个代码是:

MODEL small
STACK 100h
DATASEG
; --------------------------
; Your variables here
; --------------------------
saveal db ' '
dir db 0       ;not used

app dw 0       ;place of the apple
st_am dw 3
stars dw 0, 0, 0  ;places of the *

CODESEG
proc black
body:
    mov [es:si], ax
    add si, 2
    cmp si, 25*80*2
    jnz body
  ret
endp black

proc up
    mov di, 80*2
    cmp si, di
    jb not_move_up
    
    cmp si, [app]
    jnz move_up
    call apple
    
move_up:
    call delete
    call replace_stars

    sub si, 80*2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
    mov [stars], si
    
not_move_up:
  ret
endp up
proc down

    mov di, (24*80*2)-1
    cmp si, di
    jg not_move_down
    
    cmp si, [app]
    jnz move_down
    call apple
    
move_down:
    call delete
    call replace_stars
    
    add si, 80*2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
    mov [stars], si
    
not_move_down:
  ret
endp down
proc left

    mov dx, 0
    mov bx, si
    mov ax, si
    mov si, 80*2
    div si
    mov si, bx
    cmp dx,0
    jz not_move_left
    
    cmp si, [app]
    jnz move_left
    call apple
    
move_left:
    call delete
    call replace_stars
    
    sub si, 2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
    mov [stars], si
    
not_move_left:
  ret
endp left
proc right

    mov dx, 0
    mov bx, si
    mov ax, si
    mov si, 80*2
    div si
    mov si, bx
    cmp dx,158
    jz not_move_right
    
    cmp si, [app]
    jnz move_right
    call apple
    
move_right:
    call delete
    call replace_stars
    
    add si, 2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
    mov [stars], si
    
not_move_right:
  ret
endp right

proc apple
    mov ax, 40h
    mov es, ax
    mov ax, [es:6ch]
    and ax, 0000001111111110b
    mov di,ax
    mov [app], di
    mov ax, 0b800h
    mov es, ax
    
    mov al, '@'
    mov ah, 154
    mov [es:di], ax
  ret 
endp apple
    
proc delete
    mov bx, offset stars
    mov di, [st_am]
    dec di
    shl di, 1
    mov di, [bx+di]
    mov ax, 0b800h
    mov es, ax
    
    mov al, ' '
    mov ah, 0
    
    mov [es:di], ax
  ret
endp delete

proc replace_stars
    mov  bx, [st_am]   ; The amount of stars (3 or more)
    dec  bx
    shl  bx, 1         ; Offset to the last star
replace:
    mov  ax, [stars+bx-2]
    mov  [stars+bx], ax
    sub  bx, 2
    jnz  replace
  ret
endp replace_stars

proc first_3_dots
    mov bx, offset stars
    mov si, ((12*80+40)*2)-2
    mov al, '*'
    mov ah, 156
    mov [es:si], ax
    mov [bx], si
    mov si, (12*80+40)*2
    mov al, '*'
    mov ah, 156
    mov [es:si], ax
    mov [bx+2], si
    mov si, ((12*80+40)*2)+2
    mov al, '*'
    mov ah, 156
    mov [es:si], ax
    mov [bx+4], si
  ret
endp first_3_dots

proc delay
    mov cx, 0FFFFh
delay1:
    mov ax, 300
delay2:
    dec ax
    jnz delay2
    loop delay1
  ret
endp delay

proc incS
    
  ret
endp incS

start:
    mov ax, @data
    mov ds, ax
; --------------------------
; Your code here
; --------------------------
    mov ax, 0b800h
    mov es, ax
    
    mov si,0
    mov al, ' '
    mov ah, 0
    call black
    
    call first_3_dots
    mov si, ((12*80+40)*2)-2    

    call apple
    
wasd:
    mov ah, 0h
    int 16h
    mov [byte ptr saveal], al
    
    cmp [byte ptr saveal], 'w'
    jz w
    cmp [byte ptr saveal], 'a'
    jz a
    cmp [byte ptr saveal], 's'
    jz s
    cmp [byte ptr saveal], 'd'
    jz d
    cmp [byte ptr saveal], 'q'
    jmp exit
    
w:
    mov [byte ptr dir], 1
    call up
    jmp wasd
s:
    mov [byte ptr dir], 2
    call down
    jmp wasd    
a:
    mov [byte ptr di], 3
    call left
    jmp wasd
d:
    mov [byte ptr dir], 4
    call right
    jmp wasd
    
exit:
    mov ax, 4c00h
    int 21h
END start
assembly buffer x86-16 dosbox
1个回答
0
投票

您可以使用 Int 16h 和函数 01h(非阻塞)来检查是否已按下某个键,如果是,则使用函数 00h 来读取该键。

这些可能由 MSVC 的

_kbhit()
_getch()
使用,其中某些按键将提供多个字符:如果第一个是“转义”值,例如用于功能和光标控制键的 0 或 224,则为另一个值立即可用。

这可能也是那些 BIOS 功能的工作方式。您似乎没有使用光标控制键,但也许您现在可以了!

© www.soinside.com 2019 - 2024. All rights reserved.