Невозможно удерживать квадрат на полную площадь при его перемещении - PullRequest
2 голосов
/ 08 апреля 2019

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

Мой код: в Assembly Tasm

STA SEGMENT STACK
DB 0FFFeH DUP(?)
STA ENDS
DATA SEGMENT
;-----------
;VARIABLES HERE
xpos dw 50h
ypos dw 50h
color db 9h
constat equ 0ffffh
siNum dw ?
diNum dw ?
numOFtime dw 0h

;-------------
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STA

START :
MOV AX,DATA
MOV DS,AX
;start coding here:

mov ah, 0   ;Set display mode
mov al, 13h ;13h = 320x200, 256 colors
int  10H   ;Video BIOS Services
mov cx,50h
mov dx,50h
mov si,25H
mov di,25H

PrintSquare:
;------------------------------------------------------------------------
;cx = xpos , dx = ypos, si = x-length, di = y-length, al = color

didi:
mov color,9h
mov bp,0h
do:
add cx,si
here:
mov bh,0h
mov al,color
mov ah, 0Ch   ;write pixel at coordinate
int 10h      ;draw pixel!
dec cx
cmp cx,xpos
ja here
inc dx
inc bp
cmp bp,25h
jbe do
call drawBlackBox
inc numOFtime
inc xpos;incrising to make the sqaure moving horizontically
mov cx,xpos;cx gets the xposition
mov dx,ypos
cmp numOFtime,constat
jb didi






mov ah,004Ch  ;terminate program
int 21h
;
drawBlackBox proc
mov color,0h ;black color 
mov bp,0h
mov cx,xpos
mov dx,ypos
do1:
add cx,si
here1:
mov bh,0h
mov al,color
mov ah, 0Ch   ;write pixel at coordinate
int 10h      ;draw pixel!
dec cx
cmp cx,xpos
ja here1
inc dx
inc bp
cmp bp,25h
jbe do1
mov cx,xpos
ret

drawBlackBox endp


CODE ENDS
END START

1 Ответ

1 голос
/ 09 апреля 2019

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

Может помочь иллюстрация.Допустим, вы пытаетесь перейти с левого изображения на правое:

~   ~             ^   ^
O   O             O   O
  ^      ---->      ^
|---|             \___/

Если изображение обновляется слева направо и данные отправляются на экран в середине процесса обновления, вы увидитечто-то вроде:

^   ~
O   O
  ^
\_--|

Это то, что называется разрывом.

Чтобы решить эту проблему, вы можете построить следующий кадр в отдельном блоке памяти (вы можете использоватьrep stosb для создания следующего кадра за минимальное время), затем используйте rep movsb, или что-то такое же быстрое, чтобы передать это в видеопамять.Это немного замедлит вашу частоту кадров, но должно смягчить любые разрывы, которые вы можете видеть.


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

stacksg segment stack
    db 0fffeh dup(?)
stacksg ends

datasg segment
    buffer dw 32000 dup(0)
datasg ends

codesg segment
assume cs:codesg, es: datasg, ds:datasg, ss:stacksg

doline: ; ax = line, bx = column, cx = width
    push        di            ; preserve
    push        ax
    push        dx            ; imul hits this

    push        bx            ; get byte offset to di
    mov         bx, 320
    imul        bx
    pop         bx
    add         ax, bx
    mov         di, ax

    push        cx            ; blat line
    mov         al, 9    
    cld
    rep stosb
    pop         cx

    pop         dx            ; restore and return
    pop         ax
    pop         di
    ret

dosquare: ; ax = line, bx = column, cx = width, dx = height
    push        ax            ; preserve
    push        bx
    push        cx
    push        dx

    push        di            ; clear buffer to black
    push        ax
    push        cx
    xor         di, di
    xor         ax, ax
    mov         cx, 32000
    cld
    rep stosw
    pop         cx
    pop         ax
    pop         di

makeline:
    call        doline
    inc         ax
    dec         dx
    jnz         makeline

    push        es            ; blat double buffer to screen
    push        si
    push        di
    xor         si, si
    mov         ax, 0a000h
    mov         es, ax
    xor         di, di
    mov         cx, 32000
    cld
    rep movsw    
    pop         di
    pop         si
    pop         es

    pop         dx            ; restore and return
    pop         cx
    pop         bx
    pop         ax
    ret

start:
    mov         ax, datasg
    mov         ds, ax
    mov         es, ax

    mov         ah, 0         ; set display mode 13h, 320x200, 8bbp
    mov         al, 13h
    int         10h

    mov         ax, 10        ; line
    mov         bx, 10        ; start column
    mov         cx, 40        ; width
    mov         dx, 40        ; height

printSquare:
    call        dosquare      ; do the square
    inc         bx            ; move right but reset at end
    cmp         bx, 310 - 40
    jne         printSquare
    mov         bx, 10
    jmp         printSquare

codesg ends
end start

Подключите это к GNU Turbo Assembler и проверьте его.Я запустил и ваш исходный (разрывающий) код, и этот вариант, и последний был более плавной анимацией.

...