I was able to create a game with assembly language and using the star, which ends like a snake game when it hits the wall, but I want to add another thing to it and that the game ends when the star hits itself. And I have a problem solving part, I wanted you to help.
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,n
mov ah,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,y
printchar '*'
mov ah,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,0
mov deltay,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
Your printchar macro uses the DOS.PrintChar function 02h. For the purpose of your snake game, it's not useful and could sometimes be harmful that this DOS function also emits a carriage return / linefeed. You should use the BIOS.WriteCharacter function 0Ah instead.
printchar macro n
mov cx, 1
mov bh, 0
mov al, n
mov ah, 0Ah ; BIOS.WriteCharacter
int 10h
endm
To detect a collision all it takes is reading from the video memory using BIOS.ReadCharacterAndAttribute function 08h. You do this right between going to the next position (gotoxy) and displaying another star (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 '*'
If you would draw the rectangle (0,0) - (79,23), you would not have to verify exceeding the coordinates at label L2 because the above collision detection would also take care of that.
Next is a quick solution to draw a white rectangle:
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
Be consistent about retrieving a key from the user. Your program mixes the DOS function 07h and the Keyboard BIOS function 00h. I would suggest you use the Keyboard BIOS function all the time.
[edit]
Your completed code with corrections and even more improvements.
Please note that I have increased the size for the stack. 64 bytes is a bit small and can easily get you into trouble with certain BIOS and/or DOS system calls.
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, 1
mov bh, 0
mov al, n
mov ah, 0Ah ; BIOS.WriteCharacter
int 10h
endm
printstring macro n
lea dx, n
mov ah, 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, 0
mov ah, 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