Сегодня напишем в текстовом режиме с использованием прерываний BIOS и DOS змейку на Assembler. Для этого нужно знать основы, уметь ассемблировать (Tasm) и компоновать (Tlink) код.
Для начала напишем основу — змейку, которая перемещается в одном направлении по игровому полю. Змейка будет состоять из символа "*", координаты каждого символа хранятся в памяти.

Добавим процедуру «key_press» обработки нажатия клавиши и присваивания значения регистру CX, отвечающему за направление головы.
Управление стрелками.

Вызовем её сразу после вызова процедуры delay:
Накормим змейку, создаём процедуру «add_food». Эта процедура будет на игровом поле размещать еду, символы "$". В качестве случайных чисел будем брать время.
Вызовем 1 раз в начале.
Делаем проверку, съела змея еду или нет. Если съела, вызываем процедуру «add_food» и не удаляем хвост.
Проверку добавляем в код перед выводом символа головы:
Усложним игру. После того, как питон съест 5 символов, в хвосте будет появляться символ "@". Пишем счетчик и вывод символа:

Какая игра без Game Over. Пишем процедуру проверки границы поля, а также врезание в себя и символ "@".
Вызываем её после считывания символа:
Немного магии добавляем после инкремента индексов.
Ну вот и всё, также можно добавить меню с выбором уровня, паузу, заставку Game Over, счет очков.
По ссылке архив с исходным кодом, exe'шником и DosBox для тех, у кого не запустится.
С прошедшим днём программиста!
Для начала напишем основу — змейку, которая перемещается в одном направлении по игровому полю. Змейка будет состоять из символа "*", координаты каждого символа хранятся в памяти.

Посмотреть код
model small .data ;Сегмент данных. Храним координаты тела змейки snake dw 0000h dw 0001h dw 0002h dw 0003h dw 0004h dw 7CCh dup('?') .stack 100h .code ;В начале сегмента кода будем размещать процедуры delay proc push cx mov ah,0 int 1Ah add dx,3 mov bx,dx repeat: int 1Ah cmp dx,bx jl repeat pop cx ret delay endp start: mov ax,@data mov ds,ax mov es,ax mov ax,0003h int 10h ;Очищаем игровое поле mov cx,5 mov ax,0A2Ah int 10h ;Выводим змейку из 5 символов "*" mov si,8 ;Индекс координаты символа головы xor di,di ;Индекс координаты символа хвоста mov cx,0001h ;Регистр cx используем для управления головой. При сложении от значения cx будет изменяться координата x или y main: ;Основной цикл call delay xor bh,bh mov ax,[snake+si] ;Берем координату головы из памяти add ax,cx ;Изменяем координату x inc si inc si mov [snake+si],ax ;Заносим в память новую координату головы змеи mov dx,ax mov ax,0200h int 10h ;Вызываем прерывание. Перемещаем курсор mov ah,02h mov dl,002Ah int 21h ;Прерывание выводит символ '*' mov ax,0200h mov dx,[snake+di] int 10h mov ax,0200h mov dl,0020h int 21h ;Выводим пробел, тем самым удаляя хвост inc di inc di jmp main end start
Добавим процедуру «key_press» обработки нажатия клавиши и присваивания значения регистру CX, отвечающему за направление головы.
Управление стрелками.

key_press
key_press proc mov ax, 0100h int 16h jz en ;Без нажатия выходим xor ah, ah int 16h cmp ah, 50h jne up cmp cx,0FF00h ;Сравниваем чтобы не пойти на себя je en mov cx,0100h jmp en up: cmp ah,48h jne left cmp cx,0100h je en mov cx,0FF00h jmp en left: cmp ah,4Bh jne right cmp cx,0001h je en mov cx,0FFFFh jmp en right: cmp cx,0FFFFh je en mov cx,0001h en: ret key_press endp
Вызовем её сразу после вызова процедуры delay:
main: call delay call key_press
Накормим змейку, создаём процедуру «add_food». Эта процедура будет на игровом поле размещать еду, символы "$". В качестве случайных чисел будем брать время.
add_food
add_food proc sc: inc bl ;В регистре BL рандомное число cmp bx,50h ;Проверяем границу числа jng ex shr bl,1 ;Если больше, делим на 2 логическим сдвигом jmp sc ex: mov dl,bl ;Запись координаты sc2: cmp bx,19h jng ex2 shr bl,2 jmp sc2 ex2: mov dh,bl ;Запись координаты mov ax,0200h int 10h mov ax,0800h int 10h cmp al,2Ah ;Проверяем пустое ли место je sc cmp al,40h je sc ;Если нет повторяем mov ax,0200h mov dl,0024h int 21h ret add_food endp
Вызовем 1 раз в начале.
mov bl,51h call add_food main:
Делаем проверку, съела змея еду или нет. Если съела, вызываем процедуру «add_food» и не удаляем хвост.
Проверку добавляем в код перед выводом символа головы:
mov ah,02h int 10h ;Вызываем прерывание. Перемещаем курсор mov ax,0800h int 10h ;Читает символ mov dh,al mov ah,02h mov dl,002Ah int 21h ;Прерывание выводит символ '*' cmp dh,24h jne next call add_food jmp main next:
Усложним игру. После того, как питон съест 5 символов, в хвосте будет появляться символ "@". Пишем счетчик и вывод символа:

shit
;В сегмент данных добавим строчку .data tick dw 0 ;Счетчик -------------------------------------------------------------------- cmp dh,24h jne next push cx ;В стек регистр mov cx,[tick] inc cx cmp cx,5 jne exl xor cx,cx mov ax,0200h mov dx,[snake+di-2] int 10h mov ax,0200h mov dl,0040h int 21h exl:mov [tick],cx pop cx call add_food jmp main next:
Какая игра без Game Over. Пишем процедуру проверки границы поля, а также врезание в себя и символ "@".
game_over
game_over proc ;Проверяем границы cmp dl,50h je exit cmp dl,0 jl exit cmp dh,0 jl exit cmp dh,19h je exit ;Проверяем символы cmp al,2Ah je exit cmp al,40h je exit jmp good exit: mov ax,4c00h int 21h good: ret game_over endp
Вызываем её после считывания символа:
mov ax,0800h int 10h ;Считываем символ call game_over mov dh,al
Немного магии добавляем после инкремента индексов.
magic
inc si inc si cmp si,7CAh jne nex xor si,si nex: --------------------------------------------------------------------- inc di inc di cmp di,7CCh jne main xor di,di
Ну вот и всё, также можно добавить меню с выбором уровня, паузу, заставку Game Over, счет очков.
По ссылке архив с исходным кодом, exe'шником и DosBox для тех, у кого не запустится.
С прошедшим днём программиста!
