x86汇编实现双人Tron游戏双玩家同步移动的问题
解决双人Tron游戏双玩家同时移动的问题
当前代码的核心问题是单次仅处理一个按键输入:使用int 16h 00h读取按键时会清空缓冲区的单个按键,导致同时按住两个键时,后读取的按键会覆盖前一个的处理逻辑,无法同时跟踪两个玩家的输入状态。
解决方案
改为跟踪玩家的移动方向状态,先一次性读取键盘缓冲区中所有待处理的按键,更新两个玩家的当前方向变量,再统一处理两个玩家的移动逻辑,确保两者的输入都被正确响应。
具体实现步骤
定义方向状态变量
新增两个字节变量,记录每个玩家的当前移动方向:; 方向定义:0=停止,1=左,2=右,3=上,4=下 plyr1_dir db 0 plyr2_dir db 0重写
move_players过程
分两步执行:- 第一步:遍历键盘缓冲区所有按键,更新玩家方向(支持按键按下/抬起的状态切换)
- 第二步:根据方向变量分别处理两个玩家的移动、碰撞检测与绘制
修改后的完整代码:
move_players proc ; 第一步:读取所有键盘输入,更新玩家方向状态 read_keys: mov ah, 01h ; 检查缓冲区是否有按键 int 16h jz process_movement ; 无按键则进入移动处理 mov ah, 00h ; 读取按键(AH=扫描码,AL=ASCII码) int 16h ; 玩家1 WASD按键处理(按下) cmp ah, 1Eh ; 'A'键扫描码 je set_plyr1_left cmp ah, 20h ; 'S'键扫描码 je set_plyr1_down cmp ah, 11h ; 'W'键扫描码 je set_plyr1_up cmp ah, 21h ; 'D'键扫描码 je set_plyr1_right ; 玩家1 WASD按键处理(抬起) cmp ah, 1Eh+80h ; 'A'键抬起扫描码 je reset_plyr1_move cmp ah, 20h+80h ; 'S'键抬起扫描码 je reset_plyr1_move cmp ah, 11h+80h ; 'W'键抬起扫描码 je reset_plyr1_move cmp ah, 21h+80h ; 'D'键抬起扫描码 je reset_plyr1_move ; 玩家2 方向键处理(按下) cmp ah, 75h ; 左方向键扫描码 je set_plyr2_left cmp ah, 72h ; 上方向键扫描码 je set_plyr2_up cmp ah, 77h ; 右方向键扫描码 je set_plyr2_right cmp ah, 70h ; 下方向键扫描码 je set_plyr2_down ; 玩家2 方向键处理(抬起) cmp ah, 75h+80h ; 左方向键抬起扫描码 je reset_plyr2_move cmp ah, 72h+80h ; 上方向键抬起扫描码 je reset_plyr2_move cmp ah, 77h+80h ; 右方向键抬起扫描码 je reset_plyr2_move cmp ah, 70h+80h ; 下方向键抬起扫描码 je reset_plyr2_move ; 其他按键忽略,继续读取下一个 jmp read_keys ; 设置玩家1方向的分支 set_plyr1_left: mov byte ptr [plyr1_dir], 1 jmp read_keys set_plyr1_right: mov byte ptr [plyr1_dir], 2 jmp read_keys set_plyr1_up: mov byte ptr [plyr1_dir], 3 jmp read_keys set_plyr1_down: mov byte ptr [plyr1_dir], 4 jmp read_keys reset_plyr1_move: mov byte ptr [plyr1_dir], 0 jmp read_keys ; 设置玩家2方向的分支 set_plyr2_left: mov byte ptr [plyr2_dir], 1 jmp read_keys set_plyr2_right: mov byte ptr [plyr2_dir], 2 jmp read_keys set_plyr2_up: mov byte ptr [plyr2_dir], 3 jmp read_keys set_plyr2_down: mov byte ptr [plyr2_dir], 4 jmp read_keys reset_plyr2_move: mov byte ptr [plyr2_dir], 0 jmp read_keys ; 第二步:根据方向状态处理玩家1移动 process_movement: mov al, [plyr1_dir] cmp al, 1 je move_plyr1_left cmp al, 2 je move_plyr1_right cmp al, 3 je move_plyr1_up cmp al, 4 je move_plyr1_down jmp process_plyr2 move_plyr1_left: call plyr1_trace mov ax, [plyr1X] dec ax mov [plyr1X], ax call plyr1_check call plyr1_draw jmp process_plyr2 move_plyr1_right: call plyr1_trace mov ax, [plyr1X] inc ax mov [plyr1X], ax call plyr1_check call plyr1_draw jmp process_plyr2 move_plyr1_up: call plyr1_trace mov ax, [plyr1Y] dec ax mov [plyr1Y], ax call plyr1_check call plyr1_draw jmp process_plyr2 move_plyr1_down: call plyr1_trace mov ax, [plyr1Y] inc ax mov [plyr1Y], ax call plyr1_check call plyr1_draw jmp process_plyr2 ; 第三步:根据方向状态处理玩家2移动 process_plyr2: mov al, [plyr2_dir] cmp al, 1 je move_plyr2_left cmp al, 2 je move_plyr2_right cmp al, 3 je move_plyr2_up cmp al, 4 je move_plyr2_down jmp move_end move_plyr2_left: call plyr2_trace mov ax, [plyr2X] dec ax mov [plyr2X], ax call plyr2_check call plyr2_draw jmp move_end move_plyr2_right: call plyr2_trace mov ax, [plyr2X] inc ax mov [plyr2X], ax call plyr2_check call plyr2_draw jmp move_end move_plyr2_up: call plyr2_trace mov ax, [plyr2Y] dec ax mov [plyr2Y], ax call plyr2_check call plyr2_draw jmp move_end move_plyr2_down: call plyr2_trace mov ax, [plyr2Y] inc ax mov [plyr2Y], ax call plyr2_check call plyr2_draw jmp move_end move_end: ret move_players ENDP
关键改进点
- 一次性读取键盘缓冲区所有按键,确保两个玩家的输入都被捕获,不会互相覆盖
- 用方向变量持久化玩家的移动状态,支持按住按键持续移动、松开停止的逻辑
- 分离输入处理与移动逻辑,先统一更新状态,再执行移动,保证双玩家同时响应
内容的提问来源于stack exchange,提问作者Jeszenői Bálint
相关产品推荐
相关产品推荐

