版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
/ OpenGL實(shí)現(xiàn)俄羅斯方塊設(shè)計(jì)思路本程序采用以C++為基礎(chǔ)并利用OpenGl庫函數(shù)的方式實(shí)現(xiàn)俄羅斯方塊程序,實(shí)現(xiàn)俄羅斯方塊中正方形,T形,L形,反L形,直線型,Z字形,反Z字形七種形狀的變換操作,七種形狀的坐標(biāo)被存儲在一個三維數(shù)組中,每次隨機(jī)選擇一個形狀生成并下落,在下落過程中監(jiān)聽鍵盤事件。詳細(xì)設(shè)計(jì)說明本程序中主要的函數(shù)與其作用說明如下:down:定時下落函數(shù),由glutTimerFunc(1000,down,1);函數(shù)設(shè)置每隔1000毫秒即調(diào)用一次該函數(shù),在函數(shù)中將方塊的所有縱坐標(biāo)減一個單位。key:鍵盤事件監(jiān)聽函數(shù),當(dāng)鍵盤上有按鍵被觸發(fā)的時候即調(diào)用該函數(shù),函數(shù)內(nèi)部支持w,a,s,d四個鍵的響應(yīng),依次代表方向鍵上,左,右,下,其中w鍵是用來控制圖形變換的,每次按w鍵時,圖形在現(xiàn)有基礎(chǔ)上順時針變換一次。CheckConflict:沖突檢測函數(shù),檢測方塊下一次將要移動的位置是否會碰到已有的方塊或者左右兩邊的墻壁。CheckDelete:每一次方塊落到底部之后,調(diào)用該函數(shù)檢查是否有滿行,如果有則調(diào)用Delete函數(shù)刪除該行。myDisplay1:作圖函數(shù)。Change:變換函數(shù),主要是通過計(jì)算變換后的圖形與之前圖形的坐標(biāo)關(guān)系來實(shí)現(xiàn)。源代碼#include<GL/glut.h>#include<stdlib.h>#include<iostream>#include<time.h>#include<windows.h>usingnamespacestd;#defineLEFT'a'#defineRIGHT'd'#defineUP'w'#defineDOWN's'#defineSTART0//定義圖形的范圍#defineEND19#defineSIZE25/**初始化七個二維數(shù)組,即七個塊剛開始產(chǎn)生時出現(xiàn)的位置*這里需要考慮的情況是:剛開始產(chǎn)生時有的方塊還只露出來一部分,*如果這個時候按了UP鍵進(jìn)行變換應(yīng)該怎么處理*本程序最初設(shè)計(jì)并不考慮這個問題,一開始即畫出方塊的各個部分,以后再考慮完善的事情*另外,記錄坐標(biāo)的順序?yàn)閺淖笾劣?,從上至?/GLfloatb[][5][3]={ {{0.0f,0.9f},{0.0f,0.8f},{0.0f,0.7f},{0.0f,0.6f}},//1、記錄長條四個坐標(biāo) {{-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.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字形};GLfloatcurLoc[5][3];GLintcurrentBlock=2;//記錄當(dāng)前正在下落的是第幾種方塊,順序如上面所示GLintturn[7]={0};//應(yīng)該變換成第幾種形態(tài)了GLfloatxd=0.0f,yd=0.0f;/*這里定義的over是用來判斷方塊是否到達(dá)了不能再往下降的地方,到了則置其為true,否則就修改為false。其中有這樣幾種情況需要修改over:1、重新生成了一個方塊,修改over=false2、方塊到大底部,修改over=true*/boolover=false;//記錄游戲是否結(jié)束boolend=false;intscore=0;//設(shè)置一個鎖,在下降操作時不允許變換,在變換時不允許下降操作,否則將會產(chǎn)生資源競爭//intlock=1;/*定義一個20*20的矩陣來記錄當(dāng)前整個畫面中各個小格子的情況,可用來消除滿格行矩陣的存儲順序?yàn)閺淖蟮接?,從下到上,包含下?biāo)0BLOCK[i][j]中i對應(yīng)的是縱坐標(biāo),j對應(yīng)的是橫坐標(biāo)(這個有點(diǎn)痛苦),但是在消去滿格的時候還是不變,只是在用b數(shù)組給其賦值時需要反過來*/GLintBLOCK[SIZE][SIZE];voiddown(intid);voidInitBLOCK();voidChange();voidCheckDelete();intCheckConflict(intlef_rig=0);voidCreateBlocks();voidmyDisplay1();voidkey(unsignedchark,intx,inty);voidDelete(bool*empty);voidshow();voidshow(){ inti,j; for(i=0;i<4;i++) //函數(shù)調(diào)用的順序?qū)﹀e誤有一定的影響 for(j=0;j<2;j++) { cout<<curLoc[i][j]<<""; } cout<<endl;}/*初始化方塊矩陣,方塊是一個上端開口的長方形*/voidInitBLOCK(){ inti,j; for(i=0;i<SIZE;i++) for(j=0;j<SIZE;j++) BLOCK[i][j]=0; for(i=0;i<SIZE;i++) BLOCK[0][i]=1; for(i=0;i<4;i++) for(j=0;j<2;j++) curLoc[i][j]=b[currentBlock][i][j];}voidChange()//將圖形做變換,采用順時針旋轉(zhuǎn)的規(guī)律(下面的工作即是填入坐標(biāo)){ GLfloattemp00=curLoc[0][0]; GLfloattemp01=curLoc[0][1]; GLfloattemp10=curLoc[1][0]; GLfloattemp11=curLoc[1][1]; GLfloattemp20=curLoc[2][0]; GLfloattemp21=curLoc[2][1]; GLfloattemp30=curLoc[3][0]; GLfloattemp31=curLoc[3][1]; switch(currentBlock) { case0://長條 switch(turn[0]) { case0: curLoc[0][0]=temp10-0.1f; curLoc[0][1]=temp11; curLoc[2][0]=temp10+0.1f; curLoc[2][1]=temp11; curLoc[3][0]=temp10+0.2f; curLoc[3][1]=temp11; break; case1: curLoc[0][0]=temp10; curLoc[0][1]=temp11+0.1f; curLoc[2][0]=temp10; curLoc[2][1]=temp11-0.1f; curLoc[3][0]=temp10; curLoc[3][1]=temp11-0.2f; break; } turn[0]=(turn[0]+1)%2; break; case1://正方形 break; case2://T字形 //cout<<"turn[2]="<<turn[2]<<endl; switch(turn[2]) { case0: curLoc[1][0]=temp20; curLoc[1][1]=temp21; curLoc[2][0]=temp30; curLoc[2][1]=temp31; curLoc[3][0]=temp20; curLoc[3][1]=temp21-0.1f; break; case1: curLoc[0][0]=temp10-0.1f; curLoc[0][1]=temp11; break; case2: curLoc[0][0]=temp10; curLoc[0][1]=temp11+0.1f; curLoc[1][0]=temp00; curLoc[1][1]=temp01; curLoc[2][0]=temp10; curLoc[2][1]=temp11; break; case3: curLoc[3][0]=temp20+0.1f; curLoc[3][1]=temp21; break; } turn[2]=(turn[2]+1)%4; break; case3://Z字形 switch(turn[3]) { case0: curLoc[0][0]=temp10+0.1f; curLoc[0][1]=temp11+0.1f; curLoc[2][0]=temp10+0.1f; curLoc[2][1]=temp11; curLoc[3][0]=temp20; curLoc[3][1]=temp21; break; case1: curLoc[0][0]=temp10-0.1f; curLoc[0][1]=temp11; curLoc[2][0]=temp30; curLoc[2][1]=temp31; curLoc[3][0]=temp30+0.1f; curLoc[3][1]=temp31; break; } turn[3]=(turn[3]+1)%2; break; case4://反Z字形 switch(turn[4]) { case0: curLoc[0][0]=temp00-0.1f; curLoc[0][1]=temp01+0.1f; curLoc[1][0]=temp00-0.1f; curLoc[1][1]=temp01; curLoc[2][0]=temp00; curLoc[2][1]=temp01; curLoc[3][0]=temp00; curLoc[3][1]=temp01-0.1f; break; case1: curLoc[0][0]=temp20; curLoc[0][1]=temp21; curLoc[1][0]=temp20+0.1f; curLoc[1][1]=temp21; curLoc[2][0]=temp10; curLoc[2][1]=temp11-0.1f; break; } turn[4]=(turn[4]+1)%2; break; case5://L字形 switch(turn[5]) { case0: curLoc[0][0]=temp10; curLoc[0][1]=temp11; curLoc[1][0]=temp10+0.1f; curLoc[1][1]=temp11; curLoc[2][0]=temp10+0.2f; curLoc[2][1]=temp11; curLoc[3][0]=temp20; curLoc[3][1]=temp21; break; case1: curLoc[0][0]=temp00; curLoc[0][1]=temp01+0.1f; curLoc[1][0]=temp10; curLoc[1][1]=temp11+0.1f; curLoc[2][0]=temp10; curLoc[2][1]=temp11; curLoc[3][0]=temp10; curLoc[3][1]=temp11-0.1f; break; case2: curLoc[0][0]=temp20+0.1f; curLoc[0][1]=temp21; curLoc[1][0]=temp20-0.1f; curLoc[1][1]=temp21-0.1f; curLoc[2][0]=temp20; curLoc[2][1]=temp21-0.1f; curLoc[3][0]=temp20+0.1f; curLoc[3][1]=temp21-0.1f; break; case3: curLoc[0][0]=temp10; curLoc[0][1]=temp11+0.2f; curLoc[1][0]=temp10; curLoc[1][1]=temp11+0.1f; curLoc[2][0]=temp10; curLoc[2][1]=temp11; curLoc[3][0]=temp20; curLoc[3][1]=temp21; break; } turn[5]=(turn[5]+1)%4; break; case6://反L字形 switch(turn[6]) { case0: curLoc[0][0]=temp20-0.1f; curLoc[0][1]=temp21+0.1f; curLoc[1][0]=temp20-0.1f; curLoc[1][1]=temp21; break; case1: curLoc[0][0]=temp00+0.1f; curLoc[0][1]=temp01+0.1f; curLoc[1][0]=temp30; curLoc[1][1]=temp31+0.2f; curLoc[2][0]=temp00+0.1f; curLoc[2][1]=temp01; curLoc[3][0]=temp20; curLoc[3][1]=temp21; break; case2: curLoc[0][0]=temp00-0.1f; curLoc[0][1]=temp01-0.1f; curLoc[1][0]=temp20; curLoc[1][1]=temp21; curLoc[2][0]=temp20+0.1f; curLoc[2][1]=temp21; curLoc[3][0]=temp30+0.1f; curLoc[3][1]=temp31; break; case3: curLoc[0][0]=temp20; curLoc[0][1]=temp21+0.1f; curLoc[1][0]=temp20; curLoc[1][1]=temp21; curLoc[2][0]=temp30-0.1f; curLoc[2][1]=temp31; curLoc[3][0]=temp30; curLoc[3][1]=temp31; break; } turn[6]=(turn[6]+1)%4; break; } //如果旋轉(zhuǎn)非法(即旋轉(zhuǎn)時碰到墻壁了),則要恢復(fù)原來的狀態(tài) intret; ret=CheckConflict(); if(ret==1) { curLoc[0][0]=temp00; curLoc[0][1]=temp01; curLoc[1][0]=temp10; curLoc[1][1]=temp11; curLoc[2][0]=temp20; curLoc[2][1]=temp21; curLoc[3][0]=temp30; curLoc[3][1]=temp31; }}/*消除滿格的一行,在每次over被修改為true的時候都要檢查一遍算法思想是從第0行開始依次判斷,如果empty為true則將下面的向上,并不是判斷一次就移動所有的,而是只移動最近的,將空出來的那一行的empty標(biāo)記為true*/voidDelete(int*empty){ inti,j; intpos; while(1) //將上面非空的行填補(bǔ)到下面的空行中 { i=1; while(i<20&&empty[i]==0) //為空或者滿,都需要將上面的行移下來填充 { i++; } if(i>=20) break; j=i+1; while(j<20&&empty[j]==-1) j++; if(j>=20) break; if(j<20&&empty[j]!=-1) { for(pos=0;pos<20;pos++) BLOCK[i][pos]=BLOCK[j][pos]; empty[i]=empty[j]; empty[j]=-1; } } for(i=1;i<20;i++) if(empty[i]!=0) { for(j=0;j<20;j++) BLOCK[i][j]=0; }}/**1、判斷新生成的圖形是否和原來的圖形有沖突,有則不能更改,這個地方比較不好實(shí)現(xiàn)*2、判斷是否有滿格的行,有則調(diào)用Delete函數(shù)去掉*3、這里似乎還要加上判斷是否到大頂部,如果到達(dá)頂部則游戲結(jié)束(可采用監(jiān)視方框最上*面一行之上那行里面有沒有方格,如果有的話則游戲結(jié)束)*結(jié)束之后就可以把當(dāng)前方塊存入BLOCK中*empty表示一行中方塊的數(shù)目,-1表示為空行,0表示部分為空,1表示滿行*/voidCheckDelete()//目前這個函數(shù)還只是實(shí)現(xiàn)了一個方塊到達(dá)終點(diǎn)之后是否有能夠被刪除的行{ inti,j; intempty[SIZE]; boolis_needed=false; intcount; for(i=0;i<SIZE;i++) empty[i]=-1; for(i=0;i<4;i++) { doublex=(curLoc[i][0]+1)*10+0.5; //此處無需注意取值,因?yàn)閏heckConflict已經(jīng)解決 doubley=(curLoc[i][1]+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(BLOCK[i][j]==1) count++; if(count==20) { empty[i]=1; //若滿格,則可以刪除,置為true score++; //此處計(jì)分 is_needed=true; } elseif(count>0&&count<20) { empty[i]=0; } } if(is_needed==true)//如果有滿行則去刪除,否則免之 Delete(empty);}intCheckConflict(intlef_rig){ inti; for(i=0;i<4;i++) { doublex=(curLoc[i][0]+1)*10; //注意取值!!! doubley=(curLoc[i][1]+1)*10+0.5; //y方向無需注意 x=x>0?(x+0.5):(x-0.5); if(lef_rig==1) { inttmpx=(int)x; if(tmpx>19||tmpx<0) break; } if(BLOCK[(int)y][(int)x]==1)//判斷是否發(fā)生沖突 { break; } } if(i<4) return1; return0;}/*關(guān)鍵部分在這里,主要是要判斷方塊下一次的移動是否合法,本程序通過對b數(shù)組所存儲的下標(biāo)是否在BLOCK數(shù)組中已經(jīng)為1來判斷,這樣,只需要在BLOCK的最外層加一圈1,就不用通過原來的方式來判斷方塊是否越界*/voidkey(unsignedchark,intx,inty){ inti,ret; if(over==false) { if(k==UP)//此處需要改成調(diào)用變換圖形樣式的函數(shù) { Change(); } elseif(k==DOWN)//后續(xù)還要修改,移動到底部過了一段時間之后就不能左右移動了 { for(i=0;i<4;i++)//需繼續(xù)添加以1和-1作為哨兵 { curLoc[i][1]-=0.1f; } ret=CheckConflict(); if(ret==1)//發(fā)生沖突,則將修改復(fù)原 { for(i=0;i<4;i++) curLoc[i][1]+=0.1f; over=true;//并且可以生成下一個方塊了 } } elseif(k==RIGHT) { for(i=0;i<4;i++) curLoc[i][0]+=0.1f; ret=CheckConflict(1); if(ret==1)//發(fā)生沖突,則將修改復(fù)原 { for(i=0;i<4;i++) curLoc[i][0]-=0.1f; } } elseif(k==LEFT) { for(i=0;i<4;i++) curLoc[i][0]-=0.1f; ret=CheckConflict(1); if(ret==1)//發(fā)生沖突,則將修改復(fù)原 { for(i=0;i<4;i++) curLoc[i][0]+=0.1f; } } } if(over==true) CheckDelete(); glutPostRedisplay();//調(diào)用這個函數(shù)可以重新繪圖,每次相應(yīng)消息之后,所有全部重繪}/*讓方塊定時下降*/voiddown(intid){ inti,ret; if(over!=true) { for(i=0;i<4;i++)//需繼續(xù)添加以1和-1作為哨兵 { curLoc[i][1]-=0.1f; } ret=CheckConflict(); if(ret==1)//發(fā)生沖突,則將修改復(fù)原 { for(i=0;i<4;i++) curLoc[i][1]+=0.1f; if(curLoc[0][1]>=b[currentBlock][0][1]) { cout<<"Gameover,yourscoreis:"<<score*100<<endl; exit(1); } over=true;//并且可以生成下一個方塊了 } } if(over==true) CheckDelete(); glutPostRedisplay(); glutTimerFunc(1000,down,1);}//作圖函數(shù),要修改,利用BLOCK數(shù)組繪圖voidmyDisplay1(){ inti,j; glClear(GL_COLOR_BUFFER_BIT); //不能使用深度測試,否則畫出來的圖形很亂 for(i=0;i<20;i++) { for(j=0;j<20;j++) { if(BLOCK[i][j]==1) { glColor3f(0.0f,1.0f,0.0f); //用藍(lán)色畫圖 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(); } } }
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 堆假山合同范例
- 瀝青清包工合同范例
- 豬買賣合同范例
- 2025勞動合同續(xù)簽期限
- 照顧獨(dú)居老人合同范例
- 工程營銷合同范例
- 住宿 會議 用餐合同范例
- 工地木材合同范例
- 肯德基假期兼職合同范例
- 溝渠維修合同范例
- 9歲兒童智商測試題
- 大鎖孫天宇小品《時間都去哪了》臺詞劇本完整版-一年一度喜劇大賽
- 消防立管永臨結(jié)合施工方案
- 人教版八年級物理下冊 實(shí)驗(yàn)題02 壓力壓強(qiáng)實(shí)驗(yàn)(含答案詳解)
- 抖音快手短視頻創(chuàng)業(yè)項(xiàng)目融資商業(yè)策劃書
- 滬教版英語八年級上冊知識點(diǎn)歸納匯總
- 裝飾裝修工程售后服務(wù)具體措施
- 軟件設(shè)計(jì)說明書通用模板
- 酒店治安安全培訓(xùn)
- 糖皮質(zhì)激素類藥物臨床應(yīng)用指導(dǎo)原則(2023年)
- 我的家鄉(xiāng)-東營
評論
0/150
提交評論