assembly 我怎样才能避免一些图形故障时更新精灵?

798qvoo8  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(109)

我正在做一个汇编游戏引擎项目。在x86汇编中是否有一种方法可以快速清除屏幕(类似CLS)?我重新初始化图形模式来完成此操作。

MOV AH,00H
MOV AL,13H
INT 10H

字符串
我在屏幕上创建了图形缺陷,以进行持续更新。我做错什么了吗?我是不是应该推迟一下?
这些是当我在屏幕上移动精灵时出现的图形故障。


的数据
在这张图片中,你可以清楚地看到写着“得分000”和边界,但一切都是不相的。这是没有连续刷新时的屏幕



刷新是因为我绘制了精灵,所以我清除屏幕并在新的位置再次绘制精灵。基于按下的箭头键。

sqserrrh

sqserrrh1#

现在,您可以通过清除 * 整个屏幕 * 然后重新绘制 * 整个屏幕 * 来设置精灵的动画。这会产生 Flink 和伪影。
在x86汇编中是否有方法快速清除屏幕(类似CLS)?我重新初始化图形模式来完成此操作。
加速CLS并不能解决这个问题,但是限制精灵周围的方块的清除可以避免这些瑕疵。之后你是否重新绘制整个屏幕,或者只是重新绘制新旧框的组合区域,这只是一个“容易”与“更复杂”的问题(“容易”是因为绘制整个屏幕的代码肯定已经存在)。
在正常(游戏)条件下,新的周围框将从旧的周围框偏移几个像素。重画可能会非常快,也许也死容易,如果除了精灵本身,它只需要包括那些少数目标点,我看到的图片,你张贴。
我只是实现了@MargaretBloom建议的方法。
所有的绘图都进入一个离屏缓冲区,一旦一帧完成,它就会在垂直回扫期间在A000 h处被复制到实际的视频缓冲区。我用FASM编写了程序,并在DOSBox下进行了测试。不用说,它的工作,但我应该提到,我没有观察到任何需要等待垂直回扫期之前,复制私人缓冲区的官方视频缓冲区。也许在模拟器之外会更重要...
x1c 0d1x的数据

; Demo for sprite movement
; Assembled with FASM 1.73
; Tested on DOSBox 0.74

        ORG     256

        mov     ax, 0013h       ; BIOS.SetVideomode
        int     10h
; Clear the double buffer
        mov     di, Buffer
        mov     cx, 32000
        xor     ax, ax
        rep stosw
; Draw the border rectangle (once)
        mov     bl, 5           ; Magenta
        xor     cx, cx
.a:     mov     dx, 199
        call    SetPixel
        xor     dx, dx
        call    SetPixel
        inc     cx
        cmp     cx, 320
        jb      .a
.b:     mov     cx, 319
        call    SetPixel
        xor     cx, cx
        call    SetPixel
        inc     dx
        cmp     dx, 200
        jb      .b

        mov     cx, 155         ; SpriteX
        mov     dx, 95          ; SpriteY

MainEx:
; Both pixels are in layer beneath the sprite
        push    cx dx           ; (1)
        mov     bl, 14          ; Yellow
        mov     cx, 140
        mov     dx, 80
        call    SetPixel
        mov     bl, 12          ; LightRed
        mov     cx, 180
        mov     dx, 80
        call    SetPixel
        pop     dx cx           ; (1)
; Sprite is in layer above the separate pixels
        mov     bl, 10          ; LightGreen
        mov     [SpriteX], cx
        mov     [SpriteY], dx
        call    DrawSprite
; Refresh the video ram from the latest info
        call    UpdateScreen

Main:   mov     ah, 00h         ; BIOS.GetKeystroke
        int     16h             ; -> AX
        mov     al, ah          ; Inspecting scancode
        mov     bl, 0           ; Background color is Black
        mov     cx, [SpriteX]
        mov     dx, [SpriteY]
        cmp     al, 4Bh         ; <LEFT>
        je      Left
        cmp     al, 4Dh         ; <RIGHT>
        je      Right
        cmp     al, 48h         ; <UP>
        je      Up
        cmp     al, 50h         ; <DOWN>
        je      Down
        cmp     al, 01h         ; <ESC>
        jne     Main

        mov     ax, 0003h       ; BIOS.SetVideomode
        int     10h
        mov     ax, 4C00h       ; DOS.Terminate
        int     21h
; ------------------------------
Left:   cmp     cx, 1
        jna     Main
        call    DrawSprite      ; Wipes sprite
        dec     cx              ; X--
        jmp     MainEx
; ------------------------------
Right:  cmp     cx, 308
        jnb     Main
        call    DrawSprite      ; Wipes sprite
        inc     cx              ; X++
        jmp     MainEx
; ------------------------------
Up:     cmp     dx, 1
        jna     Main
        call    DrawSprite      ; Wipes sprite
        dec     dx              ; Y--
        jmp     MainEx
; ------------------------------
Down:   cmp     dx, 189
        jnb     Main
        call    DrawSprite      ; Wipes sprite
        inc     dx              ; Y++
        jmp     MainEx
; ------------------------------
UpdateScreen:
        push    es
        pusha
        mov     dx, 03DAh       ; Input Status #1
@@:     in      al, dx
        test    al, 8
        jnz     @b              ; Vertical Retrace in progress
@@:     in      al, dx
        test    al, 8
        jz      @b              ; Awaiting a fresh Vertical Retrace

        mov     ax, 0A000h
        mov     es, ax
        xor     di, di
        mov     si, Buffer
        mov     cx, 32000
        rep movsw
        popa
        pop     es
        ret
; ------------------------------
; IN (bl,cx,dx)
SetPixel:
        push    di
        imul    di, dx, 320     ; Y * 320 + X
        add     di, cx
        mov     [Buffer + di], bl
        pop     di
        ret
; -------------------------------
; IN (bl,cx,dx)
DrawSprite:
        pusha
        mov     si, SpriteD
.a:     imul    di, dx, 320     ; Y * 320 + X
        add     di, cx
        lodsw
        shl     ax, 1
        jnc     .c
.b:     mov     [Buffer + di], bl
.c:     inc     di
        shl     ax, 1
        jc      .b
        jnz     .c
        inc     dx              ; Y++
        cmp     si, SpriteD+20
        jb      .a
        popa
        ret
; ------------------------------
        ALIGN   2
SpriteX dw      0
SpriteY dw      0
SpriteD dw      0010000010000000b
        dw      0010000010000000b
        dw      0001000100000000b
        dw      0011111110000000b
        dw      0110111011000000b
        dw      1111111111100000b
        dw      1011111110100000b
        dw      1011111110100000b
        dw      1010000010100000b
        dw      0001101100000000b
Buffer  rb      64000

字符串

等待垂直回扫

mov     dx, 03DAh       ; Input Status #1
@@:     in      al, dx
        test    al, 8
        jnz     @b              ; Vertical Retrace in progress
@@:     in      al, dx
        test    al, 8
        jz      @b              ; Awaiting a fresh Vertical Retrace


如果输入状态#1的位3被清除,则表示显示器处于显示模式。
如果输入状态#1的位3被置位,则表示显示器处于垂直回扫模式。然而,它没有告诉我们的是,在“垂直回扫周期”上还剩下多少时间。这就是为什么程序使用第二个循环来等待“显示周期”结束的原因。然后我们将有最大的'垂直回扫周期'的时间来做复制。

相关问题