稍後我們就會具體使用程式碼來觀察現象,並使用double buffer來解決掉。
請先將前節<bgi>目錄夾複製一份,改名為<doubleBuffer>
==========
STEP #1:
修改前節程式碼,我們使用一個1000次的for迴圈,讓畫面中的搖桿每16ms向右移動1 pixel。
#include <stdio.h> #include <conio.h> #include "graphics.h" #include <stdlib.h> int main(){ initwindow(640,480,"This is my game"); setcolor(2); settextstyle(SANS_SERIF_FONT, HORIZ_DIR, 0); outtextxy(200,300,"hello world"); readimagefile("games.gif", 220, 120, 380, 280); getch(); cleardevice(); getch(); for(int i; i<1000;i++){ cleardevice(); readimagefile("games.gif", 220+i, 120, 380+i, 280); delay(16); } }
- #19清屏
- #20行繪製"games.gif"
按下F5運行,連按兩次Enter後可看到畫面中的搖桿向右移動,但屏幕不停地閃爍。
閃爍的原因是因為:#19行執行完畢後,畫面確實地變成了全黑,而後再繪製上了搖桿。這個繪圖過程雖然快速,但還是會出現黑屏殘像,因此產生了閃爍。
解決的方式是使用setactivepage()與setvisualpage()兩則指令,做出切換page的動作。
==================
STEP #2
修改程式如下:
#include <stdio.h> #include <conio.h> #include "graphics.h" #include <stdlib.h> int main(){ int curPage =0; initwindow(640,480,"This is my game"); setactivepage(curPage); setvisualpage(curPage); setcolor(2); settextstyle(SANS_SERIF_FONT, HORIZ_DIR, 0); outtextxy(200,300,"hello world"); readimagefile("games.gif", 220, 120, 380, 280); getch(); cleardevice(); getch(); for(int i; i<1000;i++){ curPage = (curPage + 1) % 2; setactivepage(curPage); cleardevice(); readimagefile("games.gif", 220+i, 120, 380+i, 280); setvisualpage(curPage); delay(16); } }
- #8宣告了一個整數變數curPage(current page),用以紀錄目前操作中的頁面號碼。這個page可視為傳統double buffer技巧中的buffer概念。
- #12,#13在初始化的過程中,先使用預設頁面0來做首次繪製。
- #23使用餘數除法(mod,後稱餘除法)。這條指令可讓0變1,1變0,做出切換的效果。
- #24切換到非顯示中的頁面,隨後接著清屏並繪製games.gif
- #27將非顯示頁切換為顯示頁
由於在清屏與繪製的過程中,我們是針對非顯示中的頁面,因此繪製的過程也就是圖像蝶家的過程玩家是看不到的。等待繪製完畢(疊加完畢)後再一次切換為顯示屏讓玩家看清楚。如此一來就不會讓玩家看到繪製的過程,也就不會閃爍了。
按F5運行遊戲,確認此次搖桿向右移動時不會有閃爍現象。
==============
STEP #3:
剛剛使用curPage去做顯示切換實在太麻煩了(還要用餘除法,實在很累捏~~),
所以接下來我們改用超好用的swapbuffer()指令來改寫上述程式。
由於在以前的年代graphics.h只支援雙buffer(也夠了),所以整個顯示的過程是由page0與page1分工合作所完成了。
我們設計的工作流程是這樣的:
- 在任何時刻下,其中一個page作為繪製屏,另一page做為顯示屏。繪製顯示屏必定不為同一屏。
- 當程式在繪製屏上繪製完畢時,直接下一則swapbuffers()指令將角色轉換。如此一來繪製結果立刻可輸出。
- 由於新繪製圖已顯示,所以前次的顯示屏在swapbuffers()後角色轉為繪製屏,其內容已不需要,固可大膽重繪之。
改寫程式如下:
#include <stdio.h> #include <conio.h> #include "graphics.h" #include <stdlib.h> int main(){ initwindow(640,480,"This is my game"); setactivepage(0); setvisualpage(1); setcolor(2); settextstyle(SANS_SERIF_FONT, HORIZ_DIR, 0); outtextxy(200,300,"hello world"); readimagefile("games.gif", 220, 120, 380, 280); swapbuffers(); getch(); cleardevice(); swapbuffers(); getch(); for(int i; i<1000;i++){ cleardevice(); readimagefile("games.gif", 220+i, 120, 380+i, 280); swapbuffers(); delay(16); } }
完成後按F5運行,確認功能與上個STEP完全相同。
* winBGIm的說明文檔在此。