C語言圖形編程——俄羅斯方塊制作詳解
效果圖
用C語言實現(xiàn)俄羅斯方塊,需要先解決下面幾個問題:
1、如何用C語言繪制圖形界面
EasyX圖形庫(http://www.easyx.cn)即TC的圖形庫在VC下的移植。
包含庫#include
先初始化圖形窗口
initgraph(WINDOW_WIDTH, WINDOW_HIGH) ;WINDOW_WIDTH為窗口的寬帶,WINDOW_HIGH為窗口的高度。
清空繪圖設(shè)備
cleardevice();
設(shè)置畫筆顏色
setcolor(RED) ;
設(shè)置線條風(fēng)格
setlinestyle(PS_SOLID, NULL, 0);
畫矩形
rectangle
還有畫線、顯示文字等函數(shù),可以參照其幫助文檔。
注意:由于我們用的是EasyX圖形庫,故源文件后綴要為.cpp,但其中內(nèi)容都是C的語法。
歡迎加入學(xué)習(xí)群【892643663】,獲取全套免費C/C++企業(yè)實戰(zhàn)級課程資源(素材+源碼+視頻)和編譯大禮包
2、如何存儲表示出俄羅斯方塊的形狀
在計算機(jī)中如何讓一串的01數(shù)字,代表俄羅斯方塊?
一、我們可以用編號,不同的編號代表不同的俄羅斯方塊,根據(jù)編號把不同方塊的畫法寫在代碼中,這樣19種
方塊就得有19種相應(yīng)的代碼來描繪。而且這樣擴(kuò)展性不好,若以后設(shè)計了新的方塊,則需要更改大量源代碼。
二、我們很自然的想到可用字模點陣的形式來表示,即設(shè)置一個4行4列的數(shù)組,元素置1即代表這個位置有小
方塊,元素置0即代表這個位置無小方塊,這個整個的4*4的數(shù)組組成俄羅斯方塊的形狀。
1000
1000
1100
0000
這個方法挺靠譜,但我們還可以優(yōu)化一下:不用4*4的數(shù)組,而是用16個bit位來表示這個點陣。這樣存儲起來比較方便,故我們用unsigned int 的低16位來表示方塊的點陣。
我們可以用掩碼與表示俄羅斯方塊的位進(jìn)行操作,來識別并在屏幕上畫出方塊。
詳情見GUI.cpp中的DrawRock函數(shù)。
(需要源代碼的,私信“資料”小編)
//逐位掃描由unsigned int的低2字節(jié)
//16個位組成的俄羅斯方塊形狀點陣(其代表4*4的方塊形狀)
mask = (unsigned int)1 << 15 ;
for (i=1; i<=16; i++)
{
//與掩碼相與為1的 即為方塊上的點
if ((rockArray[rockIndex].rockShapeBits & mask) != 0)
{
//在屏幕上畫出此方塊
rectangle(rockX+2,
rockY+2,
rockX+ROCK_SQUARE_WIDTH-2,
rockY+ROCK_SQUARE_WIDTH-2) ;
}
//每4次 換行 轉(zhuǎn)到下一行繼續(xù)畫
i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left)
: rockX += ROCK_SQUARE_WIDTH ;
mask >>= 1 ;
}
我們把俄羅斯方塊點陣的數(shù)位存在rockArray中,我們可以事先把這19種方塊的字模點陣自己轉(zhuǎn)化成十六進(jìn)制,然后在rockArray數(shù)組的初始化時賦值進(jìn)去。
但這樣做未免有點太費力,且擴(kuò)展性也不太好,若以后設(shè)計的新方塊種類加入,要改變數(shù)組rockArray中的值。
我們可以考慮把所有俄羅斯方塊的點陣存儲在配置文件中,在程序初始化時讀取文件,把這些點陣轉(zhuǎn)換成unsigned int的變量存儲在rockArray中。
這樣,以后我們增添新的方塊形狀只需要在配置文件中增加新的點陣即可。
@###
@###
@@##
#### (為使得看起來更醒目,我們用@表示1,用#表示0)
3、如何讓圖形動起來
若沒有按鍵的情況下,方塊是自動下落的。
如何實現(xiàn)自動下落?在某位置處用函數(shù)DrawRock在屏幕上畫出俄羅斯方塊,然后再擦除掉(即用背景色在原位置處重繪一次方塊),最后在下落的下一個位置處用函數(shù)DrawRock在屏幕上畫出俄羅斯方塊,如此循環(huán),中間用計時器間隔一段時間以控制下落的速度。
同理,按下屏幕的左右鍵也是如此,只是在按下鍵盤時把方塊的位置重新計算了。
那么按下上方向鍵時,如何讓方塊翻轉(zhuǎn)呢?
我們在配置文件中就把方塊的順時針翻轉(zhuǎn)形態(tài)放在了一起:
@###
@###
@@##
####
@@@#
@###
####
####
@@##
#@##
#@##
####
##@#
@@@#
####
####
我們每按一次上方向鍵改變一次方塊的形狀即可。若一直按上鍵,形狀應(yīng)該是循環(huán)地翻滾。
我們想到了循環(huán)鏈表的數(shù)據(jù)結(jié)構(gòu)可實現(xiàn)這個效果。
可是我們?nèi)舭堰@些一種類的方塊的各種形態(tài)串成循環(huán)鏈表形式,那么每次重新生成方塊時我們就難以隨機(jī)地生成方塊了。
故還是得用數(shù)組來存儲,但又要有循環(huán)鏈表的功能,于是我們想到了靜態(tài)循環(huán)鏈表。
我們用結(jié)構(gòu)體來作為一個方塊在rockArray中的元素
typedef struct ROCK
{ //用來表示方塊的形狀(每一個字節(jié)是8位,用每4位表示方塊中的一行)
unsigned int rockShapeBits ;
int nextRockIndex ; //下一個方塊,在數(shù)組中的下標(biāo)
} RockType ;
這樣,當(dāng)我們按下上方向鍵時,把傳入函數(shù)DrawRock中的rockIndex變?yōu)楫?dāng)前方塊結(jié)構(gòu)體中的nextRockIndex即可。
詳情見play.cpp中的ProccessUserHit函數(shù)。
4、如何判斷方塊什么時候停止什么時候滿行得分
方塊一直下落,最終是要停下來的,我們要設(shè)置一個邊界來約束方塊的移動范圍。我們把當(dāng)前游戲界面劃分成以俄羅斯方塊中的小方格為單位的格子,用一個二維數(shù)組g_gameBoard來表示這些小方格的狀態(tài),1表示此位置有方塊,0表示此位置為空。
我們按照界面的大小和方格的大小來計算此二維數(shù)組時,再多設(shè)置一圈“圍墻”,即多加兩行兩列,并把它們的值初始化為1。
當(dāng)方塊準(zhǔn)備下落或是左右移動的時候,前提前檢查其即將落下的位置是否為空,若不為空,則停止下落,并把當(dāng)前俄羅斯方塊占用的方格都設(shè)置為1。
詳情見play.cpp中的moveAbled函數(shù)。
判斷滿行:
從最后一行開始往上檢查g_gameBoard,若有一行全為1,則說明此行滿行,將此行擦出,把此行上面的所有行向下移動一個單位。
詳情見play.cpp中的ProcessFullRow函數(shù)
5、其他細(xì)節(jié)問題:
如何快速下落
詳情見play.cpp中的FastFall函數(shù)
如何暫停
詳情見play.cpp中的ProccessUserHit函數(shù)
此游戲程序的主要邏輯在play.cpp中的PlayGame函數(shù)
歡迎加入學(xué)習(xí)群【892643663】,獲取全套免費C/C++企業(yè)實戰(zhàn)級課程資源(素材+源碼+視頻)和編譯大禮包
c語言 C 語言 c++
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。