如何忽略多个按键?

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

我在程序集中制作了一个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
assembly dos x86-16 tasm
1个回答
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

然而,这不是一个很好的方法。据Stephen Kitt's answer on Retrocomputing说:

如果您正在使用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指向它的尾部。如果两个指针相等,则缓冲区为空。)

如果您有兴趣,请阅读更多on the original answer

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