好吧,我正在 Assembly x86 ( 8086 ) 上制作 Space Invaders 游戏,到目前为止它运行良好。我在图形模式 13h
中使用程序集,这意味着 320x200 像素和 256 种颜色。
对于绘图,我正在使用子函数 0ch
,这意味着我正在逐像素绘图。问题是屏幕清除速度非常快,会导致一些视觉故障。
我之前编写过一些游戏,解决方案可能是双缓冲绘图。 如何在 Assembly x86 中实现这一点?
编辑
我正在使用 Windows 8 X64,用于测试和运行我的代码 DOSBox Portable、tasm 和 tlink。
最佳答案
您需要在 RAM 中有一个缓冲区(320*200 = 64000 字节)。这个缓冲区几乎填满了一个段,所以最好确保缓冲区的起始地址是“段:0x0000”。您可以通过在 RAM 中的此缓冲区中设置像素/字节来绘制内容。例如,要将 (x,y) 处的像素设置为颜色 c,您可以这样做:
mov ax,[y]
mov dx,320
mul dx ;dx:ax = y * 320
mov di,[x] ;di = x
add di,ax ;di = y * 320 + x
mov bx,[bufferSeg] ;bx = segment of video buffer
mov es,bx ;es:di = address of pixel
mov al,[c] ;al = colour
mov [es:di],al ;Store colour in buffer at (x,y)
如您所见,这个计算很困惑/很慢;而且您不想为每个像素都这样做。幸运的是,您几乎不需要绘制单个像素(通常是绘制线条或字符,或“ Sprite ”),通常您可以计算第一个像素的地址,然后向其添加一些内容以找到下一个像素的地址从头开始计算下一个像素的地址。例如,对于绘制垂直线,下一个像素的地址是前一个像素的地址 + 320。
对于图形模式0x13;显示内存位于物理地址 0x000A0000(或 0xA000:0x0000)。绘制完所有内容后,您可以将缓冲区中的所有内容复制到显示内存中。例如:
mov ds,ax ;ds = segment for buffer
xor si,si ;si:si = address for buffer
mov ax,0xA000 ;ax = segment for display memory
mov di,ax ;di = segment for display memory
mov es,ax ;es:di = address for display memory
mov cx,320*200/2 ;cx = number of words to copy
cld ;Make sure direction flag is clear
rep movsw ;Copy 320*200/2 words from buffer to display memory
关于assembly - 双缓冲,汇编 x86,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13241594/