




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、OpenGL實現俄羅斯方塊一、 設計思路本程序采用以C+為基礎并利用OpenGl庫函數的方式實現俄羅斯方塊程序,實現俄羅斯方塊中正方形,T形,L形,反L形,直線型,Z字形,反Z字形七種形狀的變換操作,七種形狀的坐標被存儲在一個三維數組中,每次隨機選擇一個形狀生成并下落,在下落過程中監聽鍵盤事件。二、 詳細設計說明本程序中主要的函數及其作用說明如下:down:定時下落函數,由glutTimerFunc(1000,down,1);函數設置每隔1000毫秒即調用一次該函數,在函數中將方塊的所有縱坐標減一個單位。key: 鍵盤事件監聽函數,當鍵盤上有按鍵被觸發的時候即調用該函數,函數內部支持w,a,s
2、,d四個鍵的響應,依次代表方向鍵上,左,右,下,其中w鍵是用來控制圖形變換的,每次按w鍵時,圖形在現有基礎上順時針變換一次。CheckConflict:沖突檢測函數,檢測方塊下一次將要移動的位置是否會碰到已有的方塊或者左右兩邊的墻壁。CheckDelete:每一次方塊落到底部之后,調用該函數檢查是否有滿行,如果有則調用Delete函數刪除該行。myDisplay1:作圖函數。Change:變換函數,主要是通過計算變換后的圖形與之前圖形的坐標關系來實現。三、 源代碼#include<GL/glut.h>#include<stdlib.h>#include<iostr
3、eam>#include<time.h>#include<windows.h>using namespace std;#define LEFT 'a'#define RIGHT 'd'#define UP 'w'#define DOWN 's'#define START 0/定義圖形的范圍#define END 19#define SIZE 25/*初始化七個二維數組,即七個塊剛開始產生時出現的位置*這里需要考慮的情況是:剛開始產生時有的方塊還只露出來一部分,*如果這個時候按了UP鍵進行變換應該怎么處
4、理*本程序最初設計并不考慮這個問題,一開始即畫出方塊的各個部分,以后再考慮完善的事情*另外,記錄坐標的順序為從左至右,從上至下*/GLfloat b53=0.0f,0.9f,0.0f,0.8f,0.0f,0.7f,0.0f,0.6f,/1、記錄長條四個坐標-0.1f,0.9f,0.0f,0.9f,-0.1f,0.8f,0.0f,0.8f,/2、記錄正方形-0.1f,0.9f,-0.2f,0.8f,-0.1f,0.8f,0.0f,0.8f,/3、T字形-0.1f,0.9f,0.0f,0.9f,0.0f,0.8f,0.1f,0.8f,/4、記錄Z字形-0.1f,0.9f,0.0f,0.9f,-0.
5、2f,0.8f,-0.1f,0.8f,/5、記錄倒Z字形-0.1f,0.9f,-0.1f,0.8f,-0.1f,0.7f,0.0f,0.7f,/6、記錄L字形0.0f,0.9f,0.0f,0.8f,-0.1f,0.7f,0.0f,0.7f,/7、記錄倒L字形;GLfloat curLoc53;GLint currentBlock=2;/記錄當前正在下落的是第幾種方塊,順序如上面所示GLint turn7=0;/應該變換成第幾種形態了GLfloat xd=0.0f,yd=0.0f;/*這里定義的over是用來判斷方塊是否到達了不能再往下降的地方,到了則置其為true,否則就修改為false。其中
6、有這樣幾種情況需要修改over:1、重新生成了一個方塊,修改over=false2、方塊到大底部,修改over=true*/bool over=false;/記錄游戲是否結束bool end=false;int score=0;/設置一個鎖,在下降操作時不允許變換,在變換時不允許下降操作,否則將會產生資源競爭/int lock=1;/*定義一個20*20的矩陣來記錄當前整個畫面中各個小格子的情況,可用來消除滿格行矩陣的存儲順序為從左到右,從下到上,包含下標0BLOCKij中i對應的是縱坐標,j對應的是橫坐標(這個有點痛苦),但是在消去滿格的時候還是不變,只是在用b數組給其賦值時需要反過來*/G
7、Lint BLOCKSIZESIZE;void down(int id);void InitBLOCK();void Change();void CheckDelete();int CheckConflict(int lef_rig=0);void CreateBlocks();void myDisplay1();void key(unsigned char k,int x,int y);void Delete(bool *empty);void show();void show()int i,j;for(i=0;i<4;i+)/函數調用的順序對錯誤有一定的影響for(j=0;j<
8、2;j+)cout<<curLocij<<" "cout<<endl;/*初始化方塊矩陣,方塊是一個上端開口的長方形*/void InitBLOCK()int i,j;for(i=0;i<SIZE;i+)for(j=0;j<SIZE;j+)BLOCKij=0;for(i=0;i<SIZE;i+)BLOCK0i=1;for(i=0;i<4;i+)for(j=0;j<2;j+)curLocij=bcurrentBlockij;void Change()/將圖形做變換,采用順時針旋轉的規律(下面的工作即是填入坐標)
9、GLfloat temp00=curLoc00;GLfloat temp01=curLoc01;GLfloat temp10=curLoc10;GLfloat temp11=curLoc11;GLfloat temp20=curLoc20;GLfloat temp21=curLoc21;GLfloat temp30=curLoc30;GLfloat temp31=curLoc31;switch(currentBlock)case 0:/長條switch(turn0)case 0:curLoc00=temp10-0.1f;curLoc01=temp11;curLoc20=temp10+0.1f;
10、curLoc21=temp11;curLoc30=temp10+0.2f;curLoc31=temp11;break;case 1:curLoc00=temp10;curLoc01=temp11+0.1f;curLoc20=temp10;curLoc21=temp11-0.1f;curLoc30=temp10;curLoc31=temp11-0.2f;break;turn0=(turn0+1)%2;break;case 1:/正方形break;case 2:/T字形/cout<<"turn2="<<turn2<<endl;switch(t
11、urn2)case 0:curLoc10=temp20;curLoc11=temp21;curLoc20=temp30;curLoc21=temp31;curLoc30=temp20;curLoc31=temp21-0.1f;break;case 1:curLoc00=temp10-0.1f;curLoc01=temp11;break;case 2:curLoc00=temp10;curLoc01=temp11+0.1f;curLoc10=temp00;curLoc11=temp01;curLoc20=temp10;curLoc21=temp11;break;case 3:curLoc30=t
12、emp20+0.1f;curLoc31=temp21;break;turn2=(turn2+1)%4;break;case 3:/Z字形switch(turn3)case 0:curLoc00=temp10+0.1f;curLoc01=temp11+0.1f;curLoc20=temp10+0.1f;curLoc21=temp11;curLoc30=temp20;curLoc31=temp21;break;case 1:curLoc00=temp10-0.1f;curLoc01=temp11;curLoc20=temp30;curLoc21=temp31;curLoc30=temp30+0.1
13、f;curLoc31=temp31;break;turn3=(turn3+1)%2;break;case 4:/反Z字形switch(turn4)case 0:curLoc00=temp00-0.1f;curLoc01=temp01+0.1f;curLoc10=temp00-0.1f;curLoc11=temp01;curLoc20=temp00;curLoc21=temp01;curLoc30=temp00;curLoc31=temp01-0.1f;break;case 1:curLoc00=temp20;curLoc01=temp21;curLoc10=temp20+0.1f;curLoc
14、11=temp21;curLoc20=temp10;curLoc21=temp11-0.1f;break;turn4=(turn4+1)%2;break;case 5:/L字形switch(turn5)case 0:curLoc00=temp10;curLoc01=temp11;curLoc10=temp10+0.1f;curLoc11=temp11;curLoc20=temp10+0.2f;curLoc21=temp11;curLoc30=temp20;curLoc31=temp21;break;case 1:curLoc00=temp00;curLoc01=temp01+0.1f;curL
15、oc10=temp10;curLoc11=temp11+0.1f;curLoc20=temp10;curLoc21=temp11;curLoc30=temp10;curLoc31=temp11-0.1f;break;case 2:curLoc00=temp20+0.1f;curLoc01=temp21;curLoc10=temp20-0.1f;curLoc11=temp21-0.1f;curLoc20=temp20;curLoc21=temp21-0.1f;curLoc30=temp20+0.1f;curLoc31=temp21-0.1f;break;case 3:curLoc00=temp1
16、0;curLoc01=temp11+0.2f;curLoc10=temp10;curLoc11=temp11+0.1f;curLoc20=temp10;curLoc21=temp11;curLoc30=temp20;curLoc31=temp21;break;turn5=(turn5+1)%4;break;case 6:/反L字形switch(turn6)case 0:curLoc00=temp20-0.1f;curLoc01=temp21+0.1f;curLoc10=temp20-0.1f;curLoc11=temp21;break;case 1:curLoc00=temp00+0.1f;c
17、urLoc01=temp01+0.1f;curLoc10=temp30;curLoc11=temp31+0.2f;curLoc20=temp00+0.1f;curLoc21=temp01;curLoc30=temp20;curLoc31=temp21;break;case 2:curLoc00=temp00-0.1f;curLoc01=temp01-0.1f;curLoc10=temp20;curLoc11=temp21;curLoc20=temp20+0.1f;curLoc21=temp21;curLoc30=temp30+0.1f;curLoc31=temp31;break;case 3:
18、curLoc00=temp20;curLoc01=temp21+0.1f;curLoc10=temp20;curLoc11=temp21;curLoc20=temp30-0.1f;curLoc21=temp31;curLoc30=temp30;curLoc31=temp31;break;turn6=(turn6+1)%4;break;/如果旋轉非法(即旋轉時碰到墻壁了),則要恢復原來的狀態int ret;ret=CheckConflict();if(ret = 1)curLoc00=temp00;curLoc01=temp01;curLoc10=temp10;curLoc11=temp11;c
19、urLoc20=temp20;curLoc21=temp21;curLoc30=temp30;curLoc31=temp31;/*消除滿格的一行,在每次over被修改為true的時候都要檢查一遍算法思想是從第0行開始依次判斷,如果empty為true則將下面的向上,并不是判斷一次就移動所有的,而是只移動最近的,將空出來的那一行的empty標記為true*/void Delete(int *empty)int i,j;int pos;while(1)/將上面非空的行填補到下面的空行中i=1;while(i < 20&&emptyi = 0)/為空或者滿,都需要將上面的行移下
20、來填充i+;if(i >= 20)break;j=i+1;while(j < 20&&emptyj = -1)j+;if(j >= 20)break;if(j < 20&&emptyj != -1)for(pos=0;pos<20;pos+)BLOCKipos=BLOCKjpos;emptyi=emptyj;emptyj=-1;for(i=1;i<20;i+)if(emptyi != 0)for(j=0;j<20;j+)BLOCKij=0;/*1、判斷新生成的圖形是否和原來的圖形有沖突,有則不能更改,這個地方比較不好實現
21、*2、判斷是否有滿格的行,有則調用Delete函數去掉*3、這里似乎還要加上判斷是否到大頂部,如果到達頂部則游戲結束(可采用監視方框最上*面一行之上那行里面有沒有方格,如果有的話則游戲結束)*結束之后就可以把當前方塊存入BLOCK中*empty表示一行中方塊的數目,-1表示為空行,0表示部分為空,1表示滿行*/void CheckDelete()/目前這個函數還只是實現了一個方塊到達終點之后是否有能夠被刪除的行int i,j;int emptySIZE;bool is_needed=false;int count;for(i=0;i<SIZE;i+)emptyi=-1;for(i=0;i
22、<4;i+)double x=(curLoci0+1)*10+0.5;/此處無需注意取值,因為checkConflict已經解決double y=(curLoci1+1)*10+0.5;BLOCK(int)y(int)x=1;/融合for(i=1;i<20;i+)count=0;for(j=0;j<20;j+)if(BLOCKij=1)count+;if(count=20)emptyi=1;/若滿格,則可以刪除,置為truescore+;/此處計分is_needed=true;else if(count > 0&&count < 20)emptyi
23、=0;if(is_needed=true)/如果有滿行則去刪除,否則免之Delete(empty);int CheckConflict(int lef_rig)int i;for(i=0;i<4;i+)double x=(curLoci0+1)*10;/注意取值!double y=(curLoci1+1)*10+0.5;/y方向無需注意x=x>0?(x+0.5):(x-0.5);if(lef_rig = 1)int tmpx=(int)x;if(tmpx > 19|tmpx < 0)break;if(BLOCK(int)y(int)x=1) /判斷是否發生沖突break
24、;if(i < 4)return 1;return 0;/*關鍵部分在這里,主要是要判斷方塊下一次的移動是否合法,本程序通過對b數組所存儲的下標是否在BLOCK數組中已經為1來判斷,這樣,只需要在BLOCK的最外層加一圈1,就不用通過原來的方式來判斷方塊是否越界*/void key(unsigned char k,int x,int y)int i,ret;if(over = false)if(k=UP)/此處需要改成調用變換圖形樣式的函數Change();else if(k=DOWN)/后續還要修改,移動到底部過了一段時間之后就不能左右移動了for(i=0;i<4;i+)/需繼續
25、添加以1和-1作為哨兵curLoci1-=0.1f;ret=CheckConflict();if(ret = 1)/發生沖突,則將修改復原for(i=0;i<4;i+)curLoci1+=0.1f;over=true;/并且可以生成下一個方塊了else if(k=RIGHT)for(i=0;i<4;i+)curLoci0+=0.1f;ret=CheckConflict(1);if(ret = 1)/發生沖突,則將修改復原for(i=0;i<4;i+)curLoci0-=0.1f;else if(k=LEFT)for(i=0;i<4;i+)curLoci0-=0.1f;r
26、et=CheckConflict(1);if(ret = 1)/發生沖突,則將修改復原for(i=0;i<4;i+)curLoci0+=0.1f;if(over=true)CheckDelete();glutPostRedisplay();/調用這個函數可以重新繪圖,每次相應消息之后,所有全部重繪/*讓方塊定時下降*/void down(int id)int i,ret;if(over!=true)for(i=0;i<4;i+)/需繼續添加以1和-1作為哨兵curLoci1-=0.1f;ret=CheckConflict();if(ret = 1)/發生沖突,則將修改復原for(i
27、=0;i<4;i+)curLoci1+=0.1f;if(curLoc01 >= bcurrentBlock01)cout<<"Game over,your score is:"<<score*100<<endl;exit(1);over=true;/并且可以生成下一個方塊了if(over=true)CheckDelete();glutPostRedisplay();glutTimerFunc(1000,down,1);/作圖函數,要修改,利用BLOCK數組繪圖void myDisplay1()int i,j;glClear(G
28、L_COLOR_BUFFER_BIT);/不能使用深度測試,否則畫出來的圖形很亂for(i=0;i<20;i+)for(j=0;j<20;j+)if(BLOCKij=1)glColor3f(0.0f,1.0f,0.0f);/用藍色畫圖glRectf(j/10.0f-1.0f,i/10.0f-1.0f,j/10.0f-1.0f+0.1f,i/10.0f-1.0f+0.1f);glLineWidth(2.0f);glBegin(GL_LINE_LOOP);glColor3f(0.0f,0.0f,0.0f);glVertex2f(j/10.0f-1.0f,i/10.0f-1.0f);glVertex2f(j/10.0f-1.0f+0.1f,i/10.0f-1.0f);glVertex2f(j/10.0f-1.0f+0.1f,i/10.0f-1.0f+0.1f);glVertex2f(j/10.0f-1.0f,i/10.0f-1.0f+0.1f);glEnd();glFlush();if(over = false)for(i=0;i<4;i+)glColor3f(0.0f,1.0
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《碳中和概論》課件第1章 緒論
- 智能家電產品代理銷售及售后服務協議
- 語文現代散文閱讀理解技巧提升課
- 《五言絕句詩詞教學:唐詩的欣賞與創作》
- 市場營銷推廣合作協議詳細版
- 學習的重要性演講演講稿類話題12篇
- 石油勘探項目合作合同
- 食品安全與健康營養知識要點梳理與解析
- 2025年藥學基礎知識期末考試試卷及答案
- 2025年信息傳播與社會網絡研究期末考試試題及答案
- 人工智能在教育行業的創新應用研究
- 高考物理一輪復習考點精講精練第34講 光電效應 波粒二象性(解析版)
- 新能源行業光伏發電技術操作指南
- 陽光心理-健康人生小學生心理健康主題班會課件
- 城口縣集中供暖工程特許經營管理招標文件
- 學前兒童健康教育 課件項目六 學前兒童安全教育
- 山東省臨沂市平邑縣2023-2024學年七年級下學期7月期末歷史試題(原卷版)
- 2024年山東省濰坊市中考生物試卷附答案
- 北京聯合大學微觀經濟學期末試卷
- 肺癌胸腔鏡(肺葉切除)護理查房課件
- 云南省昆明市2023-2024學年高二下學期期末質量檢測化學試題
評論
0/150
提交評論