
Новичок
Профиль
Группа: Участник
Сообщений: 19
Регистрация: 14.11.2006
Репутация: 1 Всего: 1
|
Всем привет! Изрядно я намучился с ассемблером... И пока мучался обещал себе, что не поленюсь и выложу игру на форум, дабы помоч тем кто попадет в такую же ситуацию как и я! Сразу скажу, что мне так же помогали. В том числе и на этом форуме! Более конкретно - anwe... Anwe спасибо Так же помогал еще человек, но я не знаю кто  (через знакомых). Может быть он тоже посещает этот форум и поймет, что я о нем... спасибо Описание самой игры в исходнике, довольно много коментариев... более подробные писать нет времени - сессия! Всё... надеюсь кому-нибудь поможет Код | ; Программа рисует квадратик в текстовом режиме им можно управлять стрелками или с дополнительной ; клавиатуры. Нажатие на клавишу определяет направление движения, после чего он движется до стенки ; и там остановится или до нажатия любой клавиши (не со стрелками). При столкновении с врагом конец. ; Количество врагов от 1 до 8 определяется значением в cm. Враги двигаются в произвольном направлении ; с разными векторами скоростей по осям x и y. После столкновения со стенкой или друг другом направление ; движения с которого произошло столкновение меняется на противоположное (лево - право) (верх - низ) ; и время задержки движения по этому направлению задаётся случайным образом (от 1 до 4). ; Конец определяется при столкновении врага с игроком.
DOSSEG .MODEL TINY .STACK 100h .DATA plx dw 40 ; координаты игрока ply dw 13 plxt dw 40 ; координаты игрока временные plyt dw 13 px dw 0 ; направление перемещения 1 влево 2 вправо py dw 0 ; направление перемещения 1 вверх 2 вниз mx dw 28,56,40,24,34,46,46,34 ; координаты врагов x my dw 13,13,17,13,07,07,19,13 ; y mmx dw 8 dup(0) ; направление перемещения 0 влево 1 вправо mmy dw 8 dup(0) ; направление перемещения 0 вверх 1 вниз mdx dw 8 dup(0) ; задержка перемещения врага по x 1-4 ;действует до столкновения mdy dw 8 dup(0) ; задержка перемещения врага по y 1-4 ;после чего обновляется mdtx dw 8 dup(0) ; текущая задержка перемещения врага по x mdty dw 8 dup(0) ; текущая задержка перемещения врага по y plc db 7fh,33h,11h,00h ; значения цветов для игрока, врагов, рамки, фона cm dw 8 ; Количество врагов 1-8 seed dw 0 ; переменная для подпрограммы RND dead dw 0 ; признак конца (1 - конец) dtm dd 0 ; переменная для подпрограммы задержки delym
.CODE .386 ; Начало программы start: mov ax,@data ;инициализация сегмента данных @data - содержит сагмент mov ds,ax ;где расположены данные определённые в .DATA
; инициализация генератора RND ; путём чтения значения части значения системного времени по адресу 0040h:006ch push 0040h pop es mov bx,es:[006ch] mov [seed],bx
; установка начальных значений для врагов mov cx,[cm] ; загрузка количества врагов для инициализации цикла mov si,0 ; установка указателя данных врагов на первого (нулевого) ; цикл инициализации переменных для врагов linit: mov ax,1 ; маска для направления движения (возможно только 2 значения 1 и 0) call rnd ; вызов функции возвращающей случайное число в нужном диапазоне mov mmx[si],bx ; сохранение полученного значения (вернулось в bx) в памяти mov ax,1 ; тоже для координаты y call rnd ; mov mmy[si],bx ; mov ax,3 ; установка задержки для перемещения по осям x и y call rnd ; add bl,1 ; mov mdx[si],bx ; заносится в 2 переменные 1 - для хранения mov mdtx[si],bx ; 2 - для временного использования (уменьшается до 0) mov ax,3 ; при достижении 0 происходит ход и временное значение обновляется call rnd ; до исходного add bl,1 ; mov mdy[si],bx ; mov mdty[si],bx ; inc si inc si loop linit ; инициализация экрана ; установка видеорежима 80х25 mov al,3 mov ah,0 int 10 ; выбор активной страницы mov ah,05 mov al,0 int 10 ; установка регистра сегмента дополнительных данных на сегмент видеопамяти ; сохранение в стеке начала видеопамяти push 0b800h ; востановление в es этого значения pop es
; рисование фона на экран ; чем (код пробела) mov al,20h ; каким цветом mov ah,plc[3] ; сколько позиций закрасить mov cx,80*25 ; с какой позиции рисовать mov di,0 ; сброс флага направления в 0 означает, что ; значение di будет увеличиваться командой stosw cld ; заполнение области памяти значением в ax ; rep вызывает повторение stosw, пока cx не станет равно 0, ; и уменьшает его каждый раз на 1 ; mov es:[di],ax rep stosw
; символ mov al,20h ; цвет mov ah,plc[2] ; верх mov cx,80 ; заносим сколько раз повторить push 0 ; смещение с которого будет заполнение 0 (с начала видеопамяти) pop di ; rep stosw ; помещаем содержимое ax в ячейку памяти по адресу es:di ; rep вызывает уменьшение cx на 1 и если cx не 0 повторяет команду ;бока mov cx,24 ; в cx заносим количество боковин push 156 ; в di заносим откуда рисуем pop di ; в цикле рисуем сразу правую и левую стенки ; каждая стенка состоит из 2 символов ; т.к. видеопамять линейна, то с крайнего правого места ; переходим к крайнему левому на ряд ниже l1: mov es:[di],ax inc di inc di mov es:[di],ax inc di inc di mov es:[di],ax inc di inc di mov es:[di],ax add di, 154 loop l1 ; низ mov cx,80 mov di,3840 cld rep stosw
; отрисовка врагов ; количество mov cx,[cm] mov si,0 ; инициализация указателя на переменные врагов, начинаем с первого (0) linim: call mdraw ; вызов подпрограммы рисования врага inc si ; переход к следующему врагу inc si ; si увеличиваем 2 раза, т.к значения на которые он указывает 2 байтовые loop linim ; пока cx не обнулиться, перебираются все враги
lmain: ; основной цикл программы ; проверка на конец call delym ; задержка на 1 такт таймера call movep mov ax,1 ; занесение признака конца в ax cmp ax,[dead] ; сравнение со значением в памяти je exit ; переход на метку выхода в случае конца mov cx,[cm] ; подготовка к циклу перебора врагов mov si,0 ; инициализация номера врага lwaitm: ; цикл уменьшения задержек для монстров dec mdtx[si] ; уменьшение задержки для врага по оси x jnz lm0 ; если задержка не равна нулю перейти к изменению задержки по оси y call movemx ; задержка равна нулю - вызов подпрограммы перемещения врага по оси x mov ax,1 ; занесение признака конца в ax cmp ax,[dead] ; сравнение со значением в памяти je exit ; переход на метку выхода в случае конца lm0: dec mdty[si] ; уменьшение задержки для врага по оси y jnz lm1 ; переход к проверке конца игры если задержка не равна 0 call movemy ; задержка равна нулю - вызов подпрограммы перемещения врага по оси y lm1: mov ax,1 ; занесение признака конца в ax cmp ax,[dead] ; сравнение со значением в памяти je exit ; переход на метку выхода в случае конца ; перемещение указателя на данные второго врага inc si inc si loop lwaitm ; повторять, пока не переместили всех врагов jmp lmain ; переход к началу главного цикла
; выход exit: ; отрисовка игрока красным цветом mov ax,[ply] mov bx,160 mul bx mov bx,[plx] shl bx,1 add ax,bx mov di,ax mov al,20h mov ah,44h mov es:[di],ax inc di inc di mov es:[di],ax
; ожидание нажатия клавиши exit1: mov ah,01 int 16h jz exit1 ; выполняется пока не нажата кнопка mov ah,4ch ;DOS terminate program function # int 21h ;terminate the program
; ; подпрограмма хода игрока ; стирает с текущего местоположения ; опрашивает нажитие клавиш ; movep proc near push ax push bx push dx push di push si
; стирание с предыдущей позиции mov ax,[ply] mov bx,160 mul bx mov bx,[plx] shl bx,1 add ax,bx mov di,ax mov al,20h mov ah,plc[3] mov es:[di],ax inc di inc di mov es:[di],ax mov ah,01 int 16h jz lendmp xor ax,ax mov [px],ax mov [py],ax int 16h cmp ah,48h jz lmpup cmp ah,50h jz lmpdwn cmp ah,4bh jz lmplft cmp ah,4dh jz lmprgt cmp ah,47h jz lmplu cmp ah,49h jz lmpru cmp ah,4fh jz lmpld cmp ah,51h jz lmprd cmp ah,01 jnz lstop mov ax,1 mov [dead],ax jmp lexitmp lmpup: mov [py],1 jmp lendmp lmpdwn: mov [py],2 jmp lendmp lmplft: mov [px],1 jmp lendmp lmprgt: mov [px],2 jmp lendmp lmplu: mov [py],1 mov [px],1 jmp lendmp lmpru: mov [py],1 mov [px],2 jmp lendmp lmpld: mov [py],2 mov [px],1 jmp lendmp lmprd: mov [py],2 mov [px],2 jmp lendmp lstop: mov [py],0 mov [px],0 jmp lendmp lendmp: ; сохранение старой позиции mov ax,[plx] mov [plxt],ax mov ax,[ply] mov [plyt],ax ; проверка перемещения cmp [py],1 jnz lmp01 dec [ply] lmp01: cmp [py],2 jnz lmp02 inc [ply] lmp02: cmp [px],1 jnz lmp03 dec [plx] lmp03: cmp [px],2 jnz lmp04 inc [plx] lmp04: ; проверка что на новой позиции ; сперва для первого символа квадрата ; вычисление области в видеопамяти памяти ; куда делается перемещение mov ax,[ply] mov bx,160 mul bx mov bx,[plx] shl bx,1 add ax,bx mov di,ax ; запись в ax атрибута, в этом месте mov ax,es:[di] ; сравнение полученного значения с атрибутом ; которым рисуется пустое место cmp ah,plc[3] ; если совпадает (можно перемещатся) переход к проверке ; перемещения для второго символа квадрата jz lmp05 ; если предыдущая проверка несовпала ; сравним со значением отвечающим за цвет стенки cmp ah,plc[2] ; переход к восстановлению старых координат, если ; перемещаемся в стенку jz lmp06 ; проверка на перемещение на врага cmp ah,plc[1] ; если несовпало с врагом (такое в общем случае невозможно ; т.к. вся видеопамять заполнена в данный момент только 3 атрибутами ; используется для отладки) переход к отрисовке. jnz lpldr ; в противном случае (столкновение с врагом), установим признак завершения mov [dead],1 ; переход к рисованию jmp lpldr
lmp05: inc di inc di mov ax,es:[di] cmp ah,plc[3] jz lpldr cmp ah,plc[2] jz lmp06 cmp ah,plc[1] jnz lpldr mov [dead],1 jmp lpldr
lmp06: mov ax,[plxt] mov [plx],ax mov ax,[plyt] mov [ply],ax lpldr: ; отрисовка игрока mov ax,[ply] mov bx,160 mul bx mov bx,[plx] shl bx,1 add ax,bx mov di,ax mov al,20h mov ah,plc[0] mov es:[di],ax inc di inc di mov es:[di],ax
lexitmp: pop si pop di pop dx pop bx pop ax ret movep endp
; подпрограмма рисования врага ; в si номер врага ; рисует врага по его координатам mdraw proc near ; сохранение регистров push ax push bx push cx push dx push si push di ; рисование на новом месте ; вычисление адреса в видеопамяти по экранным координатам ; занесение строки в ax mov ax,my[si] ; занесение числа байтов в bx mov bx,160 ; умножение ax на bx и получение адреса начала нужной строки в видеопамяти mul bx ; загрузка в bx колонки mov bx,mx[si] ; умножение bx на 2 (т.к. знакоместо в памяти занимает 2 байта) shl bx,1 ; сложение ax и bx, получение в результате окончательного адреса в ax add ax,bx ; занесение значения ax в di (для удобства индексации) mov di,ax ; в al заносим символ, которым рисуем (пробел) mov al,20h ; в ah заносим цвет mov ah,plc[1] ; собственно занесение в адрес видиопамяти символа и атрибута (рисование врага) mov es:[di],ax ; переход ко второй клетке врага (2 байта) inc di inc di ; рисование второй клетки mov es:[di],ax
; востановление регистров pop di pop si pop dx pop cx pop bx pop ax ret mdraw endp
; подпрограмма перемещения текущего врага по оси x ; в si указатель на переменные врага movemx proc near ;сохранение регистров push ax push bx push cx push dx push si push di
; стирание врага со старого места mov ax,my[si] mov bx,160 mul bx mov bx,mx[si] shl bx,1 add ax,bx mov di,ax mov al,20h mov ah,00h mov es:[di],ax inc di inc di mov es:[di],ax
; изменение координаты по х, в зависимости от направления движения ; загрузка в ax направления движения mov ax,mmx[si] ; сохраним старое значение координаты x в cx, вдруг туда ходить нельзя mov cx,mx[si] ; проверка ax на 0 cmp ax,00 ; переход если ax=0 на movemxl (движение влево) jz movemxl ; отработка движения вправо, проверка не делается, т.к. варианта всего 2 ; увеличим значение координаты x текущего врага inc word ptr mx[si] jmp movemxc movemxl: ; увеличим значение координаты x текущего врага (перемещение влево) dec word ptr mx[si] movemxc: ; проверка что находится на новом месте, куда переместился враг ; определение что находится на новом месте mov ax,my[si] mov bx,160 mul bx mov bx,mx[si] shl bx,1 add ax,bx mov di,ax mov ax,es:[di] ; проверка на пустое место cmp ah,plc[3] ; переход к проверки 2 клетки jz lmmx1 ; проверка на стенку cmp ah,plc[2] ; переход на обработку столкновения с препятствием jz lmmx2 ; проверка на другого врага cmp ah,plc[1] ; переход на обработку столкновения с препятствием jz lmmx2 ; проверка на столкновение с игроком cmp ah,plc[0] ; если и не игрок, значит просто глюк, перейти к выходу jnz lexitmovemx mov [dead],1 jmp lmmx3 lmmx1: inc di inc di mov ax,es:[di] ; проверка на пустое место cmp ah,plc[3] ; переход к перемещению если на новом месте пусто jz lmmx3 ; проверка на стенку cmp ah,plc[2] ; переход на обработку столкновения с препятствием jz lmmx2 ; проверка на другого врага cmp ah,plc[1] ; переход на обработку столкновения с препятствием jz lmmx2 ; проверка на столкновение с игроком cmp ah,plc[0] ; если и не игрок, значит просто глюк, перейти к выходу jnz lexitmovemx mov [dead],1 jmp lmmx3
lmmx2: mov mx[si],cx ; востановим старую координату x xor word ptr mmx[si],1 ; изменение направления движения mov ax,1 ; call rnd ; изменение задержки движения add bx,1 mov mdx[si],bx ; lmmx3:
call mdraw lexitmovemx: ; установка текущей задержки mov ax,mdx[si] mov mdtx[si],ax ; восстановление регистров pop di pop si pop dx pop cx pop bx pop ax ret movemx endp
; подпрограмма перемещения текущего врага по оси y ; в si указатель на переменные врага movemy proc near ;сохранение регистров push ax push bx push cx push dx push si
; стирание врага со старого места mov ax,my[si] mov bx,160 mul bx mov bx,mx[si] shl bx,1 add ax,bx mov di,ax mov al,20h mov ah,00h mov es:[di],ax inc di inc di mov es:[di],ax
; изменение координаты по y, в зависимости от направления движения ; загрузка в al направления движения mov ax,mmy[si] ; сохраним старое значение координаты y в cx, вдруг туда ходить нельзя mov cx,my[si] ; проверка ax на 0 cmp ax,00 ; переход если ax=0 на movemxl (движение влево) jz movemyl ; отработка движения вправо, проверка не делается, т.к. варианта всего 2 ; увеличим значение координаты y текущего врага inc word ptr my[si] jmp movemyc movemyl: ; увеличим значение координаты y текущего врага (перемещение влево) dec word ptr my[si] movemyc: ; проверка что находится на новом месте, куда переместился враг ; определение что находится на новом месте mov ax,my[si] mov bx,160 mul bx mov bx,mx[si] shl bx,1 add ax,bx mov di,ax mov ax,es:[di] ; проверка на пустое место cmp ah,plc[3] ; переход к проверке второй клетки jz lmmy1 ; проверка на стенку cmp ah,plc[2] ; переход на обработку столкновения с препятствием jz lmmy2 ; проверка на другого врага cmp ah,plc[1] ; переход на обработку столкновения с препятствием jz lmmy2 ; проверка на столкновение с игроком cmp ah,plc[0] ; если и не игрок, значит просто глюк, перейти к выходу jnz lexitmovemy mov [dead],1 jmp lmmy3 lmmy1: inc di inc di mov ax,es:[di] ; проверка на пустое место cmp ah,plc[3] ; переход к перемещению если на новом месте пусто jz lmmy3 ; проверка на стенку cmp ah,plc[2] ; переход на обработку столкновения с препятствием jz lmmy2 ; проверка на другого врага cmp ah,plc[1] ; переход на обработку столкновения с препятствием jz lmmy2 ; проверка на столкновение с игроком cmp ah,plc[0] ; если и не игрок, значит просто глюк, перейти к выходу jnz lexitmovemy mov [dead],1 jmp lmmy3 lmmy2: mov my[si],cx ; востановим старую координату y xor word ptr mmy[si],1 ; изменение направления движения mov ax,1 ; call rnd ; изменение задержки движения add bx,1 ; mov mdy[si],bx ; lmmy3:
call mdraw lexitmovemy: ; установка текущей задержки mov ax,mdy[si] mov mdty[si],ax ; восстановление регистров pop si pop dx pop cx pop bx pop ax ret movemy endp
delym proc near push eax push edx push ecx push ebx mov ax,0 int 1ah mov word ptr dtm[0],dx mov word ptr dtm[2],cx mov ebx,[dtm] ldl: mov ax,0 int 1ah mov word ptr dtm[0],dx mov word ptr dtm[2],cx mov eax,[dtm] sub eax,ebx cmp eax,01h jl ldl pop ebx pop ecx pop edx pop eax ret delym endp
; случайное число в ax маска rnd proc near push dx push si push di
push ax pop dx push bx push cx mov ax,seed mov cx,8 newbit: mov bx,ax and bx,002Dh xor bh,bl clc jpe shift stc shift: rcr ax,1 loop newbit mov seed,ax pop cx pop bx and ax,dx mov bx,ax
pop di pop si pop dx ret rnd endp END
|
|