Если, не двигаясь хорошо, вы имеете в виду, что края кажутся движущимися в разное время, это проблема (разрыв), обычно решаемая двойной буферизацией.Проблема вызвана тем фактом, что вы выполняете рендеринг на активной (видимой) поверхности, поэтому на экране могут отображаться полу-модифицированные кадры.
Может помочь иллюстрация.Допустим, вы пытаетесь перейти с левого изображения на правое:
~ ~ ^ ^
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 и проверьте его.Я запустил и ваш исходный (разрывающий) код, и этот вариант, и последний был более плавной анимацией.