问题描述
我能够使用汇编语言和使用星星创建一个游戏,当它撞到墙上时会像蛇游戏一样结束,但我想添加另一件事,当星星撞到自己时游戏结束。我有一个解决问题的部分,我想让你帮忙。
gotoxy macro x,y
mov dl,x
mov dh,y
mov bh,0
mov ah,2
int 10h
endm
printchar macro n
mov dl,n
mov ah,2
int 21h
endm
printstring macro n
lea dx,9
int 21h
endm
.model small
.stack 64
.data
x db 40
y db 12
deltax db 0
deltay db -1
msg1 DB "GAME OVER !!!$"
.code
main:
mov ax,@data
mov ds,ax
gotoxy x,y
printchar '*'
mov ah,7
int 21h
l1:
gotoxy x,y
mov al,x
add al,deltax
mov x,al
mov al,y
add al,deltay
mov y,al
gotoxy x,0bh
int 21h
cmp al,0
je l2
mov ah,0
int 16h
cmp al,'w'
je L_W
cmp al,'s'
je L_S
cmp al,'a'
je L_A
cmp al,'d'
je l_D
jmp l2
L_W:
mov deltax,0
mov deltay,-1
jmp L2
L_S:
mov deltax,1
jmp L2
L_A:
mov deltax,-1
mov deltay,0
jmp L2
L_D:
mov deltax,1
mov deltay,0
L2:
cmp y,0
je LEND
cmp y,23
je LEND
cmp x,0
je LEND
cmp x,79
je LEND
jmp l1
LEND:
gotoxy 35,12
printstring msg1
mov ah,7
int 21h
mov ah,4ch
int 21h
end main
解决方法
printchar macro n
mov dl,n
mov ah,2
int 21h
endm
您的 printchar 宏使用 DOS.PrintChar 函数 02h。就您的蛇游戏而言,此 DOS 函数还发出回车/换行符是没有用的,有时可能是有害的。您应该改用 BIOS.WriteCharacter 函数 0Ah。
printchar macro n
mov cx,1
mov bh,0
mov al,0Ah ; BIOS.WriteCharacter
int 10h
endm
与星星相撞
要检测冲突,只需使用 BIOS.ReadCharacterAndAttribute 函数 08h 从视频内存中读取即可。您可以在转到下一个位置 (gotoxy) 和显示另一颗星 (printchar) 之间正确执行此操作。
gotoxy x,y
mov bh,0
mov ah,08h ; BIOS.ReadCharacterAndAttribute
int 10h ; -> AX
cmp ax,0720h ; Is this position unoccupied? (0720h means a WhiteOnBlack space character)
jne LEND ; No
printchar '*'
撞到边界
如果您要绘制矩形 (0,0) - (79,23),您将不必验证超出标签 L2 处的坐标,因为上述碰撞检测也会处理
接下来是绘制白色矩形的快速解决方案:
mov dx,174Fh ; (79,23)
xor cx,cx ; (0,0)
mov bh,77h ; WhiteOnWhite
mov ax,0600h ; BIOS.ClearWindow
int 10h
mov dx,164Eh ; (78,22)
mov cx,0101h ; (1,1)
mov bh,07h ; WhiteOnBlack
mov ax,0600h ; BIOS.ClearWindow
int 10h
最后一个提示
在从用户那里检索密钥时要保持一致。您的程序混合了 DOS 功能 07h 和键盘 BIOS 功能 00h。我建议你一直使用键盘 BIOS 功能。
[编辑]
您已完成代码并进行了更正和更多改进。
请注意,我增加了堆栈的大小。 64 字节有点小,很容易让您遇到某些 BIOS 和/或 DOS 系统调用的麻烦。
gotoxy macro x,y
mov dl,x
mov dh,y
mov bh,0
mov ah,02h ; BIOS.SetCursor
int 10h
endm
printchar macro n
mov cx,0Ah ; BIOS.WriteCharacter
int 10h
endm
printstring macro n
lea dx,09h ; DOS.PrintString
int 21h
endm
.model small
.stack 512
.data
x db 40
y db 12
delta dw 0FF00h ; deltax = 0 deltay = -1
msg1 db "GAME OVER !!!$"
.code
main:
mov ax,@data
mov ds,ax
mov dx,174Fh ; (79,23)
xor cx,cx ; (0,0)
mov bh,77h ; WhiteOnWhite
mov ax,0600h ; BIOS.ClearWindow
int 10h
mov dx,164Eh ; (78,22)
mov cx,0101h ; (1,1)
mov bh,07h ; WhiteOnBlack
mov ax,0600h ; BIOS.ClearWindow
int 10h
gotoxy x,y
printchar '*'
mov ah,00h ; BIOS.GetKey
int 16h ; -> AX
Again:
mov ax,delta
add x,al
add y,ah
gotoxy x,y
mov bh,08h ; BIOS.ReadCharacterAndAttribute
int 10h ; -> AX
cmp ax,0720h ; Is this position unoccupied?
jne Done ; No
printchar '*'
mov ah,01h ; BIOS.TestKey
int 16h ; -> AX ZF
jz Again ; No key available
mov ah,00h ; BIOS.GetKey
int 16h ; -> AX
mov bx,0FF00h ; deltax = 0 deltay = -1
cmp al,'w' ; Up
je SetDelta
mov bx,0100h ; deltax = 0 deltay = 1
cmp al,'s' ; Down
je SetDelta
mov bx,00FFh ; deltax = -1 deltay = 0
cmp al,'a' ; Left
je SetDelta
mov bx,0001h ; deltax = 1 deltay = 0
cmp al,'d' ; Right
jne Again
SetDelta:
mov delta,bx
jmp Again
Done:
gotoxy 35,12
printstring msg1
mov ah,00h ; BIOS.GetKey
int 16h ; -> AX
mov ax,4C00h ; DOS.Terminate
int 21h
end main