DOS汇编程序优化:如何让方块仅在地面时响应空格跳跃
解决方法:仅在方块处于地面时响应空格键
要解决这个问题,我们需要跟踪方块的状态(是否在地面),并避免在跳跃过程中响应按键输入。原代码的问题在于使用了阻塞式的按键等待,且没有检查方块位置就触发跳跃,导致缓冲区的按键会被重复处理。以下是具体修改步骤:
1. 添加地面状态变量
首先在数据段定义一个变量来标记方块是否处于地面:
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 IsOnGround db 1 ; 1 = 在地面,0 = 在空中
2. 替换阻塞式按键等待为非阻塞检查
原代码的WaitForSpace过程会阻塞程序直到按下空格,这会导致跳跃过程中按住空格时,缓冲区积累多个按键事件。我们需要在主循环中使用非阻塞的按键检查(int 16h的1号功能),只在方块在地面时响应空格。
3. 修改主循环逻辑
移除原来的loopSquareJump阻塞循环,替换为非阻塞的主循环,加入状态判断:
start: mov ax, @data mov ds, ax Call GraphicsScreen Call PaintFloor Call PaintPlayerSquare mov [IsOnGround], 1 ; 初始状态:方块在地面 loopMain: ; 非阻塞检查是否有按键输入 mov ah, 1 int 16h jz SkipKeyCheck ; 没有按键,跳过处理 ; 读取按键 mov ah, 0 int 16h cmp al, 32 jne SkipKeyCheck ; 不是空格键,跳过 ; 检查是否在地面 cmp [IsOnGround], 1 jne SkipKeyCheck ; 不在地面,忽略按键 ; 触发跳跃:标记为空中,执行跳跃过程 mov [IsOnGround], 0 Call PlayerJump mov [IsOnGround], 1 ; 跳跃结束,回到地面 SkipKeyCheck: ; 加入短延迟避免循环过快(可根据需要调整时长) push cx push dx push ax MOV CX, 0H MOV DX, 1000H ; 更短的延迟,比如1ms左右 MOV AH, 86H INT 15H pop ax pop dx pop cx jmp loopMain
4. 移除无用的WaitForSpace过程
因为我们不再使用阻塞式等待,所以可以删除WaitForSpace过程,减少冗余代码。
修改后的完整代码
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 IsOnGround db 1 ; 1 = 在地面,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 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 Square 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 mov [IsOnGround], 1 ; 初始状态标记为在地面 loopMain: ; 非阻塞检查按键缓冲区 mov ah, 1 int 16h jz SkipKeyCheck ; 读取按键 mov ah, 0 int 16h cmp al, 32 jne SkipKeyCheck ; 验证是否在地面 cmp [IsOnGround], 1 jne SkipKeyCheck ; 执行跳跃 mov [IsOnGround], 0 Call PlayerJump mov [IsOnGround], 1 SkipKeyCheck: ; 短延迟,防止循环占用过多CPU push cx push dx push ax MOV CX, 0H MOV DX, 500H MOV AH, 86H INT 15H pop ax pop dx pop cx jmp loopMain exit: mov ax, 4c00h int 21h END start
关键说明
- 状态跟踪:
IsOnGround变量确保只有当方块回到地面后,才会响应下一次空格键按压。 - 非阻塞按键检查:使用
int 16h的1号功能(ah=1)检查按键,不会阻塞主循环,程序可以同时处理跳跃动画和输入。 - 清空按键缓冲区:当读取按键(
ah=0)时,会移除缓冲区中的按键事件,避免跳跃过程中积累的空格被重复处理。
内容的提问来源于stack exchange,提问作者yoav
相关产品推荐
相关产品推荐

