不间断清屏
Clear Screen Without Interrupt
我正在使用 MASM 编写游戏,
我使用 ClrScr,它是 Irvine32.inc
中的一个程序
但无法清理整个控制台window
一些炭仍然存在。
我的代码是32位系统下的运行,所以不能使用"int"指令
我正在尝试编写一个程序来将黑色-space输出到整个控制台
但是当我调用那个proc时它会闪烁。而且很难盯着屏幕..
有解决办法吗?
更新
这是我用来清屏的代码
ForceCLS PROC
PUSH ECX
Translate 0,0 ;Gotoxy 0, 0
LoopTimes 50 ;Same AS MOV ECX, 50
SettingColor Black ;Set Font Color to Black
NewLine:
PUSH ECX
LoopTimes 115
BLANKS:
Write 020H
; Same As MOV EAX, 020H ; CALL WriteChar
Loop BLANKS
POP ECX
NL ;New Line
Loop NewLine
POP ECX
Translate 0,0 ;Same As Gotoxy 0, 0
DefaultColor ;Set Font Color to Default
RET
ForceCLS ENDP
这里是输出示例:
之所以会出现闪烁,是因为当您清除控制台时,它会暂时变成空白。
为了防止这种闪烁,您需要在内存缓冲区中渲染场景,然后将缓冲区输出到控制台。您可以为此使用 WriteConsoleOutput 函数。
这是 Windows 控制台中动画的一个简单示例。最有趣的部分发生在 ANIMATION
循环中。 RenderScene
过程将场景渲染到 buffer
,WriteConsoleOutput
函数将此缓冲区的内容发送到控制台。
TITLE Animation example
INCLUDE Irvine32.inc
INCLUDE win32.inc
COLS = 80 ; number of columns
ROWS = 25 ; number of rows
CHAR_ATTRIBUTE = 0Fh ; bright white foreground
.data
console HANDLE 0
buffer CHAR_INFO ROWS * COLS DUP(<<'-'>, CHAR_ATTRIBUTE>)
bufferSize COORD <COLS, ROWS>
bufferCoord COORD <0, 0>
region SMALL_RECT <0, 0, COLS-1, ROWS-1>
x DWORD 0 ; current position
y DWORD 2 ; of the figure
character WORD '0' ; filled with this symbol
.code
main PROC
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov console, eax ; save console handle
mov ecx, 70 ; draw 70 frames
ANIMATION:
push ecx
call RenderScene
invoke WriteConsoleOutput, console,
ADDR buffer, bufferSize, bufferCoord, ADDR region
INVOKE Sleep,250 ; delay between frames
pop ecx
loop ANIMATION
exit
main ENDP
ClearBuffer PROC USES eax
xor eax, eax
BLANKS:
mov buffer[eax * CHAR_INFO].Char, ' '
inc eax
cmp eax, ROWS * COLS
jl BLANKS
ret
ClearBuffer ENDP
CharToBuffer PROC USES eax edx bufx:DWORD, bufy:DWORD, char:WORD
mov eax, bufy
mov edx, COLS
mul edx
add eax, bufx
mov dx, char
mov buffer[eax * CHAR_INFO].Char, dx
ret
CharToBuffer ENDP
RenderScene PROC USES eax edx ecx
CALL ClearBuffer
; render 10 by 7 rectangle
mov edx, y
mov ecx, 7
ONELINE:
mov eax, x
push ecx
mov ecx, 10
ONECHAR:
INVOKE CharToBuffer, eax, edx, character
inc eax
loop ONECHAR ; inner loop prints characters
inc edx
pop ecx
loop ONELINE ; outer loop prints lines
inc x ; increment x for the next frame
inc character ; change fill character for the next frame
ret
RenderScene ENDP
END main
此示例使用了一些未包含在 Irvine32.inc 中的函数和结构,因此我在 win32.inc 文件中添加了一些声明:
CHARTYPE UNION
UnicodeChar WORD ?
AsciiChar DB ?
CHARTYPE ENDS
CHAR_INFO STRUCT
Char CHARTYPE <>
Attributes WORD ?
CHAR_INFO ENDS
WriteConsoleOutput EQU <WriteConsoleOutputA>
WriteConsoleOutput PROTO,
hConsoleOutput:HANDLE,
lpBuffer:PTR CHAR_INFO,
dwBufferSize:COORD,
dwBufferCoord:COORD,
lpWriteRegion:PTR SMALL_RECT
我正在使用 MASM 编写游戏,
我使用 ClrScr,它是 Irvine32.inc
中的一个程序但无法清理整个控制台window
一些炭仍然存在。
我的代码是32位系统下的运行,所以不能使用"int"指令
我正在尝试编写一个程序来将黑色-space输出到整个控制台
但是当我调用那个proc时它会闪烁。而且很难盯着屏幕..
有解决办法吗?
更新
这是我用来清屏的代码
ForceCLS PROC
PUSH ECX
Translate 0,0 ;Gotoxy 0, 0
LoopTimes 50 ;Same AS MOV ECX, 50
SettingColor Black ;Set Font Color to Black
NewLine:
PUSH ECX
LoopTimes 115
BLANKS:
Write 020H
; Same As MOV EAX, 020H ; CALL WriteChar
Loop BLANKS
POP ECX
NL ;New Line
Loop NewLine
POP ECX
Translate 0,0 ;Same As Gotoxy 0, 0
DefaultColor ;Set Font Color to Default
RET
ForceCLS ENDP
这里是输出示例:
之所以会出现闪烁,是因为当您清除控制台时,它会暂时变成空白。
为了防止这种闪烁,您需要在内存缓冲区中渲染场景,然后将缓冲区输出到控制台。您可以为此使用 WriteConsoleOutput 函数。
这是 Windows 控制台中动画的一个简单示例。最有趣的部分发生在 ANIMATION
循环中。 RenderScene
过程将场景渲染到 buffer
,WriteConsoleOutput
函数将此缓冲区的内容发送到控制台。
TITLE Animation example
INCLUDE Irvine32.inc
INCLUDE win32.inc
COLS = 80 ; number of columns
ROWS = 25 ; number of rows
CHAR_ATTRIBUTE = 0Fh ; bright white foreground
.data
console HANDLE 0
buffer CHAR_INFO ROWS * COLS DUP(<<'-'>, CHAR_ATTRIBUTE>)
bufferSize COORD <COLS, ROWS>
bufferCoord COORD <0, 0>
region SMALL_RECT <0, 0, COLS-1, ROWS-1>
x DWORD 0 ; current position
y DWORD 2 ; of the figure
character WORD '0' ; filled with this symbol
.code
main PROC
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov console, eax ; save console handle
mov ecx, 70 ; draw 70 frames
ANIMATION:
push ecx
call RenderScene
invoke WriteConsoleOutput, console,
ADDR buffer, bufferSize, bufferCoord, ADDR region
INVOKE Sleep,250 ; delay between frames
pop ecx
loop ANIMATION
exit
main ENDP
ClearBuffer PROC USES eax
xor eax, eax
BLANKS:
mov buffer[eax * CHAR_INFO].Char, ' '
inc eax
cmp eax, ROWS * COLS
jl BLANKS
ret
ClearBuffer ENDP
CharToBuffer PROC USES eax edx bufx:DWORD, bufy:DWORD, char:WORD
mov eax, bufy
mov edx, COLS
mul edx
add eax, bufx
mov dx, char
mov buffer[eax * CHAR_INFO].Char, dx
ret
CharToBuffer ENDP
RenderScene PROC USES eax edx ecx
CALL ClearBuffer
; render 10 by 7 rectangle
mov edx, y
mov ecx, 7
ONELINE:
mov eax, x
push ecx
mov ecx, 10
ONECHAR:
INVOKE CharToBuffer, eax, edx, character
inc eax
loop ONECHAR ; inner loop prints characters
inc edx
pop ecx
loop ONELINE ; outer loop prints lines
inc x ; increment x for the next frame
inc character ; change fill character for the next frame
ret
RenderScene ENDP
END main
此示例使用了一些未包含在 Irvine32.inc 中的函数和结构,因此我在 win32.inc 文件中添加了一些声明:
CHARTYPE UNION
UnicodeChar WORD ?
AsciiChar DB ?
CHARTYPE ENDS
CHAR_INFO STRUCT
Char CHARTYPE <>
Attributes WORD ?
CHAR_INFO ENDS
WriteConsoleOutput EQU <WriteConsoleOutputA>
WriteConsoleOutput PROTO,
hConsoleOutput:HANDLE,
lpBuffer:PTR CHAR_INFO,
dwBufferSize:COORD,
dwBufferCoord:COORD,
lpWriteRegion:PTR SMALL_RECT