Как мне переместить графический объект через доску в 8086 TASM? - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь переместить объект 6x6 пикселей в сборке 8086, но безуспешно. Я бы хотел, чтобы он перемещался на 4 пикселя в секунду, но в настоящее время он вообще не движется.

Я был бы очень рад, если бы кто-нибудь мог мне помочь, потому что это серьезный проект для моих выпускных экзаменов по информатике в средней школе, и я получил до конца выходных

Вот сам код

    IDEAL
    MODEL medium

        DATASEG

    STACK 100h

    segment extra para public use16 ;Create Extra Segment that is 16 bits;
      ;(Removed the data segment for your sake, its very long pixel lists)

    CODESEG 

    ; -------------------------------
    ; change screen mode to text mode
    ; -------------------------------

    proc DrawPix
    ContLines:
        mov  cx, [LineLength]     ; How many times should the "rep movsb" should iterate
        push di         ; Save in stack the calculated position indicating the begining of the current line

        rep  movsb      ; copies bytes from si(image) to di (screen)

        pop  di         ; di was changed during the movesb. I change it back to pint to the begin of the line
        add  di, ScreenWidth ; by adding ScreenWidth (320)' I am moving the di to point to the next line
        dec  [NumOfLines]   ; Check if I wrote all the lines of the image
        jnz  ContLines    ; IF there are still pixcells to print on the screen(image not ended), loop to next line
        ret
        endp



    proc keycontrol
;check for arrow keys, and go to check arrow removed;
            jmp Shoot
    checkarrow:
        removed, irrelevant (supposed to change direction of turret)
    Exit:
    ret

    endp

    proc Shoot
    cmp [turretstate],1 ;turret facing up
    je bulletup
    cmp [turretstate],2;turret facing down
    je bulletdown
    cmp [turretstate],3;turret facing left
    je bulletleft
    cmp [turretstate],4;turret facing right
    je bulletright
    ret

    bulletup:
      not relevant for testing left movement
    bulletdown:
       not relevant for testing left movement
    bulletright:
    not relevant for testing left movement
    bulletleft:
        mov di,320*87+133
       lea si, [bullet]
       mov [LineLength],6
       mov [numOFLines],6
       call DrawPix
       ret
       endp

       proc leftbull
       pop dx
       dec dx
       mov di,320*84
       add di,dx
       lea si, [bullet]
       mov [LineLength],6
       mov [NumOfLines],6
       call DrawPix
       ret
       endp

       proc progbullets
       mov dx,0
       checkleft:
       inc dx
       cmp dx,136
       je exit1
       mov cx,87
       mov ah,0Dh
       int 10h
       cmp al,4
       jne checkleft
       push dx
       call leftbull
       exit1:
       ret
       endp
    ;---------------------------------------------;
    ;---------------------------------------------;
    start:


        Main_Loop:
        mov [sectimer], 0
        mov ah,00H
        int 1Ah
        mov [sectimer],dx
        call keycontrol
        func_Loop:
        call progbullets
        mov ah,00H
        int 1Ah
        sub dx,18
        cmp dx,[sectimer]
        jge Main_Loop
        ;call moveGame
        jmp func_Loop
        ; call the operating system to terminate this program

        mov ah,1
        int 21h
        mov ax, 4C00H
        int 21h  


    ends
    end start

Программа имеет стартовый экран, может перемещать турель и размещать «пули», но я не смог заставить их двигаться, и там и там есть несколько странных пикселей. Процесс съемки является главной задачей, он должен идти один за другим по значению x (пуля остается на том же значении y), и проверять, является ли пиксель красным (цвет маркера), и, если это так, перемещаться это один слева.

РЕДАКТИРОВАТЬ: Большое спасибо за помощь, я новичок здесь, и мне это действительно нужно. У меня нет подходящего отладчика для GUI TASM, который я использую, поэтому я не могу это сделать Я удалил большинство ненужных вещей, но не был уверен, что еще не нужно, так как я не уверен, что не работает. Я думаю, что "стрелять" Proc является наиболее актуальным. Стрельба работает только для левой пули, потому что я сначала хотел ее проверить, но для этого она тоже не работала

1 Ответ

0 голосов
/ 16 мая 2018

Одна из основных проблем в сокращенном коде:

   push dx
   call leftbull

...

   proc leftbull
   pop dx
   dec dx

Вы пропустили детали реализации инструкций call и ret. Они также используют область памяти «стек», поэтому pop dx не читает значение, сохраненное в стеке push dx до call, а «адрес возврата», то есть адрес следующей инструкции после call инструкция.

Вы можете исправить подобные проблемы, используя собственное соглашение о вызовах для своих подпрограмм, где вы будете передавать аргументы в регистрах, как в этом случае просто удалите push dx и pop dx, потому что у вас уже есть желаемое значение в dx (но убедитесь, что вы вызывали leftbull также из другого места, чтобы исправить этот вызов, чтобы поместить аргумент также в dx).


Другое дело, что это немного наивный и грубый подход к поиску пиксельных данных для существующего маркера. Вместо этого зарезервируйте некоторое место в сегменте данных для позиций маркеров (в зависимости от того, сколько маркеров вы можете иметь на экране одновременно), и продолжайте обновлять эти позиции, чтобы вам не приходилось искать текущую позицию в пиксельных данных.

Кроме того, в более сложных играх некоторые спрайты могут отображаться друг на друга, поэтому поиск пиксельных данных в таком случае завершится неудачей, так как спрайт "под" не будет виден = не найден. Но также чтение видеопамяти происходит очень медленно, поэтому сканирование через 320 пикселей нигде не происходит так быстро, как сканирование через 320 байтов в сегменте данных. А считывание значения пикселей службой int 10h обычно в десять раз медленнее, чем чтение их непосредственно из видеопамяти, поэтому ваша текущая идея примерно в 200-1000 раз медленнее, чем наличие «переменных» положения маркера и обновление маркеров через них.

Пересмотрите всю игровую схему и алгоритм основного цикла, возможно, попробуйте на некоторое время нарисовать на бумаге то, что вам действительно нужно сохранить, чтобы сохранить полное «состояние мира», чтобы вы могли перерисовывать мир с нуля каждый frame (в некотором роде следуя современной схеме архитектуры MVC SW), а также различные варианты кода вверх / вниз / влево / вправо ... попробуйте параметризовать это, чтобы вы могли иметь единую универсальную подпрограмму, обрабатывающую все случаи, выполняя различные действия на основе параметр конкретной пули.

Однажды я сделал DOS-игру длиной 2048 байт для одного соревнования по коду, поэтому код не совсем читаемый, но вы все же можете взглянуть на него поближе, может быть, он воодушевит вас в одном или двух вещах (источник включены, и я использовал TASM тогда): http://www.pouet.net/prod.php?which=2692

...