OpenGL實現(xiàn)俄羅斯方塊源代碼.doc
《OpenGL實現(xiàn)俄羅斯方塊源代碼.doc》由會員分享,可在線閱讀,更多相關(guān)《OpenGL實現(xiàn)俄羅斯方塊源代碼.doc(15頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、 OpenGL實現(xiàn)俄羅斯方塊 一、 設(shè)計思路 本程序采用以C++為基礎(chǔ)并利用OpenGl庫函數(shù)的方式實現(xiàn)俄羅斯方塊程序,實現(xiàn)俄羅斯方塊中正方形,T形,L形,反L形,直線型,Z字形,反Z字形七種形狀的變換操作,七種形狀的坐標(biāo)被存儲在一個三維數(shù)組中,每次隨機選擇一個形狀生成并下落,在下落過程中監(jiān)聽鍵盤事件。 二、 詳細設(shè)計說明 本程序中主要的函數(shù)及其作用說明如下: down:定時下落函數(shù),由glutTimerFunc(1000,down,1);函數(shù)設(shè)置每隔1000毫秒即調(diào)用一次該函數(shù),在函數(shù)中將方塊的所有縱坐標(biāo)減一個單位。 key: 鍵盤事件監(jiān)聽函數(shù),當(dāng)鍵盤上有按鍵被觸發(fā)的
2、時候即調(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ù),主要是通過計算變換后的圖形與之前圖形的坐標(biāo)關(guān)系來實現(xiàn)。
三、 源代碼
#include 3、dlib.h>
#include 4、P鍵進行變換應(yīng)該怎么處理
*本程序最初設(shè)計并不考慮這個問題,一開始即畫出方塊的各個部分,以后再考慮完善的事情
*另外,記錄坐標(biāo)的順序為從左至右,從上至下
*/
GLfloat b[][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 5、}},//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字形
};
GLfloa 6、t curLoc[5][3];
GLint currentBlock=2;//記錄當(dāng)前正在下落的是第幾種方塊,順序如上面所示
GLint turn[7]={0};//應(yīng)該變換成第幾種形態(tài)了
GLfloat xd=0.0f,yd=0.0f;
/*
這里定義的over是用來判斷方塊是否到達了不能再往下降的地方,到了則置
其為true,否則就修改為false。
其中有這樣幾種情況需要修改over:
1、重新生成了一個方塊,修改over=false
2、方塊到大底部,修改over=true
*/
bool over=false;
//記錄游戲是否結(jié)束
bool end 7、=false;
int score=0;
//設(shè)置一個鎖,在下降操作時不允許變換,在變換時不允許下降操作,否則將會產(chǎn)生資源競爭
//int lock=1;
/*
定義一個20*20的矩陣來記錄當(dāng)前整個畫面中各個小格子的情況,可用來消除滿格行
矩陣的存儲順序為從左到右,從下到上,包含下標(biāo)0
BLOCK[i][j]中i對應(yīng)的是縱坐標(biāo),j對應(yīng)的是橫坐標(biāo)(這個有點痛苦),但是在消去滿格
的時候還是不變,只是在用b數(shù)組給其賦值時需要反過來
*/
GLint BLOCK[SIZE][SIZE];
void down(int id);
void InitBLOCK() 8、;
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++) //函數(shù)調(diào)用的順序?qū)﹀e誤有一定的影響
for(j=0;j<2;j++)
{
cout<< 9、curLoc[i][j]<<" ";
}
cout< 10、hange()//將圖形做變換,采用順時針旋轉(zhuǎn)的規(guī)律(下面的工作即是填入坐標(biāo))
{
GLfloat temp00=curLoc[0][0];
GLfloat temp01=curLoc[0][1];
GLfloat temp10=curLoc[1][0];
GLfloat temp11=curLoc[1][1];
GLfloat temp20=curLoc[2][0];
GLfloat temp21=curLoc[2][1];
GLfloat temp30=curLoc[3][0];
GLfloat temp31=curLoc[3][1];
switch( 11、currentBlock)
{
case 0://長條
switch(turn[0])
{
case 0:
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;
case 1:
curLoc[0][0]=temp10;
curLoc[0][1]=temp 12、11+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;
case 1://正方形
break;
case 2://T字形
//cout<<"turn[2]="< 13、[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;
case 1:
curLoc[0][0]=temp10-0.1f;
curLoc[0][1]=temp11;
break;
case 2:
curLoc[0][0]=temp10;
curLoc[0][1]=temp11+0.1f;
14、curLoc[1][0]=temp00;
curLoc[1][1]=temp01;
curLoc[2][0]=temp10;
curLoc[2][1]=temp11;
break;
case 3:
curLoc[3][0]=temp20+0.1f;
curLoc[3][1]=temp21;
break;
}
turn[2]=(turn[2]+1)%4;
break;
case 3://Z字形
switch(turn[3])
{
case 0:
curLoc[0][0]=te 15、mp10+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;
case 1:
curLoc[0][0]=temp10-0.1f;
curLoc[0][1]=temp11;
curLoc[2][0]=temp30;
curLoc[2][1]=temp31;
curLoc[3][0]=temp30+0.1 16、f;
curLoc[3][1]=temp31;
break;
}
turn[3]=(turn[3]+1)%2;
break;
case 4://反Z字形
switch(turn[4])
{
case 0:
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;
17、 curLoc[3][0]=temp00;
curLoc[3][1]=temp01-0.1f;
break;
case 1:
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;
case 5://L 18、字形
switch(turn[5])
{
case 0:
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;
case 1:
curLoc[0][0]=temp00;
19、 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;
case 2:
curLoc[0][0]=temp20+0.1f;
curLoc[0][1]=temp21;
curLoc[1][0]=temp20-0.1f;
20、 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;
case 3:
curLoc[0][0]=temp10;
curLoc[0][1]=temp11+0.2f;
curLoc[1][0]=temp10;
curLoc[1][1]=temp11+0.1f;
curLoc[2][0]=temp10;
21、 curLoc[2][1]=temp11;
curLoc[3][0]=temp20;
curLoc[3][1]=temp21;
break;
}
turn[5]=(turn[5]+1)%4;
break;
case 6://反L字形
switch(turn[6])
{
case 0:
curLoc[0][0]=temp20-0.1f;
curLoc[0][1]=temp21+0.1f;
curLoc[1][0]=temp20-0.1f;
curLoc[1][1]=temp21;
b 22、reak;
case 1:
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;
case 2:
curLoc[0][0]=temp00-0.1f;
curLoc[ 23、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;
case 3:
curLoc[0][0]=temp20;
curLoc[0][1]=temp21+0.1f;
curLoc[1][0]=temp20;
curLoc[1][1]=te 24、mp21;
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)
int ret;
ret=CheckConflict();
if(ret == 1)
{
curLoc[0][0]=temp00;
curLoc[0][1]=temp01;
25、
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
*/
void Delete(int *emp 26、ty)
{
int i,j;
int pos;
while(1) //將上面非空的行填補到下面的空行中
{
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++)
27、 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、判斷新生成的圖形是否和原來的圖形有沖突,有則不能更改,這個地方比較不好實現(xiàn)
*2、判斷是否有滿格的行,有則調(diào)用Delete函數(shù)去掉
*3、這里似乎還要加上判斷是否到大頂部,如果到達頂部則游戲結(jié)束(可采用監(jiān)視方框最上
* 28、面一行之上那行里面有沒有方格,如果有的話則游戲結(jié)束)
*結(jié)束之后就可以把當(dāng)前方塊存入BLOCK中
*empty表示一行中方塊的數(shù)目,-1表示為空行,0表示部分為空,1表示滿行
*/
void CheckDelete()//目前這個函數(shù)還只是實現(xiàn)了一個方塊到達終點之后是否有能夠被刪除的行
{
int i,j;
int empty[SIZE];
bool is_needed=false;
int count;
for(i=0;i 29、][0]+1)*10+0.5; //此處無需注意取值,因為checkConflict已經(jīng)解決
double y=(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++; //此處計分
is_n 30、eeded=true;
}
else if(count > 0&&count < 20)
{
empty[i]=0;
}
}
if(is_needed==true)//如果有滿行則去刪除,否則免之
Delete(empty);
}
int CheckConflict(int lef_rig)
{
int i;
for(i=0;i<4;i++)
{
double x=(curLoc[i][0]+1)*10; //注意取值!!!
double y=(curLoc[i][1]+1)*10+0.5; //y方向無需注意
31、 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) //判斷是否發(fā)生沖突
{
break;
}
}
if(i < 4)
return 1;
return 0;
}
/*
關(guān)鍵部分在這里,主要是要判斷方塊下一次的移動是否合法,
本程序通過對b數(shù)組所存儲的下標(biāo)是否在BLOCK數(shù)組中已經(jīng)為1
來判斷,這樣,只需要在BLOCK 32、的最外層加一圈1,就不用通過
原來的方式來判斷方塊是否越界
*/
void key(unsigned char k,int x,int y)
{
int i,ret;
if(over == false)
{
if(k==UP)//此處需要改成調(diào)用變換圖形樣式的函數(shù)
{
Change();
}
else if(k==DOWN)//后續(xù)還要修改,移動到底部過了一段時間之后就不能左右移動了
{
for(i=0;i<4;i++)//需繼續(xù)添加以1和-1作為哨兵
{
curLoc[i][1]-=0.1f;
} 33、
ret=CheckConflict();
if(ret == 1)//發(fā)生沖突,則將修改復(fù)原
{
for(i=0;i<4;i++)
curLoc[i][1]+=0.1f;
over=true;//并且可以生成下一個方塊了
}
}
else if(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 34、<4;i++)
curLoc[i][0]-=0.1f;
}
}
else if(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)用這 35、個函數(shù)可以重新繪圖,每次相應(yīng)消息之后,所有全部重繪
}
/*
讓方塊定時下降
*/
void down(int id)
{
int i,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] > 36、= b[currentBlock][0][1])
{
cout<<"Game over,your score is:"< 37、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); //用藍色畫圖
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);
g 38、lColor3f(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= 39、0;i<4;i++)
{
glColor3f(0.0f,1.0f,0.0f); //用藍色畫圖
glRectf(curLoc[i][0],curLoc[i][1],curLoc[i][0]+0.1f,curLoc[i][1]+0.1f);
glLineWidth(2.0f);
glBegin(GL_LINE_LOOP);
glColor3f(0.0f,0.0f,0.0f);
glVertex2f(curLoc[i][0],curLoc[i][1]);
glVertex2f(curLoc[i][0]+0.1f,curLoc[i][1 40、]);
glVertex2f(curLoc[i][0]+0.1f,curLoc[i][1]+0.1f);
glVertex2f(curLoc[i][0],curLoc[i][1]+0.1f);
glEnd();
glFlush();
}
}
glutSwapBuffers();
}
/*
* 隨機生成方塊,原理即生成一個7以內(nèi)的隨機數(shù),
* 對應(yīng)的二維數(shù)組即為下一個產(chǎn)生的方塊
*/
void CreateBlocks()
{
int i,j;
myDisplay1();
if(over)
{
srand(t 41、ime(NULL));
currentBlock=rand()%7;
for(i=0;i<7;i++) //關(guān)鍵之處,每次創(chuàng)建一個新的方塊后要將變形的記錄清空
turn[i]=0;
for(i=0;i<4;i++)
for(j=0;j<2;j++)
{
curLoc[i][j]=b[currentBlock][i][j];
}
over=false;
glutPostRedisplay();
}
}
void main(int argc ,char **argv)
{
glutInit(&argc,argv 42、);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
glutInitWindowPosition(400,100);
glutInitWindowSize(600,600);
InitBLOCK();
glutCreateWindow("俄羅斯方塊 author:parkfang");
glutDisplayFunc(&CreateBlocks);
glutTimerFunc(1000,down,1);
glutKeyboardFunc(key);
glClearColor(1.0f,1.0f,1.0f,1.0f);//用白色清除屏幕
glutMainLoop();
}
- 溫馨提示:
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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025《增值稅法》高質(zhì)量發(fā)展的增值稅制度規(guī)范增值稅的征收和繳納
- 深入學(xué)習(xí)《中華人民共和國科學(xué)技術(shù)普及法》推進實現(xiàn)高水平科技自立自強推動經(jīng)濟發(fā)展和社會進步
- 激揚正氣淬煉本色踐行使命廉潔從政黨課
- 加強廉潔文化建設(shè)夯實廉政思想根基培育風(fēng)清氣正的政治生態(tài)
- 深入學(xué)習(xí)2024《突發(fā)事件應(yīng)對法》全文提高突發(fā)事件預(yù)防和應(yīng)對能力規(guī)范突發(fā)事件應(yīng)對活動保護人民生命財產(chǎn)安全
- 2023年四年級數(shù)學(xué)上冊第一輪單元滾動復(fù)習(xí)第10天平行四邊形和梯形作業(yè)課件新人教版
- 2023年四年級數(shù)學(xué)上冊第14單元階段性綜合復(fù)習(xí)作業(yè)課件新人教版
- 2023年四年級數(shù)學(xué)上冊易錯清單十五課件新人教版
- 2023年四年級數(shù)學(xué)上冊易錯清單七課件西師大版
- 2023年五年級數(shù)學(xué)下冊易錯清單六作業(yè)課件北師大版
- 2023年五年級數(shù)學(xué)下冊易錯清單二作業(yè)課件北師大版
- 2023年五年級數(shù)學(xué)下冊四分?jǐn)?shù)的意義和性質(zhì)第10課時異分母分?jǐn)?shù)的大小比較作業(yè)課件蘇教版
- 2023年五年級數(shù)學(xué)下冊周周練四作業(yè)課件北師大版
- 2023年五年級數(shù)學(xué)下冊六折線統(tǒng)計圖單元復(fù)習(xí)卡作業(yè)課件西師大版
- 2023年四年級數(shù)學(xué)上冊6除數(shù)是兩位數(shù)的除法單元易錯集錦一作業(yè)課件新人教版