我在汇编中制作了一个DOS程序,当您按下空格键时会跳一个正方形。
如果在正方形跳跃时按住空格,即使您停止按空格也将继续跳跃。我怎样才能让它仅注意正方形在地面上时所按下的空间?
代码(与TASM一起编译):
IDEAL
MODEL small
STACK 100h
DATASEG
X dw 0
Y dw 0
SquareX dw 20
SquareY dw 193
SquareSize dw 0
color db 1 ; default color is blue
FloorY dw 194
FloorX dw 0
CODESEG
proc HalfSecondDelay
push cx ;Backup
push dx
push ax
MOV CX, 1H
MOV DX, 3H
MOV AH, 86H
INT 15H
pop ax ;Backup
pop dx
pop cx
ret
endp HalfSecondDelay
proc WaitForSpace
EnterSpace: ;Wait until user presses Space
mov ah,0
int 16h
cmp al,32
jne EnterSpace
ret
endp WaitForSpace
proc PlayerJump ;Makes The Square Jump
push cx
mov cx, 10
MoveUp:
Call HalfSecondDelay
call RemovePlayerSquare
sub [SquareY],4 ; Move Up
call PaintPlayerSquare
loop MoveUp
mov cx, 10
MoveDown:
Call HalfSecondDelay
call RemovePlayerSquare
add [SquareY], 4 ; Move Down
Call PaintPlayerSquare
loop MoveDown
pop cx
ret
endp PlayerJump
proc PaintFloorLine
push bp
mov bp,sp
push cx
mov cx, 320
LoopPaintFloorLine:
call PaintPixel
inc [X]
loop loopPaintFloorLine
pop cx
pop bp
ret
endp PaintFloorLine
proc PaintFloor ;Paints The Floor
push bp
mov bp,sp
push cx
mov [x], 0
mov [y], 194
mov [color], 0Ah
mov cx, 7
loopPaintFloor:
call PaintFloorLine
inc [Y]
mov [x], 0
loop loopPaintFloor
pop cx
pop bp
ret
endp PaintFloor
proc PaintPixel
push bp
mov bp,sp
push ax
push bx
push cx
push dx
mov cx,[X]
mov dx,[Y]
mov al,[color]
mov ah,0ch
int 10h
pop dx
pop cx
pop bx
pop ax
pop bp
ret
endp PaintPixel
proc PaintLine
push bp
mov bp,sp
push cx
mov cx, [SquareSize]
loopPaintLine:
call PaintPixel
inc [X]
loop loopPaintLine
mov cx, [SquareSize] ; Return The X
sub [X], cx
pop cx
pop bp
ret
endp PaintLine
proc PaintSquare ;Paints A Sqaure
push bp
mov bp,sp
push cx
mov cx, [SquareSize]
loopPrinSquare:
call PaintLine
dec [Y]
loop loopPrinSquare
mov cx, [SquareSize] ; Return The Y
add [Y], cx
pop cx
pop bp
ret
endp PaintSquare
proc PaintPlayerSquare ; Paints The Player Square
push bp
mov bp,sp
mov ax, [SquareX]
mov [x], ax
mov ax, [SquareY]
mov [Y], ax
mov [SquareSize], 25
mov [color], 1 ; blue color
call PaintSquare ;
pop bp
ret
endp PaintPlayerSquare
proc RemovePlayerSquare ;Removes The Player Square
push bp
mov bp,sp
push ax
push bx
push cx
push dx
mov ax, [SquareX]
mov [x], ax
mov ax, [SquareY]
mov [Y], ax
mov [color], 0 ; black color
call PaintSquare ;
pop dx
pop cx
pop bx
pop ax
pop bp
ret
endp RemovePlayerSquare
proc GraphicsScreen
mov al, 13h
mov ah, 0
int 10h
ret
endp GraphicsScreen
start:
mov ax, @data
mov ds, ax
Call GraphicsScreen
Call PaintFloor
Call PaintPlayerSquare
loopSquareJump:
Call WaitForSpace
Call PlayerJump
jmp loopSquareJump
exit:
mov ax, 4c00h
int 21h
END start
答案 0 :(得分:1)
您的问题来自于不想在键盘缓冲区中保留的 Space 按键,导致以后需要处理。一种解决方案是在等待按下 Space 之前清除键盘缓冲区,如下所示:
proc ClearKeyboardBuffer
ClearKeyboardBuffer_loop:
mov ah,01h
int 16h ; is there a key pressed
jz ClearKeyboardBuffer_ret ; if not, return
mov ah,00h
int 16h ; "handle" the key
jmp ClearKeyboardBuffer_loop
ClearKeyboardBuffer_ret:
ret
endp ClearKeyboardBuffer
然后只需像这样修改循环:
loopSquareJump:
Call ClearKeyboardBuffer
Call WaitForSpace
Call PlayerJump
jmp loopSquareJump
但是,这不是一个好方法。根据{{3}}:
如果您要使用BIOS功能从游戏的键盘中进行读取, 清除缓冲区的最快方法是使其尾部等于 头:读取0x0041A处的值并将其写入0x0041C( 禁用中断):
proc clearkeyboardbuffer ; AX is clobbered push ds mov ax, 0040h mov ds, ax mov ax, [001Ah] mov [001Ch], ax pop ds ret endp clearkeyboardbuffer
(BIOS键盘缓冲区是一个从0x0041E开始的循环列表,并且 0x0041A指向缓冲区的头部,0x0041C指向缓冲区的尾部。如果两者 指针相等,缓冲区为空。)
如果有兴趣,请阅读更多Stephen Kitt's answer on Retrocomputing。