在组装中制作乒乓游戏时,如何一次输入多个按键? [英] Making a pong game in assembly, how do I get an input of multiple keystyokes at once?
问题描述
我是一个初学者,所以这段代码可能没有什么用,我为此使用了 int 16h
,但对此 int
知之甚少.我刚刚发现您一次不能进行多次击键.有帮助吗?
这段代码的问题在于,一次只能移动一块板,而我俩都需要.如何检查多个输入?
I'm a beginner so this code probably isn't any good, I used int 16h
for this but I don't know a lot about this int
. I just found out you can't have multiple keystrokes at once; any help?
The problem with this code is that only one board can move at a time and I need both. How do I check for multiple inputs?
以下是任何人想要的代码:
Here's the code for anyone who wants it:
IDEAL
MODEL small
STACK 100h
DATASEG
; --------------------------
; Your variables here
; --------------------------
line1X dw 80
line1Y dw 120
line1start dw 5
line1end dw 10
line2X dw 80
line2Y dw 120
line2start dw 310
line2end dw 315
CODESEG
proc startVideo ;creates video mode
mov al,13h
mov ah,0h
int 10h
ret
endp startVideo
proc clearScrean ;turns the screen black
mov ah, 0ch
xor al,al
mov dx,200
BlankLine:
mov cx,320
BlankColumn:
int 10h
Loop BlankColumn
dec dx
cmp dx,0
jne BlankLine
ret
endp clearScrean
proc drawboard ;creates the board
push bp
mov bp,sp
mov al,0fh
mov ah,0ch
beginning equ [bp+10]
fn equ [bp+8]
X equ [bp+6] ;boards start
Y equ [bp+4] ;boards end
mov dx,Y
drawrow:
mov cx,fn
drawcolumn:
int 10h
dec cx
cmp cx,beginning
jne drawcolumn
dec dx
cmp dx,X
jne drawrow
pop bp
ret 8
endp drawboard
proc drawall
push [line1start]
push [line1end]
push [line1X]
push [line1Y]
call drawboard
push [line2start]
push [line2end]
push [line2X]
push [line2Y]
call drawboard
ret
endp drawall
proc boardup
push bp
mov bp,sp
mov bx,[bp+4]
mov si,[bp+6]
cmp [word ptr bx],0 ;checks if board didnt get to border
je fn1
call clearScrean
sub [word ptr bx],5 ;3 pixels added to board
sub [word ptr si],5
call drawall ;prints both boards
fn1:
pop bp
ret 4
endp boardup
proc boarddown
push bp
mov bp,sp
mov bx,[bp+4]
mov si,[bp+6]
cmp [word ptr si],200 ;checks if board didnt get to border
je fn2
call clearScrean
add [word ptr bx],5 ;3 pixels added to board
add [word ptr si],5
call drawall ;prints both boards
fn2:
pop bp
ret 4
endp boarddown
start:
mov ax, @data
mov ds, ax
mov bh,0
call startVideo
call clearScrean
call drawall
checkskey: ;checks if key is being pressed
mov ah,1
int 16h
jz checkskey ;jumps if key isnt pressed
mov ah,0 ;checks which key is pressed
int 16h
cmp ah,11h ;if key pressed is w jump to upboard
je upboard1
cmp ah,01fh ;if key pressed is s jump to downboard
je downboard1
cmp ah,050h
je downboard2
cmp ah,048h
je upboard2
jmp checkskey ;if key isnt pressed jump to check key
upboard1: ;board 1 goes up
push offset line1Y
push offset line1X
call boardup
jmp checkskey
downboard1: ;board 1 goes down
push offset line1Y
push offset line1X
call boarddown
jmp checkskey
downboard2:
push offset line2Y
push offset line2X
call boarddown
jmp checkskey
upboard2:
push offset line2Y
push offset line2X
call boardup
jmp checkskey
exit:
mov ax, 4c00h
int 21h
END start
推荐答案
另一个答案涉及一个多人游戏,其中没有一个玩家持续按下专用键并占用键盘.尽管这种情况是相当合理的,但您可能希望允许玩家长时间按住其键.为此,我们可以用我们自己的处理程序代替BIOS/DOS提供的键盘处理程序.
The other answer deals with a multi-player game where none of the players keep pushing their dedicated keys and thus hogging the keyboard. Although this scenario is quite reasonable, you might want to allow the players to hold their key down for a longer period. To this effect we can substitute the keyboard handler that BIOS/DOS provides by a handler of our own.
键盘上的每个键都关联一个唯一的8位数字,我们称之为扫描代码.
每当按键被按下时,键盘就会在端口60h上提供相关按键的扫描代码.键盘还会产生一个中断09h.此中断的处理程序可以检查扫描代码并以其喜欢的任何方式对其进行处理.这就是下面的演示程序所做的.
当按下一个键时,扫描码是一个字节,其最高位关闭.释放键时,扫描码是一个字节,其最高位打开.其余7位在按下和释放时均保持不变.
With each key on the keyboard is associated a unique 8-bit number we call the scancode.
Whenever a key is pressed the keyboard makes the scancode of the concerned key available at port 60h. The keyboard also generates an interrupt 09h. A handler for this interrupt can examine the scancode and process it in any way it likes. That's what the below demonstration program does.
When a key is pressed the scancode is a byte with its highest bit off. When a key is released the scancode is a byte with its highest bit on. The other 7 bits remain the same for both presses and releases.
应该注意的是,尽管对于您的 pong 游戏而言,它很好,但其中包含的替换处理程序却是一种简约的处理程序.复杂的处理程序还将考虑以E0h或E1h代码为前缀的扩展扫描代码.
It should be noted that, although fine for the purpose of your pong game, the included substitution handler is a minimalistic one. A sophisticated handler would also take into account the extended scancodes that are prefixed with an E0h or E1h code.
该程序还有其他注释,因此您可以轻松了解正在发生的事情.该代码使用FASM语法.该演示可以在实际的DOS环境和DOSBox(0.74)中正常运行.
The program has additional comments so you can easily understand what's happening. The code uses FASM syntax. The demo runs OK in the real DOS environment and in the DOSBox (0.74).
; Multi-player Keyboard Input (c) 2021 Sep Roland
ORG 256 ; Output will be a .COM program
mov ax, 3509h ; DOS.GetInterruptVector
int 21h ; -> ES:BX
push es bx ; (1)
mov dx, Int09
mov ax, 2509h ; DOS.SetInterruptVector
int 21h
mov ax, 0013h ; BIOS.SetVideoMode 320x200 (256 colors)
int 10h
mov ax, 0A000h ; Video buffer
mov es, ax
cld ; So we can use the string primitive STOSB
Cont:
mov si, 160 ; Width
mov di, 100 ; Height
mov al, 0 ; Black
cmp [KeyList+48h], al ; Up
je .a
mov al, 2 ; Green
.a: mov cx, 160 ; X
mov dx, 0 ; Y
call Paint
mov al, 0 ; Black
cmp [KeyList+50h], al ; Down
je .b
mov al, 14 ; Yellow
.b: mov cx, 160 ; X
mov dx, 100 ; Y
call Paint
mov al, 0 ; Black
cmp [KeyList+11h], al ; aZerty / qWerty
je .c
mov al, 4 ; Red
.c: mov cx, 0 ; X
mov dx, 0 ; Y
call Paint
mov al, 0 ; Black
cmp [KeyList+1Fh], al ; S
je .d
mov al, 1 ; Blue
.d: mov cx, 0 ; X
mov dx, 100 ; Y
call Paint
cmp byte [KeyList+1], 0 ; ESC
je Cont
pop dx ds ; (1)
mov ax, 2509h ; DOS.SetInterruptVector
int 21h
mov ax, 4C00h ; DOS.Terminate
int 21h
; --------------------------------------
Int09:
push ax bx
in al, 60h
mov ah, 0
mov bx, ax
and bx, 127 ; 7-bit scancode goes to BX
shl ax, 1 ; 1-bit press/release goes to AH
xor ah, 1 ; -> AH=1 Press, AH=0 Release
mov [cs:KeyList+bx], ah
mov al, 20h ; The non specific EOI (End Of Interrupt)
out 20h, al
pop bx ax
iret
; --------------------------------------
; IN (al,cx,dx,si,di)
Paint:
push cx dx di ; AL=Color CX=X DX=Y SI=Width DI=Height
push ax ; (1)
mov ax, 320 ; BytesPerScanline
mul dx
add ax, cx ; (Y * BPS) + X
mov dx, di
mov di, ax
pop ax ; (1)
.a: mov cx, si
rep stosb
sub di, si
add di, 320
dec dx
jnz .a
pop di dx cx
ret
; --------------------------------------
KeyList db 128 dup 0
KeyList db 128 dup 0
程序的 KeyList 记录键盘上所有键的当前状态.如果字节为0,则说明未按下该键.如果字节为1,则当前正在按下该键.
The program's KeyList records the current state of all of the keys on the keyboard. If a byte is 0, the key is not being pressed. If a byte is 1, that key is currently being pressed.
这篇关于在组装中制作乒乓游戏时,如何一次输入多个按键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!