我正在制作贪吃蛇游戏并遇到了问题。 目前,我使用了
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
您可以使用 Int 16h 和函数 01h(非阻塞)来检查是否已按下某个键,如果是,则使用函数 00h 来读取该键。
这些可能由 MSVC 的
_kbhit()
和 _getch()
使用,其中某些按键将提供多个字符:如果第一个是“转义”值,例如用于功能和光标控制键的 0 或 224,则为另一个值立即可用。
这可能也是那些 BIOS 功能的工作方式。您似乎没有使用光标控制键,但也许您现在可以了!